При разработке и доработке конфигураций 1С часто возникает задача подстановки даты по умолчанию при создании новых документов или заполнении реквизитов. Если пользователь работает «задним числом» или ведет ввод данных за определенный период, использование системного времени операционной системы (которое возвращает стандартная функция ТекущаяДата()) приводит к ошибкам ввода. Разберем, как получить и настроить рабочую дату сеанса программно, какие существуют ограничения контекста и как решается эта задача в современных конфигурациях.
В платформе 1С:Предприятие для работы с датой сеанса предусмотрено специальное свойство. Распространенная ошибка разработчиков — попытка вызвать его как функцию со скобками (например, РабочаяДата()). На самом деле это свойство (атрибут) глобального контекста.
Проанализируем описание данного свойства из синтакс-помощника:
Дата.ИспользованиеРабочейДаты имеет значение Назначать).Посмотрим на пример получения и изменения рабочей даты в коде обычного приложения:
// Получение текущей установленной рабочей даты
ТекущаяРабочаяДата = РабочаяДата;
// Установка новой рабочей даты (если разрешено изменение)
Если ИспользованиеРабочейДаты = ИспользованиеРабочейДаты.Назначать Тогда
РабочаяДата = '20231231';
КонецЕсли;
Важное ограничение: Свойство РабочаяДата отсутствует в тонком клиенте, веб-клиенте и на стороне сервера. Попытка обратиться к нему в серверном модуле или в контексте управляемой формы приведет к ошибке компиляции «Переменная не определена».
Выясним причину, почему функция ТекущаяДата() часто приводит к расхождениям во времени, особенно в клиент-серверном варианте работы базы:
ТекущаяДата() возвращает время операционной системы того физического устройства, на котором выполняется код. Вызов на клиенте возвращает системные часы клиентского ПК, а вызов на сервере — системные часы сервера. Если между ними есть рассинхронизация или они находятся в разных часовых поясах, значения будут отличаться.ТекущаяДатаСеанса() возвращает платформенное время с учетом часового пояса сеанса пользователя независимо от того, где выполняется код — на клиенте или на сервере.Посмотрим на пример безопасного получения актуального системного времени сеанса:
// Корректное получение времени сеанса в управляемом приложении
АктуальнаяДата = ТекущаяДатаСеанса();
В управляемом приложении концепция встроенной платформенной рабочей даты была упразднена. В типовых конфигурациях на базе Библиотеки стандартных подсистем (БСП) этот механизм перенесен на прикладной уровень.
Рассмотрим, как устроена работа с пользовательской датой в управляемых формах:
ХранилищеОбщихНастроек или в специальном служебном регистре.ОбработкаЗаполнения модуля менеджера или объекта) дата документа инициализируется сохраненным значением.Если требуется реализовать механизм рабочей даты, независимый от системных часов и доступный во всех программных контекстах (включая серверный код), разберем два основных подхода.
Способ 1. Использование параметров сеанса
Создадим параметр сеанса РабочаяДатаСеанса с типом Дата. Инициализируем его при старте программы в модуле сеанса в обработчике УстановкаПараметровСеанса:
Процедура УстановкаПараметровСеанса(ТребуемыеПараметры)
Если ТребуемыеПараметры = Неопределено
Или ТребуемыеПараметры.Найти("РабочаяДатаСеанса") <> Неопределено Тогда
// Считываем сохраненное значение из настроек пользователя
СохраненнаяДата = ХранилищеОбщихНастроек.Загрузить("НастройкиПользователя", "РабочаяДата");
Если ЗначениеЗаполнено(СохраненнаяДата) Тогда
ПараметрыСеанса.РабочаяДатаСеанса = СохраненнаяДата;
Иначе
ПараметрыСеанса.РабочаяДатаСеанса = ТекущаяДатаСеанса();
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Теперь значение параметра ПараметрыСеанса.РабочаяДатаСеанса доступно на сервере для быстрой подстановки в документы без повторных обращений к базе данных.
Способ 2. Чтение и запись через ХранилищеОбщихНастроек
Рассмотрим пример сохранения и чтения даты непосредственно через хранилище настроек:
// Сохранение рабочей даты пользователя
ХранилищеОбщихНастроек.Сохранить("ПараметрыРаботы", "РабочаяДата", ВыбраннаяПользователемДата);
// Чтение рабочей даты при создании документа
ДатаДляЗаполнения = ХранилищеОбщихНастроек.Загрузить("ПараметрыРаботы", "РабочаяДата");
Если Не ЗначениеЗаполнено(ДатаДляЗаполнения) Тогда
ДатаДляЗаполнения = ТекущаяДатаСеанса();
КонецЕсли;
Таким образом, для толстого клиента в обычных формах применяется свойство РабочаяДата, а для современных управляемых приложений создается прикладной механизм на базе параметров сеанса или хранилища настроек.