Работа с датами в 1С 8.3: от ручного ввода в документе до кода и запросов
Содержание
Дату в 1С задают двумя путями: руками в поле документа (формат дд.ММ.гггг, календарь по кнопке справа от поля) или программно — функциями Дата(2026, 1, 15) и ТекущаяДатаСеанса(). Это разные механизмы: первый про интерфейс пользователя, второй про встроенный язык, запросы и печатные формы.
Для пользователя важно ввести дату в карточке и не получить «пустую дату». Для разработчика — собрать значение типа Дата, привести его к нужному виду функцией Формат, посчитать начало и конец периода и правильно отобрать записи по датам в запросе. Разберём обе стороны.
Важная оговорка: дата в 1С — это всегда дата и время в одном значении. Поле без времени хранит 00:00:00. Из-за этого возникает половина ошибок с периодами, и к этому мы ещё вернёмся.
Ручной ввод даты в поле документа
Любое поле даты в интерфейсе «Такси» работает одинаково. Встаньте в поле и наберите цифры — разделители-точки программа подставит сама. Набор 150126 превращается в 15.01.2026, набирать точки руками не нужно.
Короткие приёмы ввода:
- 📅 Полный формат —
дд.ММ.гггг. Текущий год подставляется, если вы ввели только день и месяц. - ⌨️ Кнопка календаря в правой части поля открывает выпадающий календарь для выбора мышью.
- 🧹 Чтобы очистить поле, выделите значение и нажмите
Delete— получится пустая дата.
Если у поля есть ещё и время (например, дата документа у видов, где важен порядок проведения), время вводится следом за датой в том же поле: 15.01.2026 14:30:00. Когда время не показано — оно равно нулю.
Дата документа по умолчанию подставляется из рабочей даты сеанса. Рабочую дату задают в Сервис → Настройки → Рабочая дата (в типовых — через меню функций текущего раздела или настройки пользователя). Поставьте рабочую дату на нужный день перед вводом пачки документов задним числом — не придётся править дату в каждом.
Пустое поле даты — это не «ноль» и не «сегодня», а специальное значение «пустая дата». Документ с незаполненной обязательной датой не проведётся, а отбор по периоду такой документ не поймает. Если дата «слетела» в пустую — ищите ввод через копирование или обмен, где значение не передалось.
Выбор даты через встроенный календарь
Календарь удобен, когда нужно не промахнуться по дню недели или быстро перескочить на другой месяц. Открывается он кнопкой у правого края поля.
Что умеет календарь:
- Клик по дню — выбор даты, окно закрывается.
- Стрелки вверху листают месяцы, клик по названию месяца или года открывает ускоренную навигацию по месяцам и годам.
- Сегодняшний день подсвечен — удобно для сверки «какое сегодня число по базе».
Для полей, где выбирают не одну дату, а промежуток (отборы в отчётах, период в обработках), 1С показывает не обычный календарь, а диалог выбора периода. Там задают стандартный период — «Этот месяц», «Прошлый квартал», «Год» — или произвольные даты начала и конца. Стандартный период пересчитывается относительно рабочей даты, поэтому отчёт за «текущий месяц» всегда актуален.
Проверяйте, что в диалоге периода выбрана именно дата, а не «по сегодня». «По сегодня» — это скользящая граница: завтра отчёт покажет другой результат, и свериться с вчерашней выгрузкой не получится.
Функции формирования даты во встроенном языке
В коде дату собирают функцией Дата. Она принимает либо числа, либо строку:
// год, месяц, день
Д1 = Дата(2026, 1, 15);
// с временем: год, месяц, день, час, минута, секунда
Д2 = Дата(2026, 1, 15, 14, 30, 0);
// из строки формата ГГГГММДДЧЧММСС
Д3 = Дата("20260115143000");
Есть и литерал даты — значение прямо в коде в одинарных кавычках. Это самый короткий способ записать конкретную дату:
ДатаНачала = '20260101'; // 01.01.2026 00:00:00
МомментСобытия = '20260115143000'; // 15.01.2026 14:30:00
ПустаяДата = '00010101'; // пустая дата
Текущую дату берут двумя функциями, и путать их нельзя:
ТекущаяДата()возвращает дату того компьютера, где выполняется код: на сервере — серверную, на клиенте — клиентскую. Зависит от часов конкретной машины.ТекущаяДатаСеанса()возвращает дату сервера, приведённую к часовому поясу сеанса. Её и используйте в бизнес-логике — результат не зависит от того, правильно ли выставлены часы на компьютере пользователя.
СегодняшнееЧисло = ТекущаяДатаСеанса();
На клиенте управляемого приложения серверную дату без обращения к серверу не получить напрямую, поэтому ТекущаяДатаСеанса() для подстановки в форму вызывают в серверной процедуре и передают значение на клиент. Для чисто информационного показа «текущего времени» подойдёт и клиентская ТекущаяДата().
Собрать дату из отдельных чисел, полученных, например, из строкового ключа, помогает та же Дата — ей всё равно, откуда пришли год, месяц и день, лишь бы это были числа.
Приведение даты к нужному виду функцией Формат
Значение типа Дата для вывода в сообщение, печатную форму или в имя файла почти всегда приводят к строке функцией Формат. Управляет видом параметр форматной строки.
Два рабочих инструмента:
ДЛФ— локализованные форматы:D— длинная дата,T— только время,DT— дата и время. Названия месяцев подставляются по-русски автоматически.ДФ— собственный шаблон из букв:ddдень,MMмесяц,yyyyгод,HHчасы,mmминуты,ssсекунды.
Дата = '20260115143005';
Формат(Дата, "ДЛФ=D"); // 15 января 2026 г.
Формат(Дата, "ДЛФ=DT"); // 15 января 2026 г. 14:30:05
Формат(Дата, "ДФ='dd.MM.yyyy'"); // 15.01.2026
Формат(Дата, "ДФ='dd.MM.yyyy HH:mm'"); // 15.01.2026 14:30
Формат(Дата, "ДФ='yyyyMMdd'"); // 20260115 — для имени файла
Для подстановки даты в текст сообщения её нельзя просто склеить с другой строкой «плюсом» — получите системный вид с нулевым временем. Либо оберните в Формат, либо используйте СтрШаблон:
Текст = СтрШаблон("Документ от %1 проведён", Формат(Дата, "ДЛФ=D"));
Распространённая претензия пользователей — «в печатной форме вылезло 0:00:00 после даты». Это значит, что в макет попало неотформатированное значение даты. Лечится свойством «Формат» у параметра макета (ДЛФ=D) либо Формат в коде заполнения.
Обратная задача — получить дату из строки, которую ввёл пользователь или прислал внешний файл. Для свободного ввода подойдёт типизированный ввод через ТипЗнч и преобразование, но надёжнее разобрать строку самому: вырезать год, месяц и день подстрокой и собрать значение функцией Дата. Так вы контролируете, что делать с нераспознанной строкой, а не ловите исключение преобразования. Для строки строго в формате ГГГГММДД можно сразу передать её в Дата("20260115") — лишний разбор не нужен.
Периоды: начало и конец месяца, квартала, года
Самая частая задача с датами — получить границы периода. Для этого есть готовые функции, считать руками ничего не нужно:
| Функция | Что возвращает |
|---|---|
НачалоДня(Д) | ту же дату, время 00:00:00 |
КонецДня(Д) | ту же дату, время 23:59:59 |
НачалоМесяца(Д) | 1-е число месяца, 00:00:00 |
КонецМесяца(Д) | последний день месяца, 23:59:59 |
НачалоКвартала(Д) / КонецКвартала(Д) | границы квартала |
НачалоГода(Д) / КонецГода(Д) | 1 января и 31 декабря |
НачалоНедели(Д) / КонецНедели(Д) | понедельник и воскресенье |
Сдвиг на месяцы делает ДобавитьМесяц:
ПрошлыйМесяц = ДобавитьМесяц(ТекущаяДатаСеанса(), -1);
НачалоПрошлогоМесяца = НачалоМесяца(ПрошлыйМесяц);
КонецПрошлогоМесяца = КонецМесяца(ПрошлыйМесяц);
ДобавитьМесяц аккуратен с концом месяца: ДобавитьМесяц('20260131', 1) вернёт 28 февраля, а не несуществующее 31-е.
Разницу двух дат получают вычитанием — результат в секундах (число):
СекундМеждуДатами = ДатаОкончания - ДатаНачала;
ДнейМеждуДатами = (ДатаОкончания - ДатаНачала) / 86400; // 86400 секунд в сутках
Прибавить к дате интервал тоже можно арифметикой: Дата + 3600 — плюс час, Дата + 86400 — плюс сутки. Для дней и секунд это удобнее, чем ДобавитьМесяц; для месяцев и лет — только ДобавитьМесяц, потому что в них разное число дней.
Для квартальных и годовых границ действует та же логика: НачалоКвартала и КонецГода сами определят, в каком квартале или году лежит переданная дата, — вам не нужно знать, какой сейчас квартал. Это удобно для отчётов «с начала года»: нижняя граница — НачалоГода(ТекущаяДатаСеанса()), верхняя — КонецДня(ТекущаяДатаСеанса()).
Даты в запросах к базе
В языке запросов свои функции — они пишутся по-русски заглавными буквами и работают над полями таблиц.
Собрать константную дату в запросе:
ВЫБРАТЬ
Продажи.Дата,
Продажи.Сумма
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
ГДЕ
Продажи.Дата МЕЖДУ &НачалоПериода И &КонецПериода
Литерал даты прямо в тексте запроса задаёт функция ДАТАВРЕМЯ:
ГДЕ Продажи.Дата >= ДАТАВРЕМЯ(2026, 1, 1)
Разложить дату на части и свести к периоду:
ГОД(Поле),КВАРТАЛ(Поле),МЕСЯЦ(Поле),ДЕНЬ(Поле),НЕДЕЛЯ(Поле)— числовые части.НАЧАЛОПЕРИОДА(Поле, МЕСЯЦ)иКОНЕЦПЕРИОДА(Поле, МЕСЯЦ)— границы периода (ДЕНЬ,НЕДЕЛЯ,МЕСЯЦ,КВАРТАЛ,ГОД).ДОБАВИТЬКДАТЕ(Поле, МЕСЯЦ, 1)— сдвиг на интервал.РАЗНОСТЬДАТ(Дата1, Дата2, ДЕНЬ)— разница в указанных единицах.
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Продажи.Дата, МЕСЯЦ) КАК МесяцПродажи,
СУММА(Продажи.Сумма) КАК Оборот
ИЗ
Документ.РеализацияТоваровУслуг КАК Продажи
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Продажи.Дата, МЕСЯЦ)
При отборе остатков и оборотов по регистрам момент времени задают через Граница, чтобы захватить движения последнего дня целиком:
Отбор = Новый Граница(КонецДня(ДатаОтчёта), ВидГраницы.Включая);
Пустую дату в запросе сравнивают с ДАТАВРЕМЯ(1, 1, 1) — именно так выглядит «пустая дата» для языка запросов.
Типичные ошибки с датами и как их избежать
Здесь собраны не повторы шагов, а именно ловушки, на которых спотыкаются чаще всего.
00:00:00 последнего дня, и всё, что проведено позже полуночи, отсекается. Оберните границу в КонецДня, а для регистров используйте Граница(..., ВидГраницы.Включая).Дата без форматирования. Задайте параметру макета свойство «Формат» со значением ДЛФ=D или форматируйте дату функцией Формат при заполнении.ТекущаяДата() (часы конкретной машины) и ТекущаяДатаСеанса() (серверная с учётом часового пояса). В бизнес-логике берите ТекущаяДатаСеанса().Дата или в поле попала строка или число в неверном формате. Для строки нужен формат ГГГГММДД или ГГГГММДДЧЧММСС, для чисел — отдельные год, месяц, день.00:00:00, а у документа есть время. Сравнивайте диапазоном: от НачалоДня до КонецДня, а не = Дата.Короткая самопроверка на понимание механики дат:
Частые вопросы
Как задать пустую дату в коде?
'00010101' или функцией Дата(1, 1, 1). В запросе пустой дате соответствует ДАТАВРЕМЯ(1, 1, 1). Проверка «дата не заполнена» — сравнение с этим значением, а не с нулём или Неопределено.Чем отличается ДЛФ от ДФ в функции Формат?
ДЛФ — готовые локализованные форматы (D — длинная дата с названием месяца по-русски, T — время, DT — дата и время). ДФ — ваш собственный шаблон из букв dd, MM, yyyy, HH, mm, ss. Для имени файла берут ДФ='yyyyMMdd', для документа на экране — ДЛФ=D.Как получить первый и последний день месяца?
НачалоМесяца(Дата) и КонецМесяца(Дата). КонецМесяца возвращает последний день со временем 23:59:59, поэтому подходит как верхняя граница отбора без дополнительных поправок.Почему дата в документе на час или сутки отличается от ожидаемой?
ТекущаяДата(), которая берёт часы того компьютера, где исполняется код, или не учтён часовой пояс сеанса. Для записи даты события в базу используйте ТекущаяДатаСеанса().Как в запросе отобрать документы за конкретный месяц?
НАЧАЛОПЕРИОДА(Поле.Дата, МЕСЯЦ), либо задать границы через параметры МЕЖДУ &Начало И &Конец, где конец вычислен как КонецМесяца. Сравнение на точное равенство дате для документов с временем не работает.