Работая с системой 1С:Предприятие, мы часто сталкиваемся с задачами, требующими точной синхронизации данных. Одной из таких критически важных задач является корректное время в документах и операциях. Представьте ситуацию, когда из-за сбоев системных часов сервера документы выписываются с неправильной датой, что приводит к серьезным проблемам в учете. В этой статье мы подробно разберем, как получить время на клиенте и сервере в 1С, сравнить его и при значительном расхождении заблокировать вход пользователя в программу, предотвращая дальнейшие ошибки.
Основная причина возникновения проблем с временем часто кроется в аппаратных сбоях серверного оборудования, например, из-за севшей батарейки CMOS на материнской плате сервера. Хотя эта батарейка используется часами реального времени преимущественно при выключенном компьютере, ее неисправность или другие аппаратные проблемы могут приводить к постоянному "отставанию" или "убеганию" времени даже во время работы сервера. Это, в свою очередь, становится причиной того, что документы в 1С выписываются с ошибочными датами, нарушая хронологию учета и вызывая путаницу.
Нашей задачей является создание механизма со стороны 1С, который не позволит пользователям работать в системе, если системное время их компьютера значительно отличается от времени сервера. Это будет своего рода "предохранитель", пока основная аппаратная проблема не будет решена системным администратором.
Для реализации такой проверки нам необходимо выбрать подходящее место в коде 1С. Идеальным решением будет обработчик события ПриНачалеРаботыСистемы(), который располагается в модуле сеанса. Этот обработчик выполняется один раз при каждом запуске клиентского приложения, что позволяет нам перехватить момент входа пользователя и выполнить необходимые проверки до того, как пользователь получит полный доступ к функционалу программы.
Далее мы рассмотрим, какие функции в 1С позволяют получать текущее время и как их правильно использовать для сравнения времени на клиентской и серверной сторонах.
Для корректного сравнения времени очень важно понимать, как работают различные функции даты и времени в 1С. От их правильного выбора зависит точность нашей проверки.
ТекущаяДата():
Эта функция возвращает системное время того компьютера, на котором она выполняется. Если мы вызовем её на клиенте, получим системное время клиента. Если вызовем в серверном модуле, она вернёт системное время сервера. Использование этой функции для прямого сравнения системных часов клиента и сервера возможно, но не рекомендуется в клиент-серверной архитектуре без учета часовых поясов, так как она возвращает местное время, которое может отличаться из-за разных часовых поясов, даже если абсолютное время совпадает.
ТекущаяДатаСеанса():
Данная функция является предпочтительной для большинства операций внутри одного сеанса. Она всегда получает текущее время с сервера, но приводит его к часовому поясу, установленному в настройках сеанса пользователя. Это обеспечивает единообразие времени для всех операций в рамках сеанса одного пользователя. Однако, для задачи сравнения *системных часов* клиента и сервера, эта функция не подходит, так как она всегда отражает время сервера (пусть и с коррекцией часового пояса сеанса), и её вызов на клиенте по сути тоже вернёт время сервера.
ТекущаяУниверсальнаяДата() (UTC):
Это наиболее надёжный и правильный способ для сравнения системного времени. Функция ТекущаяУниверсальнаяДата() возвращает время по Гринвичу (UTC, Coordinated Universal Time), которое является универсальным и не зависит от локальных часовых поясов. Сравнивая универсальное время, полученное на клиенте, с универсальным временем, полученным на сервере, мы можем определить точное расхождение системных часов, полностью исключив влияние часовых поясов. Этот подход является наиболее рекомендуемым для нашей задачи.
Мы будем размещать наш код в модуле сеанса, в обработчике события ПриНачалеРаботыСистемы(). Наша общая логика будет состоять из следующих шагов:
Давайте рассмотрим два основных подхода к реализации.
Этот метод будет работать корректно, если мы гарантируем, что все пользователи и сервер находятся в одном часовом поясе. В этом случае мы можем сравнивать местное системное время, полученное функцией ТекущаяДата().
Разберем шаги подробнее:
ТекущаяДата() для получения системного времени сервера.ТекущаяДата(), которая вернет системное время клиентского компьютера.Abs() поможет нам в этом, вернув модуль разницы в секундах.ЗавершитьРаботуСистемы().Пример кода для реализации в модуле сеанса:
&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
// Получаем текущее системное время на сервере
ДатаСервера = ПолучитьСистемноеВремяСервера();
// Получаем текущее системное время на клиенте
ДатаКлиента = ТекущаяДата();
// Вычисляем разницу в секундах (модуль Abs нужен, чтобы разница всегда была положительной)
РазницаВСекундах = Abs(ДатаКлиента - ДатаСервера);
// Устанавливаем допустимое отклонение (например, 10 минут = 600 секунд)
ДопустимоеОтклонение = 600;
Если РазницаВСекундах > ДопустимоеОтклонение Тогда
Предупреждение("Время на вашем компьютере значительно отличается от времени на сервере!
|Для корректной работы необходимо синхронизировать время.
|Программа будет закрыта.");
ЗавершитьРаботуСистемы(Ложь); // Параметр Ложь означает, что пользователю будет задан вопрос о завершении
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьСистемноеВремяСервера()
// Эта функция выполняется на сервере и возвращает его системное время
Возврат ТекущаяДата();
КонецФункции
Обратите внимание на параметр Ложь в функции ЗавершитьРаботуСистемы(Ложь). Он означает, что система спросит пользователя, действительно ли он хочет завершить работу. Если вы хотите принудительно закрыть программу без каких-либо вопросов, используйте ЗавершитьРаботуСистемы(Истина).
Этот метод является наиболее правильным и универсальным. Он будет работать корректно, даже если в будущем появятся клиенты из других часовых поясов, поскольку сравнивает абсолютное время, не привязанное к локальным настройкам. Мы будем использовать функцию ТекущаяУниверсальнаяДата().
Разберем шаги подробнее:
ТекущаяУниверсальнаяДата() для получения времени сервера в формате UTC.ТекущаяУниверсальнаяДата(), которая вернет время клиентского компьютера в формате UTC.Пример кода для реализации в модуле сеанса:
&НаКлиенте
Процедура ПриНачалеРаботыСистемы()
// Получаем универсальное время на сервере
ДатаСервераUTC = ПолучитьУниверсальноеВремяСервера();
// Получаем универсальное время на клиенте
ДатаКлиентаUTC = ТекущаяУниверсальнаяДата();
// Вычисляем разницу в секундах
РазницаВСекундах = Abs(ДатаКлиентаUTC - ДатаСервераUTC);
ДопустимоеОтклонение = 600; // 10 минут
Если РазницаВСекундах > ДопустимоеОтклонение Тогда
Предупреждение("Системные часы вашего компьютера и сервера не синхронизированы!
|Пожалуйста, исправьте время на вашем компьютере.
|Программа будет закрыта.");
ЗавершитьРаботуСистемы(Ложь);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьУниверсальноеВремяСервера()
// Эта функция выполняется на сервере и возвращает его универсальное время (UTC)
Возврат ТекущаяУниверсальнаяДата();
КонецФункции
Этот подход является более гибким и надёжным, так как он полностью исключает влияние часовых поясов на результат сравнения.
Если в вашем случае требуется безусловное завершение работы программы без вопросов к пользователю (например, для повышения строгости контроля), вы можете использовать параметр Истина в функции ЗавершитьРаботуСистемы(Истина). Однако, чаще всего, вариант с предупреждением и возможностью пользователя отказаться (ЗавершитьРаботуСистемы(Ложь)) является более дружелюбным.
Критически важно помнить, что блокировка входа в 1С при расхождении времени — это лишь временное решение или "костыль", как это было упомянуто в обсуждении. Основная проблема заключается в аппаратной неисправности сервера, которая приводит к сбою системных часов. Системному администратору необходимо в кратчайшие сроки:
Только комплексный подход, включающий как решение на стороне 1С, так и устранение корневой причины на серверном уровне, обеспечит стабильную и корректную работу вашей информационной системы.
Таким образом, мы получили рабочее решение для контроля синхронизации времени между клиентом и сервером в 1С. Применив один из предложенных подходов, вы сможете значительно снизить риски, связанные с неверными датами в документах, и обеспечить более надёжную работу вашей системы.