Разработка и Конфигурация · 10 мин
Как получить начало месяца в 1С
Как получить начало месяца в 1С: функция НачалоМесяца, работа в запросах, отчётах, типовых документах и на управляемых формах. Примеры кода и ошибки.
Во встроенном языке 1С дата всегда хранится с точностью до секунды, поэтому «начало месяца» — это конкретное значение: первое число нужного месяца с временем 00:00:00. Получить его можно одной встроенной функцией, но на практике задача шире: начало месяца нужно в запросах, отчётах на СКД, при установке периодов в документах и при расчёте дат относительно текущей или произвольной даты.
Основной инструмент — функция НачалоМесяца(). Она принимает один параметр типа «Дата» и возвращает дату первого числа того же месяца с обнулённым временем. Функция доступна и на сервере, и на клиенте, работает одинаково в обычных и управляемых формах, в тонком и веб-клиенте.
Ошибки чаще всего связаны не с самой функцией, а с контекстом: разработчик забывает, что в запросе синтаксис другой, путает начало месяца с началом периода отчёта или передаёт в функцию не дату, а строку. Ниже разобраны все рабочие сценарии с примерами кода и способами проверки результата.
Функция НачалоМесяца во встроенном языке
Синтаксис функции предельно прост: НачалоМесяца(<Дата>). Параметр обязателен и должен иметь тип «Дата». Возвращаемое значение — дата первого числа того месяца, в который попадает переданная дата, с временем 00:00:00.
Типичный пример в модуле:
ТекущаяДата = ТекущаяДатаСеанса(); // например, 17.03.2026 14:25:10
НачалоТекущегоМесяца = НачалоМесяца(ТекущаяДата); // 01.03.2026 0:00:00
ПроизвольнаяДата = Дата(2026, 11, 28, 15, 40, 0);
НачалоНоября = НачалоМесяца(ПроизвольнаяДата); // 01.11.2026 0:00:00
Обратите внимание: функция не изменяет месяц и год, она только «сбрасывает» день до первого числа и время до полуночи. Если передана дата 01.03.2026 10:00:00, результатом будет 01.03.2026 00:00:00 — то есть функция имеет смысл даже для первого числа, потому что обнуляет время.
Для получения начала месяца текущей даты в серверном коде корректно использовать ТекущаяДатаСеанса(), а не ТекущаяДата() в клиентском контексте — иначе при разнице часовых поясов клиента и сервера можно получить начало соседнего месяца на границе дат.
НачалоМесяца = НачалоМесяца(ТекущаяДатаСеанса()); // 01-е число, 00:00:00Начало месяца в запросах
В языке запросов 1С функция НачалоМесяца() встроенного языка недоступна — там используется собственное выражение НАЧАЛОПЕРИОДА(<Дата>, МЕСЯЦ). Это одна из самых частых причин ошибок у начинающих разработчиков: код из модуля механически переносят в текст запроса, и консоль запросов выдаёт синтаксическую ошибку.
Пример запроса, группирующего документы по месяцам:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) КАК НачалоМесяца,
СУММА(Продажи.СуммаОборот) КАК Сумма
ИЗ
РегистрНакопления.Продажи.Обороты КАК Продажи
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ)
Если начало месяца нужно передать в запрос как параметр — например, для отбора документов с начала текущего месяца — вычислите значение во встроенном языке и передайте через УстановитьПараметр:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| РеализацияТоваровУслуг.Ссылка
|ИЗ
| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|ГДЕ
| РеализацияТоваровУслуг.Дата >= &НачалоМесяца";
Запрос.УстановитьПараметр("НачалоМесяца", НачалоМесяца(ТекущаяДатаСеанса()));
При сравнении дат в условии ГДЕ помните, что дата документа содержит время. Отбор Дата >= &НачалоМесяца корректен, а вот верхнюю границу лучше задавать через КОНЕЦПЕРИОДА(Дата, МЕСЯЦ) или функцию КонецМесяца(), иначе документы последнего дня месяца с ненулевым временем выпадут из выборки.
Начало месяца для произвольной даты: прошлый и следующий месяц
Часто нужно начало не текущего, а предыдущего или следующего месяца — например, для закрытия периода или формирования отчёта за прошлый месяц. Для этого функцию комбинируют с ДобавитьМесяц():
Текущая = ТекущаяДатаСеанса();
НачалоПрошлогоМесяца = НачалоМесяца(ДобавитьМесяц(Текущая, -1));
НачалоСледующегоМесяца = НачалоМесяца(ДобавитьМесяц(Текущая, 1));
Функция ДобавитьМесяц() корректно обрабатывает переходы через год и разную длину месяцев: от 31 января минус один месяц получится дата в пределах декабря, а не несуществующее 31 ноября. Поэтому связка ДобавитьМесяц + НачалоМесяца надёжнее ручной арифметики с днями.
Для сдвига на несколько месяцев укажите нужное число вторым параметром: НачалоМесяца(ДобавитьМесяц(Дата, -3)) даст начало месяца три месяца назад. Это удобно в регламентных заданиях, которые формируют данные за квартал.
- 1Определите базовую дату: текущую (ТекущаяДатаСеанса) или произвольную из реквизита
- 2При необходимости сдвиньте её функцией ДобавитьМесяц(Дата, N)
- 3Примените НачалоМесяца к полученному значению
- 4Проверьте результат через Сообщить() или отладчик: день должен быть 01, время 00:00:00
Начало месяца в отчётах на СКД
В системе компоновки данных есть несколько способов получить начало месяца. Самый простой — использовать стандартный период: параметр типа СтандартнаяДатаНачала уже содержит свойство Дата, а вариант «Этот месяц» или «Прошлый месяц» автоматически даёт начало нужного месяца без кода.
Если период нужен вычисляемым, добавьте в набор данных выражение НАЧАЛОПЕРИОДА(Поле.Дата, МЕСЯЦ) — оно работает в запросе СКД так же, как в обычном запросе. Для группировки записей по месяцам этого достаточно.
Третий вариант — функции языка выражений СКД. В вычисляемых полях и ресурсах доступны функции встроенного языка, если они разрешены, поэтому НачалоМесяца() можно вызывать и там. Однако предпочтительнее вычислять дату на уровне запроса: это быстрее и не требует включения пользовательских функций.
Сравнение вариантов
Для любого кода встроенного языка: обработки, модули объектов, регламентные задания. Не работает внутри текста запроса.
Для отборов и группировок в запросах и наборах данных СКД. Требует поля или параметра типа Дата.
Для отчётов, где пользователь сам выбирает период. Начало месяца задаётся настройкой без программирования.
Типичные ошибки и как их избежать
Первая ошибка — передача в НачалоМесяца() значения, которое не является датой: строки «01.03.2026» или пустого значения. Строка вызовет ошибку преобразования типа, поэтому перед вызовом убедитесь, что реквизит заполнен и имеет тип «Дата». Для реквизитов с составным типом используйте проверку ТипЗнч(Значение) = Тип("Дата").
Вторая ошибка — использование клиентской ТекущаяДата() в серверных процедурах и наоборот. В тонком клиенте при вызове сервера дата может отличаться на часовой пояс, и на стыке месяцев начало периода окажется смещённым. Правило простое: на сервере — ТекущаяДатаСеанса().
Третья ошибка — сравнение дат без учёта времени. Условие Дата = НачалоМесяца(Дата) будет ложным для документа от первого числа, проведённого в 09:15, потому что время не совпадает. Сравнивайте через НачалоДня(Дата) = НачалоМесяца(Дата) или используйте диапазоны.
Проверка результата и границы применения
Быстро проверить результат можно через Сообщить() или в отладчике: у корректного значения день всегда равен 01, а время — 00:00:00. Удобный шаблон проверки:
Результат = НачалоМесяца(ПроверяемаяДата);
Если День(Результат) = 1 И Результат = НачалоДня(Результат) Тогда
// значение корректно
КонецЕсли;
Учитывайте граничные случаи. Для пустой даты (01.01.0001 00:00:00) функция вернёт ту же пустую дату — это не ошибка, но в отборах такое значение обычно бессмысленно, поэтому проверяйте заполненность заранее. Для дат с часовыми поясами в распределённых базах ориентируйтесь на дату сеанса сервера, где выполняется код.
В типовых конфигурациях для периодических задач часто уже есть готовые механизмы: стандартные периоды в отчётах, обработки закрытия месяца, общие модули работы с датами. Прежде чем писать свой код, проверьте, не решает ли задачу штатная функциональность — это снижает риск расхождений при обновлении конфигурации.
Как проверить результат
Первое число месяца, время 00:00:00
Сохранилось исходное время или день отличен от 01
Выбираются все документы с первого числа включительно
Документы первого числа с ненулевым временем пропущены
Дата сдвинута ровно на месяц, переход через год корректен
Ручной расчёт дней дал несуществующую дату
Частые вопросы
Чем НачалоМесяца отличается от НачалоДня?
НачалоДня обнуляет только время, сохраняя число, а НачалоМесяца дополнительно устанавливает первое число месяца. Для даты 17.03.2026 14:00 первая функция вернёт 17.03.2026 00:00:00, вторая — 01.03.2026 00:00:00.
Как получить конец месяца?
Используйте парную функцию КонецМесяца(Дата) — она возвращает последний день месяца со временем 23:59:59. В запросах аналог — КОНЕЦПЕРИОДА(Дата, МЕСЯЦ). Для отборов диапазоном это предпочтительнее ручного вычисления последнего дня.
Можно ли использовать НачалоМесяца в управляемой форме на клиенте?
Да, функция доступна в клиентском контексте управляемых форм. Однако если результат нужен для серверного запроса, надёжнее вычислить его на сервере с ТекущаяДатаСеанса(), чтобы избежать расхождений часовых поясов.
Как получить начало месяца из строки с датой?
Сначала преобразуйте строку в дату — например, через Дата(Год, Месяц, День) с разбором строки или штатные механизмы преобразования, — затем примените НачалоМесяца. Передавать строку напрямую нельзя: будет ошибка несоответствия типов.
Почему запрос с НачалоМесяца выдаёт ошибку?
Потому что в языке запросов этой функции нет. Замените её на НАЧАЛОПЕРИОДА(ПолеДаты, МЕСЯЦ) внутри текста запроса либо вычислите значение в модуле и передайте как параметр через УстановитьПараметр.
Как получить начало месяца для даты из документа в цикле выборки?
Эффективнее не вызывать функцию для каждой строки в коде, а сразу в запросе выбрать поле НАЧАЛОПЕРИОДА(Документ.Дата, МЕСЯЦ). Это выполняется на стороне СУБД и работает быстрее при больших объёмах данных.
Что важно запомнить
Начало месяца в коде получают функцией НачалоМесяца(Дата), в запросах — выражением НАЧАЛОПЕРИОДА(Дата, МЕСЯЦ). Для сдвига на другие месяцы используйте ДобавитьМесяц, на сервере берите ТекущаяДатаСеанса, а при сравнениях дат учитывайте время.