При интеграции 1С с внешними веб-сервисами через HTTP-запросы часто возникает необходимость передать дату в строго определенном стандарте, например: Tue, 20 Dec 2022 13:41:57 GMT. Этот формат является обязательным для таких заголовков, как Date, Last-Modified, Expires и If-Modified-Since. В этой статье мы разберем, как правильно сформировать такую строку, избежав типичных ошибок с часовыми поясами и локализацией.
Прежде всего, выясним, что это за формат. Согласно современным спецификациям (RFC 7231, пришедшим на смену RFC 1123 и RFC 2616), формат даты в заголовках HTTP строго регламентирован. Он должен всегда использовать английские названия дней недели и месяцев, иметь фиксированную длину и, что самое важное, указывать время только в часовом поясе GMT (Greenwich Mean Time).
Многие разработчики совершают ошибку, пытаясь использовать функцию XMLСтрока(Дата). Разберем, почему это неверно. Функция XMLСтрока возвращает дату в формате ISO 8601 (например, 2022-12-20T13:41:57). Большинство веб-серверов либо проигнорируют такой заголовок, либо вернут ошибку 400 (Bad Request), так как стандарт HTTP не допускает использования ISO 8601 в поле Date.
Самый простой и эффективный способ в 1С — это использование функции Формат() с явным указанием локализации. Рассмотрим код, который позволяет получить нужный результат всего в одну строку:
// Приводим локальную дату к универсальному времени (GMT/UTC)
ДатаUTC = УниверсальноеВремя(ТекущаяДата());
// Формируем строку по стандарту RFC 1123
СтрокаДатыHTTP = Формат(ДатаUTC, "Л=en_US; ДФ='ddd, dd MMM yyyy HH:mm:ss'") + " GMT";
// Результат: "Tue, 20 Dec 2022 13:41:57 GMT"
Проанализируем параметры этой функции:
Важное замечание по часовым поясам: Стандарт HTTP требует использования только GMT. Поэтому перед форматированием мы обязательно используем функцию УниверсальноеВремя(). Если передать локальное время (например, московское), но приписать в конце строку "GMT", сервер неверно интерпретирует момент отправки запроса.
В некоторых случаях, например, при работе на серверах под управлением Linux, где не установлены языковые пакеты en_US, функция Формат() может не выдать ожидаемый английский текст. В такой ситуации надежнее использовать "ручную" сборку через массивы. Рассмотрим этот алгоритм подробнее.
Функция ПолучитьДатуВФорматеHTTP(Знач ВхДата) Экспорт
// Переводим в UTC, если передана локальная дата
ДатаUTC = УниверсальноеВремя(ВхДата);
// Массивы имен (индексы соответствуют номерам из функций ДеньНедели и Месяц)
ДниНедели = Новый Массив;
ДниНедели.Добавить(""); // Индекс 0 не используется
ДниНедели.Добавить("Mon"); ДниНедели.Добавить("Tue"); ДниНедели.Добавить("Wed");
ДниНедели.Добавить("Thu"); ДниНедели.Добавить("Fri"); ДниНедели.Добавить("Sat");
ДниНедели.Добавить("Sun");
Месяцы = Новый Массив;
Месяцы.Добавить("");
Месяцы.Добавить("Jan"); Месяцы.Добавить("Feb"); Месяцы.Добавить("Mar");
Месяцы.Добавить("Apr"); Месяцы.Добавить("May"); Месяцы.Добавить("Jun");
Месяцы.Добавить("Jul"); Месяцы.Добавить("Aug"); Месяцы.Добавить("Sep");
Месяцы.Добавить("Oct"); Месяцы.Добавить("Nov"); Месяцы.Добавить("Dec");
// Сборка компонентов
СтрДеньНедели = ДниНедели[ДеньНедели(ДатаUTC)];
СтрДень = Формат(День(ДатаUTC), "ЧЦ=2; ЧВН=");
СтрМесяц = Месяцы[Месяц(ДатаUTC)];
СтрГод = Формат(Год(ДатаUTC), "ЧГ=0");
СтрВремя = Формат(ДатаUTC, "ДФ=HH:mm:ss");
Возврат СтрДеньНедели + ", " + СтрДень + " " + СтрМесяц + " " + СтрГод + " " + СтрВремя + " GMT";
КонецФункции
Разберем, почему этот метод считается максимально безопасным:
ЧВН= (Число С Ведущими Нулями) для дня месяца гарантирует, что "2" число превратится в "02", сохраняя структуру заголовка.Выясним, как проверить корректность полученной строки. Стандартная строка HTTP-date должна содержать ровно 29 символов. Если ваша строка длиннее или короче, скорее всего, вы забыли про ведущий ноль в числе месяца или неправильно указали формат года. Проанализируем пример: Fri, 01 Dec 2023 08:00:00 GMT — здесь ровно 29 знаков, включая пробелы и запятую.
Посмотрим также на типичную ситуацию при отладке: если сервер возвращает ошибку авторизации или подписи (например, в API Amazon S3 или Cloudflare), первым делом проверьте, совпадает ли время вашего сервера с универсальным временем. Даже небольшое расхождение более чем в 5 минут при правильно отформатированной дате может привести к отклонению запроса из соображений безопасности.
Таким образом, для большинства задач в 1С достаточно использования функции Формат() с локалью en_US, но для критически важных кроссплатформенных решений лучше выбрать вариант с ручным формированием строки через массивы названий.