Время на сервере 1С: какой функцией его брать и почему часы расходятся

· 9 мин

Содержание

Чтобы получить время сервера 1С, вызовите ТекущаяДата() в серверной процедуре (&НаСервере или &НаСервереБезКонтекста): она вернёт часы операционной системы того компьютера, где работает рабочий процесс 1С. Для дат документов и отборов правильнее брать ТекущаяДатаСеанса() — это время сервера, пересчитанное в часовой пояс сеанса.

Типичная ситуация: бухгалтер в Новосибирске проводит документ, а в журнале стоит московское время. Или кассир видит, что чек «пробит в будущем» на две минуты. Оба случая — про то, чьи часы спрашивает код и в каком поясе их показывает. Всё, что описано дальше, относится к платформе 8.3 и работает в любой конфигурации — и в клиент-серверном, и в файловом варианте.

Клиентское и серверное время: чьи часы видит код

В 1С одновременно идут как минимум двое часов: на компьютере пользователя и на сервере. Если база через веб-публикацию — добавляются часы веб-сервера. А у СУБД свои часы, и они тоже могут не совпадать.

Какой компьютер считается «сервером», зависит от варианта работы:

Вариант работыГде выполняется серверный кодЧьё время вернёт ТекущаяДата() на сервере
Клиент-серверный (кластер 1С)Рабочий процесс rphostКомпьютер с рабочим процессом
Файловый, тонкий клиент напрямуюТот же компьютер, что и клиентКомпьютер пользователя
Файловый через веб-серверМодуль расширения веб-сервераКомпьютер веб-сервера
Кластер из нескольких рабочих серверовЛюбой из рабочих серверовТот сервер, куда попал вызов

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

Сама дата в 1С — это просто число и время, без часового пояса. Значение 15.03 10:00:00 не знает, московское оно или иркутское. Поэтому решение «какое время писать» принимает код, а не платформа.

Функции для получения времени сервера в коде 1С

На сервере доступны три функции, и они отвечают на разные вопросы.

  • 🕐 ТекущаяДата() — местное время компьютера, на котором выполняется код. Часовой пояс сеанса не учитывает.
  • 🌍 ТекущаяДатаСеанса() — время сервера, переведённое в часовой пояс сеанса. Подходит для дат документов, отборов «за сегодня», сроков.
  • 🧭 ТекущаяУниверсальнаяДата() — время UTC по часам сервера. Удобно для журналов обмена, меток синхронизации и сравнения событий из разных регионов.

Есть и ТекущаяУниверсальнаяДатаВМиллисекундах() — возвращает число миллисекунд. Её используют для замера длительности операций, а не для записи дат в документы.

Пример: вывести время клиента и сервера рядом

Код для управляемой формы. Команда на клиенте вызывает серверную функцию и выводит всё в окно сообщений:

&НаКлиенте
Процедура ПоказатьВремя(Команда)

    ДанныеСервера = ВремяСервера();
    ФорматДаты = "ДФ='dd.MM.yyyy HH:mm:ss'";

    Сообщить("Клиент, ТекущаяДата(): " + Формат(ТекущаяДата(), ФорматДаты));
    Сообщить("Сервер, ТекущаяДата(): " + Формат(ДанныеСервера.ДатаСервера, ФорматДаты));
    Сообщить("Сервер, дата сеанса: " + Формат(ДанныеСервера.ДатаСеанса, ФорматДаты));
    Сообщить("Сервер, UTC: " + Формат(ДанныеСервера.ДатаUTC, ФорматДаты));
    Сообщить("Пояс компьютера сервера: " + ДанныеСервера.ПоясСервера);
    Сообщить("Пояс сеанса: " + ДанныеСервера.ПоясСеанса);
    Сообщить("Пояс информационной базы: " + Строка(ДанныеСервера.ПоясБазы));

КонецПроцедуры

&НаСервереБезКонтекста
Функция ВремяСервера()

    Результат = Новый Структура;
    Результат.Вставить("ДатаСервера", ТекущаяДата());
    Результат.Вставить("ДатаСеанса", ТекущаяДатаСеанса());
    Результат.Вставить("ДатаUTC", ТекущаяУниверсальнаяДата());
    Результат.Вставить("ПоясСервера", ЧасовойПояс());
    Результат.Вставить("ПоясСеанса", ЧасовойПоясСеанса());
    Результат.Вставить("ПоясБазы", ПолучитьЧасовойПоясИнформационнойБазы());
    Возврат Результат;

