Работа с датами в 1С:Предприятие: от поля ввода до СКД

· 9 мин

Содержание

Дату в 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, а региональные настройки самой информационной базы. Меняют их в конфигураторе: Администрирование → Региональные настройки информационной базы. Там выбирают язык, формат даты, времени и чисел, первый день недели.

Эта настройка действует на всю базу и на всех пользователей. Поэтому перенос базы между серверами с разной локалью операционной системы не меняет вид дат — формат «зашит» в базу.

Если дата где-то отображается в непривычном виде, а региональные настройки базы в порядке, проверьте свойство Формат у конкретного поля или колонки — локальный формат поля перекрывает общий.

Отдельно стоит первый день недели. От него зависят функции НачалоНедели и КонецНедели: если в региональных настройках неделя начинается с воскресенья, границы недели сдвинутся на день по сравнению с привычным «понедельник — воскресенье». Это заметно в отчётах с недельной группировкой, поэтому первый день недели лучше задать осознанно при создании базы.

Выбор периода в отчётах на СКД

В отчётах на системе компоновки данных (СКД) период выбирают через параметры. Схема одинакова почти для всех отчётов:

  1. В схеме компоновки заводят два параметра — НачалоПериода и КонецПериода.
  2. В запросе ставят отбор: ГДЕ Документ.Дата МЕЖДУ &НачалоПериода И &КонецПериода.
  3. На форме отчёта пользователь видит поле периода с пресетами «Этот месяц», «Этот квартал», «Произвольный период».

Чтобы пользователю не настраивать две даты по отдельности, в СКД добавляют один параметр типа «Стандартный период» и вычисляют из него начало и конец. Тогда выбор периода — это один клик по пресету.

Набор пресетов у стандартного периода фиксированный и понятный без обучения:

  • 📆 Этот день / эта неделя / этот месяц / этот квартал / этот год — период привязан к текущей дате и пересчитывается каждый раз.
  • 🗓️ Прошлый месяц / прошлый квартал / прошлый год — для регулярной отчётности за закрытый период.
  • ✏️ Произвольный период — пользователь задаёт начало и конец руками, когда нужен нестандартный отрезок.

Если отчёт строят за дату «на момент» (например, остатки на конкретное число), период не нужен вовсе — достаточно одного параметра даты. Тогда в запросе ставят условие НА &ДатаОстатков для виртуальной таблицы остатков, а не отбор МЕЖДУ.

Классическая ловушка СКД: пользователь выбрал период «по 31 января», а в КонецПериода попала дата 31.01.2024 00:00:00. Документы, созданные 31 января днём, в отчёт не войдут — их время больше полуночи. Правильно подводить конец периода к 23:59:59 функцией КонецДня, а в самой схеме для таких параметров ставить время конца дня.

Тот же приём с КонецДня нужен в любом ручном отборе по датам — не только в СКД, но и в запросах обработок, и в отборах динамических списков.

Проблемы с вводом и выбором даты

Чаще всего жалобы на дату сводятся к четырём ситуациям — и почти все из-за скрытого времени.

Диагностика: выберите симптом

Отдельная причина «скачущих» дат — часовой пояс сеанса. 1С хранит дату без привязки к зоне, но если на клиенте и сервере разошлось системное время, свежесозданные документы могут получать дату с расхождением. Проверьте время на сервере приложений — оно первично для серверных вызовов.

Частые вопросы

Как в коде проверить, что дата не заполнена?
Сравните реквизит с пустой датой: Если Реквизит = '00010101' Тогда. Именно это значение платформа хранит в незаполненном поле даты.
Чем литерал `'20240115'` отличается от `Дата(2024,1,15)`?
Результат одинаковый. Литерал пишут, когда дата известна прямо в коде; конструктор Дата() — когда год, месяц и день лежат в переменных и их надо собрать.
Как получить первый и последний день месяца, не считая вручную?
Функциями НачалоМесяца(Дата) и КонецМесяца(Дата). Вторая возвращает последнее число с временем 23:59:59 — удобно сразу использовать как конец периода.
Почему дата в печатной форме выводится с нулевым временем?
Формат показывает и время. Уберите его: Формат(Дата, "ДЛФ=D") оставляет только дату, "ДЛФ=DT" — дату и время.
Можно ли сменить формат даты только для одного пользователя?
Нет. Формат по умолчанию задаётся на уровне информационной базы в региональных настройках и общий для всех. Поменять вид можно лишь у конкретного поля через его свойство Формат.