Почему в 1С «не то» время: какие часы читает программа и как это исправить
Содержание
1С берёт дату из часов того компьютера, на котором выполняется код. Код клиента читает часы пользователя, код сервера читает часы сервера 1С, а функция ТекущаяДатаСеанса() берёт время сервера и пересчитывает его в часовой пояс сеанса. Поэтому «неправильное время» в документе почти всегда означает одно из трёх: на каком-то компьютере сбиты часы, неверно задан часовой пояс или разработчик вызвал не ту функцию.
Своего источника времени у платформы нет. Она не ходит в интернет за точным временем и не берёт его у СУБД. Ниже по режимам работы: какие часы главные, как проверить расхождение и как его убрать.
Какие часы главные в файловой базе
В файловом варианте нет отдельного сервера 1С. Серверная часть платформы работает внутри процесса клиента — на том же компьютере, где запущена программа.
Из этого следует простое правило:
- 🖥️ Тонкий или толстый клиент на ПК пользователя — и клиентский, и «серверный» код читают часы этого ПК.
- 🗂️ База лежит в сетевой папке — часы файлового сервера роли не играют. Каждый пользователь пишет документы по своим часам.
- 🌐 База опубликована на веб-сервере — серверный код выполняется в процессе веб-сервера, значит, работает время машины с IIS или Apache.
- 🖧 Работа через RDP — клиент запущен на терминальном сервере, и время берётся с него, а не с ноутбука пользователя.
Отсюда типичная картина в небольшой фирме: база в общей папке, у одного бухгалтера часы спешат на 20 минут, у другого стоит чужой часовой пояс. Документы, введённые в один момент, получают разное время, и порядок проведения внутри дня «плывёт».
Для файловой базы с несколькими пользователями синхронизация часов на каждом ПК — не формальность. Других источников времени у программы просто нет.
Как 1С получает время в клиент-серверном режиме
В клиент-серверном варианте код разделён явно. Директивы &НаКлиенте и &НаСервере определяют, чьи часы будут прочитаны.
| Где выполняется код | Что вернёт ТекущаяДата() | Что вернёт ТекущаяДатаСеанса() |
|---|---|---|
| Клиент (тонкий, толстый) | Местное время ПК пользователя | Время сервера в часовом поясе сеанса |
| Сервер 1С (рабочий процесс) | Местное время машины, где запущен rphost | Время сервера в часовом поясе сеанса |
| Фоновое и регламентное задание | Местное время сервера | Время сервера в часовом поясе сеанса |
| Веб-клиент | Время компьютера с браузером | Время сервера в часовом поясе сеанса |
Главное отличие: ТекущаяДатаСеанса() не зависит от часов пользователя. Она опирается на сервер и на настройку пояса. Поэтому в типовых конфигурациях даты документов, записей журналов и отметок времени заполняют именно ею.
Несколько рабочих серверов в кластере
Если в кластере два и больше рабочих сервера, каждый вызов серверного кода может попасть на любой из них. При рассинхронизации часов между машинами получаются странные эффекты:
- ⏱️ документ, записанный позже, получает более раннее время;
- 🔁 регламентное задание стартует «не в своё» время;
- 📋 в журнале регистрации события идут не по порядку.
Все рабочие серверы кластера должны брать время из одного источника. В домене это контроллер домена, вне домена — общий NTP-сервер.
А что с сервером СУБД
Время сервера SQL или PostgreSQL 1С для дат документов не использует. В языке запросов 1С нет функции «текущая дата»: её передают параметром, например &ДатаОтчета, а значение параметра вычисляется в модуле на клиенте или на сервере 1С. Часы СУБД стоит держать синхронными ради логов и резервного копирования, но на даты в базе они не влияют.
Часовой пояс и летнее время: где возникает сдвиг на час и больше
Тип «Дата» в 1С хранит просто год, месяц, день, часы, минуты и секунды. Сведений о поясе в значении нет. Если записать 10:00, в базе будет 10:00 — без пометки, московское это время или новосибирское.
Пояс влияет на то, какое значение получит код в момент записи. Цепочка такая:
- Часы операционной системы хранят универсальное время (UTC).
- Система переводит его в местное по своему часовому поясу — так получается результат
ТекущаяДата(). - Для
ТекущаяДатаСеанса()платформа берёт время сервера и пересчитывает его в часовой пояс сеанса. - Пояс сеанса по умолчанию равен часовому поясу информационной базы. Если пояс базы не задан, используется пояс компьютера сервера 1С.
Типичные причины сдвига
- 🐧 Сервер 1С на Linux работает в UTC. Пояс базы не задан, и
ТекущаяДата()на сервере отстаёт от Москвы ровно на 3 часа. - 🕐 Старая таблица поясов в Windows. Россия отказалась от перевода часов, а необновлённая система может по старым правилам сдвигать время на час.
- 🌍 Филиал в другом регионе. Пользователь в Екатеринбурге видит в документах московское время, потому что пояс сеанса равен поясу базы.
- 🖧 Перенаправление пояса в RDP. Если на терминальном сервере включена передача часового пояса клиента, у каждого пользователя своё «местное» время, и
ТекущаяДата()на клиенте у всех разная.
Проверить пояс системы можно командами:
:: Windows — текущий часовой пояс
tzutil /g
:: Linux — пояс и состояние синхронизации
timedatectl
Как программно управлять временем и задать сдвиг
У платформы есть набор функций для работы с поясами. Все они встроенные, названия ниже точные.
| Функция | Что делает |
|---|---|
ТекущаяДата() | Местное время компьютера, где выполняется код |
ТекущаяДатаСеанса() | Время сервера в часовом поясе сеанса |
ТекущаяУниверсальнаяДата() | Время UTC компьютера, где выполняется код |
ЧасовойПоясСеанса() | Идентификатор пояса текущего сеанса |
УстановитьЧасовойПоясСеанса() | Меняет пояс только для текущего сеанса |
ПолучитьЧасовойПоясИнформационнойБазы() | Пояс, заданный для всей базы |
УстановитьЧасовойПоясИнформационнойБазы() | Задаёт пояс базы, нужны административные права |
МестноеВремя() / УниверсальноеВремя() | Переводят дату между UTC и поясом |
Пояс для всей базы
Пример: сервер работает в UTC, а учёт ведётся по Москве. Достаточно один раз задать пояс базы:
&НаСервере
Процедура УстановитьМосковскоеВремяНаСервере()
УстановитьЧасовойПоясИнформационнойБазы("Europe/Moscow");
КонецПроцедуры
После этого ТекущаяДатаСеанса() во всех новых сеансах вернёт московское время. ТекущаяДата() на сервере по-прежнему покажет время машины — это поведение функции, а не ошибка.
В конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) пояс базы задаётся без кода: в разделе Администрирование → Общие настройки есть поле часового пояса. Расположение поля внутри формы зависит от релиза.
Пояс для отдельного пользователя
Если филиал должен видеть своё время, пояс меняют для сеанса — обычно при входе пользователя:
УстановитьЧасовойПоясСеанса("Asia/Yekaterinburg");
Учтите последствие. Документы филиала будут записаны с екатеринбургским временем, а центральный офис — с московским. В одном журнале окажутся записи в разных поясах без всякой пометки. Для отчётов «по дням» это даёт ошибку на границе суток: документ, введённый в 01:00 по Екатеринбургу, по Москве относится к предыдущему дню.
Рабочая дата вместо подкрутки часов
Когда нужно ввести документы задним числом, менять часы компьютера не нужно. В конфигурациях на БСП есть механизм «Рабочая дата»: пользователь задаёт дату, и новые документы получают её. Программно её читает функция ОбщегоНазначения.ТекущаяДатаПользователя() — она возвращает рабочую дату, если та задана, иначе дату сеанса.
Перевод системных часов на сервере 1С ради «проведения задним числом» сбивает время у всех пользователей, регламентные задания и журнал регистрации. Так делать нельзя даже на пять минут.
Как найти и устранить рассинхронизацию
Сначала выясните, чьи часы врут. Обработка из двух процедур показывает время клиента и сервера рядом:
&НаКлиенте
Процедура ПроверитьВремя(Команда)
ДатаКлиента = ТекущаяДата();
ДатаСервера = ПолучитьДатуСервера();
Разница = ДатаКлиента - ДатаСервера;
Сообщить(СтрШаблон("Клиент: %1; сервер: %2; разница: %3 сек.",
ДатаКлиента, ДатаСервера, Формат(Разница, "ЧГ=0; ЧН=0")));
Сообщить("Дата сеанса: " + ТекущаяДатаСеанса());
Сообщить("Пояс сеанса: " + ЧасовойПоясСеанса());
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьДатуСервера()
Возврат ТекущаяДата();
КонецФункции
Разница дат в 1С считается в секундах. Значение около 10 800 означает сдвиг на 3 часа — это пояс, а не сбитые часы. Небольшое расхождение в десятки секунд или минуты указывает на отсутствие синхронизации.
Синхронизация в Windows
На машине в домене время приходит от контроллера домена автоматически. Вне домена источник задают вручную. Команды выполняют в консоли от имени администратора:
:: Состояние синхронизации и текущий источник
w32tm /query /status
:: Задать внешний NTP-сервер (для компьютера вне домена)
w32tm /config /manualpeerlist:"pool.ntp.org" /syncfromflags:manual /update
:: Принудительно синхронизировать сейчас
w32tm /resync
Синхронизация в Linux
# Включить автоматическую синхронизацию
timedatectl set-ntp true
# Задать часовой пояс системы
timedatectl set-timezone Europe/Moscow
# Если стоит chrony — проверить точность
chronyc tracking
Резкий перевод часов на работающем сервере 1С на минуты и часы назад лучше делать вне рабочего времени. Регламентные задания могут сработать повторно, а записи журнала регистрации перемешаются. Пользователей стоит предупредить заранее.
Если не помогло
- 🔍 Проверьте, какой функцией заполняется дата в конкретном документе. Доработанная форма может вызывать
ТекущаяДата()на клиенте — тогда время по-прежнему берётся с ПК пользователя. - 🧩 Посмотрите расширения конфигурации
: подмена даты часто живёт в обработчике
ПриСозданииНаСерверерасширения. - 🖥️ В терминальном режиме сверьте пояс не только на сервере, но и в групповой политике перенаправления пояса.
Веб-клиент, тонкий клиент и мобильные устройства
Разница между клиентами важна, когда код выполняется на стороне пользователя.
Тонкий клиент на ПК пользователя читает системные часы Windows, macOS или Linux этого ПК. Код &НаКлиенте с ТекущаяДата() получит именно их.
Веб-клиент работает в браузере. Клиентский код получает время компьютера, на котором открыт браузер, с поясом, заданным в его системе. Пользователь в Хабаровске, открывший московскую базу через браузер, увидит в клиентском ТекущаяДата() хабаровское время.
Мобильный клиент и мобильное приложение берут время телефона. На смартфонах часы обычно синхронизированы с сотовой сетью, зато пояс пользователь часто меняет в поездке.
Общий вывод для всех клиентов один: дату для записи в базу получайте на сервере или через ТекущаяДатаСеанса(). Клиентское время годится для показа «сейчас у пользователя» — например, в приветствии или таймере на форме.
Что настроить, чтобы время больше не сбивалось
Короткий порядок для администратора:
- Назначьте один источник времени: контроллер домена или NTP-сервер.
- Подключите к нему сервер 1С, все рабочие серверы кластера, терминальные серверы и сервер СУБД.
- Задайте часовой пояс информационной базы, если сервер работает в UTC или в другом регионе.
- Держите обновлёнными таблицы часовых поясов ОС.
- Для файловой базы включите синхронизацию времени на каждом ПК, где запускают 1С.
- В доработках используйте
ТекущаяДатаСеанса()вместоТекущаяДата()для всего, что пишется в базу.