КонецФункции

&НаСервереБезКонтекста здесь выбрана намеренно: форма не передаётся на сервер, вызов лёгкий. Если пояс базы не задан, в последней строке будет пусто — Строка(Неопределено) даёт пустую строку.

Каждый вызов сервера с клиента — это сетевой запрос. Не дёргайте ВремяСервера() в цикле или по таймеру раз в секунду: получите время один раз, а дальше считайте смещение от клиентских часов.

Время сервера на клиенте без лишних вызовов

В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11 и другие) есть готовые функции общего модуля ОбщегоНазначенияКлиент:

  • ОбщегоНазначенияКлиент.ДатаСеанса() — дата сеанса на клиенте;
  • ОбщегоНазначенияКлиент.УниверсальнаяДата() — время UTC.

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

Какую функцию взять под задачу

ЗадачаЧто использоватьПочему
Дата нового документаТекущаяДатаСеанса() на сервереУчтёт пояс филиала, не зависит от часов пользователя
Отбор «за сегодня» в запросеНачалоДня(ТекущаяДатаСеанса()) параметромСутки считаются по местному времени
Метка обмена или синхронизацииТекущаяУниверсальнаяДата()Одинакова для всех регионов
Замер скорости кодаТекущаяУниверсальнаяДатаВМиллисекундах()Точность до миллисекунды
Диагностика часов ОС сервераТекущаяДата() на сервереПоказывает «сырое» время компьютера
Подстановка даты в форму на клиентеОбщегоНазначенияКлиент.ДатаСеанса()Без лишнего вызова сервера

Для замера скорости вычтите одно значение миллисекунд из другого: Конец - Начало даст длительность операции. Секундной точности ТекущаяДата() для этого мало — быстрые операции покажут ноль.

Часовые пояса сеанса, базы и сервера: смещения UTC

Есть три уровня часового пояса, и путают их постоянно:

  1. Пояс компьютера сервера — задаётся в операционной системе. Его возвращает ЧасовойПояс() без параметров.
  2. Пояс информационной базы — общий для всей базы. Читается ПолучитьЧасовойПоясИнформационнойБазы(), задаётся УстановитьЧасовойПоясИнформационнойБазы().
  3. Пояс сеанса — свой у каждого сеанса. При входе он берётся из пояса базы, а если тот не задан — из пояса компьютера сервера. Меняется УстановитьЧасовойПоясСеанса().

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

// На сервере, например, при начале работы сеанса
УстановитьЧасовойПоясСеанса("Asia/Novosibirsk");

МестнаяДата = ТекущаяДатаСеанса();          // время в Новосибирске
ДатаUTC     = ТекущаяУниверсальнаяДата();   // то же мгновение в UTC

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

Перевод между поясами и расчёт смещения

Для пересчёта дат есть функции платформы:

ФункцияЧто делаетПример результата
МестноеВремя(ДатаUTC, Пояс)UTC → местное время пояса12:00 UTC → 15:00 для Europe/Moscow
УниверсальноеВремя(Дата, Пояс)Местное время → UTC19:00 в Asia/Novosibirsk → 12:00 UTC
СмещениеСтандартногоВремени(Пояс)Смещение от UTC в секундах10800 для Москвы (3 часа)
ПредставлениеЧасовогоПояса(Пояс)Читаемое имя поясаСтрока для показа пользователю

Проверим арифметику: Новосибирск — UTC+7, значит 19:00 местного минус 7 часов = 12:00 UTC. Москва — UTC+3, 10 800 секунд = 3 × 3600.

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

Не храните в базе дату «с поправкой на пояс», вычисленную вручную прибавлением часов. Когда пояс сменится, прибавленные часы останутся в данных навсегда. Храните либо UTC, либо местное время вместе с поясом.

Получение времени через запрос к базе данных

В языке запросов 1С нет функции «текущая дата». Время передают параметром — и это правильный путь, потому что вы сами решаете, какое время подставить:

Запрос = Новый Запрос;
Запрос.Текст =
    "ВЫБРАТЬ
    |    Реализация.Ссылка КАК Документ,
    |    РАЗНОСТЬДАТ(Реализация.Дата, &ТекущаяДата, ДЕНЬ) КАК ДнейПрошло
    |ИЗ
    |    Документ.РеализацияТоваровУслуг КАК Реализация
    |ГДЕ
    |    Реализация.Дата >= ДОБАВИТЬКДАТЕ(&ТекущаяДата, ДЕНЬ, -7)";
