Как преобразовать дату в формат HTTP-date (RFC 1123) для заголовков запросов в 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интеграции 1С с внешними веб-сервисами через HTTP-запросы часто возникает необходимость передать дату в строго определенном стандарте, например: Tue, 20 Dec 2022 13:41:57 GMT. Этот формат является обязательным для таких заголовков, как Date, Last-Modified, Expires и If-Modified-Since. В этой статье мы разберем, как правильно сформировать такую строку, избежав типичных ошибок с часовыми поясами и локализацией.

Понимание стандарта HTTP-date

Прежде всего, выясним, что это за формат. Согласно современным спецификациям (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: Использование встроенной функции Формат()

Самый простой и эффективный способ в 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", сервер неверно интерпретирует момент отправки запроса.

Способ 2: Ручная сборка строки (универсальный метод)

В некоторых случаях, например, при работе на серверах под управлением 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";
    
КонецФункции

Разберем, почему этот метод считается максимально безопасным:

  1. Независимость от окружения: Код будет работать одинаково на любой операционной системе и с любыми настройками локализации 1С.
  2. Контроль регистра: Мы жестко задаем написание (например, "Jan", а не "JAN"), что гарантирует совместимость с парсерами веб-серверов.
  3. Ведущие нули: Использование форматной строки ЧВН= (Число С Ведущими Нулями) для дня месяца гарантирует, что "2" число превратится в "02", сохраняя структуру заголовка.

Рекомендации по проверке

Выясним, как проверить корректность полученной строки. Стандартная строка HTTP-date должна содержать ровно 29 символов. Если ваша строка длиннее или короче, скорее всего, вы забыли про ведущий ноль в числе месяца или неправильно указали формат года. Проанализируем пример: Fri, 01 Dec 2023 08:00:00 GMT — здесь ровно 29 знаков, включая пробелы и запятую.

Посмотрим также на типичную ситуацию при отладке: если сервер возвращает ошибку авторизации или подписи (например, в API Amazon S3 или Cloudflare), первым делом проверьте, совпадает ли время вашего сервера с универсальным временем. Даже небольшое расхождение более чем в 5 минут при правильно отформатированной дате может привести к отклонению запроса из соображений безопасности.

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

← На главную