Работа с датами в 1С:Предприятие: от поля ввода до СКД
Содержание
Дату в 1С:Предприятие 8.3 задают тремя способами: набирают цифры прямо в поле, выбирают в календаре по кнопке справа от поля или получают из кода — литералом '20240115', конструктором Дата() или функцией ТекущаяДата(). Какой способ нужен, зависит от того, работаете вы в готовой конфигурации как пользователь или пишете код как разработчик.
Разница между пользовательским и программным выбором даты не только в интерфейсе. У даты в 1С всегда есть время — даже когда поле показывает только число. Из-за этого ломаются фильтры в отчётах и сравнения в коде. Ниже — как вводить дату в поле, как работать с ней в коде, как настроить формат вывода и как выбрать период в отчёте.
Ввод даты в поле: календарь, клавиши и стрелки
В любой конфигурации поле даты выглядит одинаково: само поле и кнопка календаря справа. Способы ввода:
- 📅 Кнопка календаря. Нажмите иконку справа от поля — откроется календарь. Стрелки вверху листают месяцы, клик по заголовку с месяцем и годом даёт быстрый переход к нужному периоду. Клик по числу закрывает календарь и подставляет дату.
- ⌨️ Ввод с клавиатуры. Наберите число прямо в поле. Разделители ставить не обязательно:
150124платформа сама превратит в15.01.2024. Год вводите четырьмя цифрами — так однозначно. - 🔼 Стрелки изменения. Поставьте курсор на день, месяц или год и нажимайте
↑/↓— выбранная часть даты увеличивается или уменьшается на единицу. Удобно сдвинуть дату на пару дней, не открывая календарь.
Если дата вводится вместе со временем, время редактируется в том же поле: поставьте курсор на часы или минуты и правьте так же, стрелками или цифрами.
Когда поле обязательно для заполнения, а вы оставили его пустым, при записи документа 1С подсветит поле и попросит ввести значение. Пустое поле — это не ошибка сама по себе: во многих реквизитах дата может быть не заполнена.
Если поле показывает и дату, и время, двигаться между частями можно клавишей → или мышью: один клик ставит курсор на нужную часть (день, месяц, год, час, минуту), дальше правите цифрами или стрелками. Выделять всё поле целиком не нужно — платформа понимает, какую часть вы меняете, по положению курсора.
Пустая дата и относительные значения
У незаполненной даты в 1С есть конкретное значение — 01.01.0001 00:00:00. Это так называемая «пустая дата». В интерфейсе она показывается пустым полем, но физически это дата. Поэтому проверка «поле не заполнено» в коде сравнивает реквизит именно с ней.
В отчётах и обработках вместо фиксированной даты часто выбирают относительный период: «этот месяц», «прошлый квартал», «с начала года». Такой выбор даёт поле типа «Стандартный период» — оно само пересчитает границы на момент формирования. Пользователю не нужно каждый раз вводить две даты вручную: достаточно выбрать пресет из списка.
Относительный период пересчитывается при каждом открытии. Отчёт «за этот месяц», сохранённый в ноябре, в декабре покажет уже декабрьские данные. Если нужен снимок за конкретный месяц — выбирайте «Произвольный период» и фиксируйте даты.
Выбор даты в коде: литералы, конструктор и функции
В модулях дату задают тремя путями.
Литерал даты — значение в одинарных кавычках в формате ГГГГММДД или ГГГГММДДччммсс:
Дата1 = '20240115'; // 15.01.2024, время 00:00:00
Дата2 = '20240115143000'; // 15.01.2024 14:30:00
Конструктор Дата() — когда год, месяц и день лежат в переменных:
Дата3 = Дата(2024, 1, 15);
Дата4 = Дата(2024, 1, 15, 14, 30, 0);
Текущая дата — функция ТекущаяДата() возвращает дату и время компьютера:
Сейчас = ТекущаяДата();
На клиенте ТекущаяДата() берёт время с компьютера пользователя, а оно может быть сбито. Для даты документов и проводок получайте дату на сервере: вызовите серверную процедуру, которая вернёт ТекущаяДата().
Границы периодов считают встроенные функции — они избавляют от ручной арифметики:
НачМесяца = НачалоМесяца(ТекущаяДата()); // 1-е число, 00:00:00
КонМесяца = КонецМесяца(ТекущаяДата()); // последнее число, 23:59:59
НачГода = НачалоГода(ТекущаяДата());
КонКвартала = КонецКвартала(ТекущаяДата());
Завтра = НачалоДня(ТекущаяДата()) + 86400; // +1 сутки (86400 сек)
Есть и НачалоНедели, КонецНедели, НачалоДня, КонецДня, НачалоМинуты. Сдвиг на месяцы — функцией ДобавитьМесяц(Дата, Количество), она корректно обрабатывает разную длину месяцев:
ЧерезКвартал = ДобавитьМесяц(ТекущаяДата(), 3);
Разбор даты на части — функциями Год(), Месяц(), День(), Час(), Минута(), Секунда(), ДеньНедели(). Последняя возвращает число от 1 (понедельник) до 7 (воскресенье):
Г = Год(Дата1);
М = Месяц(Дата1);
Д = День(Дата1);
ДН = ДеньНедели(Дата1); // 1 — понедельник … 7 — воскресенье
Собрать всё вместе помогает типовой фрагмент: найти все даты в заданном промежутке. Например, перебрать дни месяца от начала до конца:
Дата = НачалоМесяца(ТекущаяДата());
КонецМ = КонецМесяца(ТекущаяДата());
Пока Дата <= КонецМ Цикл
// здесь обрабатываем очередной день
Дата = НачалоДня(Дата) + 86400; // шаг — одни сутки
КонецЦикла;
Здесь НачалоДня на каждом шаге отсекает накопленное время, иначе из-за перехода на летнее/зимнее время цикл может сбиться на час.
Дата в 1С хранится как число секунд, поэтому вычитание двух дат даёт секунды, а не дни. Чтобы получить число дней, разделите результат на 86400:
Секунд = Дата2 - Дата1;
Дней = (НачалоДня(Дата2) - НачалоДня(Дата1)) / 86400;
НачалоДня в примере обнуляет время у обеих дат — иначе остаток секунд исказит счётчик дней.
Формат вывода даты
Дату для показа и печати форматируют функцией Формат(). Готовые локальные форматы задаются параметром ДЛФ (дата в локальном формате):
Формат(ТекущаяДата(), "ДЛФ=D"); // 15.01.2024
Формат(ТекущаяДата(), "ДЛФ=DT"); // 15.01.2024 14:30:00
Формат(ТекущаяДата(), "ДЛФ=T"); // 14:30:00
Формат(ТекущаяДата(), "ДЛФ=DL"); // 15 января 2024 г.
Что выдаёт каждый код ДЛФ:
| Код | Что выводит | Пример |
|---|---|---|
D | короткая дата | 15.01.2024 |
DT | дата и время | 15.01.2024 14:30:00 |
T | только время | 14:30:00 |
DL | длинная дата словами | 15 января 2024 г. |
Плюс локальных форматов в том, что они сами подстраиваются под язык и региональные настройки базы: в англоязычной базе DL даст месяц по-английски. Свой шаблон ДФ такого не умеет — он всегда выводит ровно то, что в нём написано.
Свой шаблон задаёт параметр ДФ. Буквы в шаблоне: д — день, М — месяц (заглавная), г — год, ч — часы, м — минуты (строчная), с — секунды:
Формат(ТекущаяДата(), "ДФ='дд.ММ.гггг'"); // 15.01.2024
Формат(ТекущаяДата(), "ДФ='дд MMMM гггг'"); // 15 января 2024
Не путайте М и м: заглавная М — это месяц, строчная м — минуты. Перепутанный регистр — частая причина «кривой» даты в печатной форме.
Для пустой даты задайте текст-заглушку параметром ДП, иначе она напечатается как 01.01.0001:
Формат(ПустаяДата, "ДЛФ=D; ДП='не указана'");
Эти же буквы шаблона работают в поле ввода на форме — его свойства Формат и ФорматРедактирования настраиваются в конфигураторе тем же синтаксисом.
Региональные настройки: откуда берётся вид даты
Как именно показывается дата по умолчанию (15.01.2024 или 2024-01-15), задаёт не Windows, а региональные настройки самой информационной базы. Меняют их в конфигураторе: Администрирование → Региональные настройки информационной базы. Там выбирают язык, формат даты, времени и чисел, первый день недели.
Эта настройка действует на всю базу и на всех пользователей. Поэтому перенос базы между серверами с разной локалью операционной системы не меняет вид дат — формат «зашит» в базу.
Если дата где-то отображается в непривычном виде, а региональные настройки базы в порядке, проверьте свойство Формат у конкретного поля или колонки — локальный формат поля перекрывает общий.
Отдельно стоит первый день недели. От него зависят функции НачалоНедели и КонецНедели: если в региональных настройках неделя начинается с воскресенья, границы недели сдвинутся на день по сравнению с привычным «понедельник — воскресенье». Это заметно в отчётах с недельной группировкой, поэтому первый день недели лучше задать осознанно при создании базы.
Выбор периода в отчётах на СКД
В отчётах на системе компоновки данных (СКД) период выбирают через параметры. Схема одинакова почти для всех отчётов:
- В схеме компоновки заводят два параметра —
НачалоПериодаиКонецПериода. - В запросе ставят отбор:
ГДЕ Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода. - На форме отчёта пользователь видит поле периода с пресетами «Этот месяц», «Этот квартал», «Произвольный период».
Чтобы пользователю не настраивать две даты по отдельности, в СКД добавляют один параметр типа «Стандартный период» и вычисляют из него начало и конец. Тогда выбор периода — это один клик по пресету.
Набор пресетов у стандартного периода фиксированный и понятный без обучения:
- 📆 Этот день / эта неделя / этот месяц / этот квартал / этот год — период привязан к текущей дате и пересчитывается каждый раз.
- 🗓️ Прошлый месяц / прошлый квартал / прошлый год — для регулярной отчётности за закрытый период.
- ✏️ Произвольный период — пользователь задаёт начало и конец руками, когда нужен нестандартный отрезок.
Если отчёт строят за дату «на момент» (например, остатки на конкретное число), период не нужен вовсе — достаточно одного параметра даты. Тогда в запросе ставят условие НА &ДатаОстатков для виртуальной таблицы остатков, а не отбор МЕЖДУ.
Классическая ловушка СКД: пользователь выбрал период «по 31 января», а в КонецПериода попала дата 31.01.2024 00:00:00. Документы, созданные 31 января днём, в отчёт не войдут — их время больше полуночи. Правильно подводить конец периода к 23:59:59 функцией КонецДня, а в самой схеме для таких параметров ставить время конца дня.
Тот же приём с КонецДня нужен в любом ручном отборе по датам — не только в СКД, но и в запросах обработок, и в отборах динамических списков.
Проблемы с вводом и выбором даты
Чаще всего жалобы на дату сводятся к четырём ситуациям — и почти все из-за скрытого времени.
Отдельная причина «скачущих» дат — часовой пояс сеанса. 1С хранит дату без привязки к зоне, но если на клиенте и сервере разошлось системное время, свежесозданные документы могут получать дату с расхождением. Проверьте время на сервере приложений — оно первично для серверных вызовов.
Частые вопросы
Как в коде проверить, что дата не заполнена?
Если Реквизит = '00010101' Тогда. Именно это значение платформа хранит в незаполненном поле даты.Чем литерал `'20240115'` отличается от `Дата(2024,1,15)`?
Дата() — когда год, месяц и день лежат в переменных и их надо собрать.Как получить первый и последний день месяца, не считая вручную?
НачалоМесяца(Дата) и КонецМесяца(Дата). Вторая возвращает последнее число с временем 23:59:59 — удобно сразу использовать как конец периода.Почему дата в печатной форме выводится с нулевым временем?
Формат(Дата, "ДЛФ=D") оставляет только дату, "ДЛФ=DT" — дату и время.Можно ли сменить формат даты только для одного пользователя?
Формат.