Как в 1С получить дату компьютера пользователя, а не дату сервера?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Торговля и дистрибуция
← На главную

При разработке в 1С часто возникает задача получить текущую дату. Обычно для этого используется функция ТекущаяДата(). Однако многие разработчики сталкиваются с ситуацией, когда эта функция, вызванная в серверном общем модуле, возвращает не время на компьютере пользователя, а системное время сервера 1С. Разберемся, почему так происходит и как получить именно локальную дату пользователя.

Проблема заключается в клиент-серверной архитектуре платформы 1С. Код в 1С может выполняться в разных контекстах: на клиенте (компьютере пользователя) и на сервере. Функция ТекущаяДата() всегда возвращает системную дату той машины, на которой она в данный момент выполняется.

Почему ТекущаяДата() возвращает разное время?

Чтобы понять корень проблемы, проанализируем контексты выполнения кода в 1С:

Таким образом, когда вы в серверном общем модуле пытаетесь получить дату, вы по определению работаете в серверном контексте, и платформа физически не может напрямую обратиться к компьютеру пользователя для получения его локального времени. Это сделано в том числе из соображений безопасности и для обеспечения целостности данных.

Основной способ решения: передача даты с клиента на сервер

Единственный правильный и надежный способ получить на сервере локальную дату пользователя — это сначала получить ее на клиенте, а затем передать на сервер в качестве параметра серверной процедуры или функции. Посмотрим на этот процесс по шагам.

  1. Получение даты на клиенте. В клиентской процедуре (например, в обработчике нажатия кнопки на форме) мы получаем текущую дату. В этот момент код выполняется на машине пользователя.
  2. Вызов серверной процедуры. Из этой же клиентской процедуры мы вызываем серверную процедуру.
  3. Передача даты как параметра. При вызове мы передаем полученную на клиенте дату в качестве аргумента (параметра) в нашу серверную процедуру.

Внутри серверной процедуры эта дата будет доступна через переменную, объявленную в ее параметрах, и с ней можно будет работать дальше.

Практический пример для управляемых форм

Рассмотрим, как это реализуется в режиме управляемых форм. Допустим, у нас есть форма, на которой размещена кнопка. Нам нужно при нажатии на эту кнопку выполнить на сервере некую операцию, используя точное время с компьютера пользователя.

Для этого в модуле формы создадим обработчик нажатия кнопки и серверную процедуру.


&НаКлиенте
Процедура ВыполнитьСДатойКлиента(Команда)
    // Шаг 1: Получаем текущую системную дату с компьютера, где запущен клиент 1С
    ДатаКлиента = ТекущаяДата();
    
    // Выведем сообщение, чтобы убедиться, что дата получена верно
    Сообщить("Сейчас на компьютере пользователя: " + Формат(ДатаКлиента, "ДЛФ=DT"));
    
    // Шаг 2 и 3: Вызываем серверную процедуру, передавая дату как параметр
    ОбработатьДанныеНаСервере(ДатаКлиента);
КонецПроцедуры

&НаСервере
Процедура ОбработатьДанныеНаСервере(ДатаСКлиента)
    // Эта процедура выполняется уже на сервере 1С
    // Параметр "ДатаСКлиента" содержит значение, которое мы получили на клиенте
    ДатаСервера = ТекущаяДата();
    
    Сообщить("На сервере получена дата клиента: " + Формат(ДатаСКлиента, "ДЛФ=DT"));
    Сообщить("Для сравнения, дата на сервере сейчас: " + Формат(ДатаСервера, "ДЛФ=DT"));
    
    // ... здесь можно выполнять дальнейшие действия с датой клиента ...
    // Например, записать ее в какой-нибудь нетиповой реквизит документа
    // или использовать в алгоритме расчета.
КонецПроцедуры

При выполнении этого кода мы увидим, что ДатаКлиента соответствует времени на локальной машине, а ДатаСервера — времени на сервере, и эти значения могут отличаться.

А как быть с обычными формами (например, в УТ 10.3)?

Для конфигураций на обычных формах (неуправляемых) логика остается абсолютно такой же, меняется лишь синтаксис и способ организации кода. В обычных формах нет директив компиляции &НаКлиенте и &НаСервере. Контекст выполнения определяется местоположением кода:

Чтобы передать дату с клиента на сервер, нужно из процедуры в модуле формы вызвать экспортную процедуру из серверного общего модуля.

Пример для обычных форм:

1. В модуле формы документа или обработки создаем обработчик нажатия кнопки:


// Код в модуле формы (выполняется на клиенте)
Процедура КнопкаВыполнитьНажатие(Кнопка)
    // Получаем дату компьютера пользователя
    ДатаКлиента = ТекущаяДата();
    Сообщить("Текущая дата на клиенте: " + ДатаКлиента);
    
    // Вызываем экспортную процедуру из общего серверного модуля
    // и передаем в нее полученную дату
    ОбщийМодульСерверный.ВыполнитьОперациюСДатой(ДатаКлиента);
КонецПроцедуры

2. В общем модуле с установленным флагом "Сервер" (назовем его, например, ОбщийМодульСерверный) создаем принимающую процедуру:


// Код в общем модуле "ОбщийМодульСерверный" (установлен флаг "Сервер")
// Процедура должна быть экспортной, чтобы ее можно было вызвать из модуля формы
Процедура ВыполнитьОперациюСДатой(ДатаСКлиента) Экспорт
    // Этот код выполняется на сервере
    ДатаНаСервере = ТекущаяДата();
    Сообщить("На сервер пришла дата от клиента: " + ДатаСКлиента);
    Сообщить("Дата на самом сервере: " + ДатаНаСервере);
КонецПроцедуры

Таким образом, несмотря на разницу в синтаксисе, принцип остается неизменным: получить на клиенте, передать на сервер.

Важные моменты и сценарии, где это не сработает

Важно понимать ограничения данного подхода. Получить дату клиента можно только тогда, когда есть сам "клиент", то есть интерактивный сеанс пользователя.

В заключение, запомним простое правило: если вам в серверном коде нужна дата с компьютера пользователя, ее всегда нужно сначала получить в клиентском коде и передать на сервер в качестве параметра. Прямой доступ к локальному времени пользователя из серверного модуля невозможен по архитектурным соображениям платформы "1С:Предприятие".

← На главную