Запрос.УстановитьПараметр("ТекущаяДата", ТекущаяДатаСеанса());
Выборка = Запрос.Выполнить().Выбрать();

Запрос выбирает реализации за последние 7 дней от даты сеанса. Для отбора «с начала дня» передайте НачалоДня(ТекущаяДатаСеанса()).

Время самой СУБД

Иногда нужно узнать часы сервера баз данных — например, при разборе блокировок или сверке логов СУБД с журналом регистрации. Это делают не из 1С, а в консоли СУБД:

-- Microsoft SQL Server
SELECT SYSDATETIME() AS МестноеВремя,
       SYSDATETIMEOFFSET() AS СоСмещением,
       GETUTCDATE() AS ВремяUTC;
-- PostgreSQL
SELECT now() AS время_со_смещением,
       current_setting('TimeZone') AS пояс_сервера;

Это только чтение, данные базы такие запросы не трогают.

Не пишите и не правьте таблицы 1С напрямую средствами СУБД. Чтение текущего времени безопасно, а любое изменение данных в обход платформы ломает целостность базы.

Сервер СУБД и сервер 1С часто стоят на разных машинах. Если их часы разошлись, сама 1С продолжит работать — даты в документы пишет сервер 1С. Но сверять события по логам станет тяжело.

Как найти, где расходится время

Порядок проверки — от простого к сложному.

  1. Сравните время в 1С. Запустите код из примера выше. Разница между клиентским и серверным ТекущаяДата() больше нескольких секунд — проблема в часах компьютеров. Разница ровно в целое число часов — проблема в поясах.
  2. Проверьте часы и пояс ОС сервера Windows. В командной строке:
:: текущий часовой пояс
tzutil /g

:: откуда берётся время и когда была синхронизация
w32tm /query /status
w32tm /query /source

:: принудительная синхронизация (нужны права администратора)
w32tm /resync
  1. Проверьте сервер на Linux:
timedatectl

Строки Time zone и System clock synchronized: yes покажут пояс и работу синхронизации.

  1. Проверьте все рабочие серверы кластера, а не только центральный. Время на каждом должно идти от одного источника — обычно от контроллера домена или общего NTP-сервера.
  2. Сравните пояс сеанса и пояс базы — строки «Пояс сеанса» и «Пояс информационной базы» из примера. Если у сеанса неожиданный пояс, ищите вызов УстановитьЧасовойПоясСеанса() в модулях сеанса и в расширениях.

В домене Windows рассинхронизация часов больше чем на 5 минут (значение по умолчанию) ломает проверку подлинности Kerberos. Если вместе со «съехавшим» временем перестал работать вход в 1С через доменного пользователя — начинайте с часов.

Если поменяли пояс или время на сервере

Сменили часовой пояс в ОС, а 1С показывает старое время — перезапустите службу агента сервера 1С.

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

Резкий перевод часов назад на работающем сервере тоже опасен: документы, созданные «в прошлом», встанут в последовательность не в том порядке. Правильнее, чтобы часы подтягивала служба синхронизации, а не ручная правка.

Ошибки при работе со временем сервера и как их исправить

Диагностика: выберите симптом

Ещё одна ошибка — на уровне кода: использовать ТекущаяДата() на клиенте для чего-то важного. Пользователь может перевести часы своего компьютера, и документ получит любую дату. Всё, что влияет на учёт, берите на сервере.

Частые вопросы

Чем ТекущаяДата() отличается от ТекущаяДатаСеанса() в файловой базе?
Если пояс базы и сеанса не задан, обе вернут одно и то же время компьютера. Разница появляется, когда пояс сеанса или базы отличается от пояса ОС.
Можно ли получить время сервера в обработке, открытой через внешнее соединение (COM)?
Да. Код во внешнем соединении выполняется на сервере, поэтому ТекущаяДата() и ТекущаяДатаСеанса() вернут серверное время.
Как узнать время сервера, не открывая Конфигуратор?
Создайте внешнюю обработку с кодом из статьи и откройте её через меню «Файл → Открыть». Для запуска внешних обработок нужны соответствующие права.
Учитывает ли 1С переход на летнее время?
Да, если пояс задан идентификатором региона, например Europe/Berlin. В России сезонного перевода часов нет с 2011 года, смещения постоянные.
Почему в журнале регистрации время отличается от даты документа?
Журнал регистрации пишет время по часам сервера 1С, а дата документа может быть подставлена в поясе сеанса или введена вручную.