К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как получить дату начала месяца в 1С

Как получить дату начала месяца в 1С: функция НачалоМесяца, примеры кода, запросы, типичные ошибки и проверка результата для разработчиков и пользователей.

Задача получить первое число месяца от произвольной даты встречается в 1С постоянно: при формировании отчётов за месяц, расчёте периодов в документах, отборах в запросах и обработках. Встроенный язык платформы содержит готовую функцию для этого — писать собственные вычисления через день, месяц и год не нужно.

Основной инструмент — функция НачалоМесяца(), которая принимает дату и возвращает дату, соответствующую первому числу того же месяца, с временем 00:00:00. Она работает одинаково в тонком клиенте, толстом клиенте и на сервере, не зависит от региональных настроек и корректно обрабатывает переходы через год.

Ниже разобраны синтаксис функции, готовые примеры кода, получение начала месяца в запросах, альтернативные способы и типичные ошибки, которые приводят к неверным периодам в отчётах и документах.

Функция НачалоМесяца: синтаксис и принцип работы

Функция объявлена в глобальном контексте встроенного языка и доступна без подключения общих модулей. Синтаксис предельно простой:

НачалоМесяца(<Дата>)

Единственный параметр — значение типа Дата. Результат — тоже значение типа Дата, у которого день установлен в 1, а время — в начало дня, то есть 00:00:00. Если передать, например, дату '20260315143000' (15 марта, 14:30), функция вернёт '20260301000000' — 1 марта, полночь.

Функция не изменяет исходное значение: даты в 1С передаются по значению, поэтому переменная, которую вы передали в НачалоМесяца, останется прежней. Результат нужно явно присвоить переменной или использовать в выражении.

Если передать пустую дату ('00010101000000'), функция вернёт ту же пустую дату — ошибки не будет, но и осмысленного результата тоже. Поэтому перед вызовом стоит проверять заполненность даты, особенно если она приходит из реквизита документа или параметра обработки.

Примеры кода для типовых сценариев

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

// Начало текущего месяца

НачалоТекущегоМесяца = НачалоМесяца(ТекущаяДатаСеанса());

// Начало месяца от даты документа

НачалоМесяцаДокумента = НачалоМесяца(Объект.Дата);

// Начало месяца от произвольной даты

ПроизвольнаяДата = Дата(2026, 6, 20, 15, 45, 0);

ПервоеЧисло = НачалоМесяца(ПроизвольнаяДата); // 01.06.2026 0:00:00

Обратите внимание на использование ТекущаяДатаСеанса() вместо ТекущаяДата(). В серверном коде и в клиент-серверном режиме правильнее опираться на дату сеанса — она учитывает часовой пояс информационной базы и не зависит от настроек компьютера пользователя.

Часто начало месяца нужно как граница периода отчёта. В паре с ним используется функция КонецМесяца(), которая возвращает последнее число месяца со временем 23:59:59:

ДатаНачала = НачалоМесяца(Отчет.Период);

ДатаОкончания = КонецМесяца(Отчет.Период);

bsl
ДатаНачала = НачалоМесяца(ТекущаяДатаСеанса());
ДатаОкончания = КонецМесяца(ТекущаяДатаСеанса());
Сообщить("Период: " + ДатаНачала + " - " + ДатаОкончания);

Начало месяца в запросах

В языке запросов функции встроенного языка недоступны — там используется собственная конструкция НАЧАЛОПЕРИОДА. Она принимает два параметра: выражение с датой и периодичность.

ВЫБРАТЬ

НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ) КАК НачалоМесяца,

СУММА(Продажи.СуммаОборот) КАК Сумма

ИЗ

РегистрНакопления.Продажи.Обороты КАК Продажи

СГРУППИРОВАТЬ ПО

НАЧАЛОПЕРИОДА(Продажи.Период, МЕСЯЦ)

Такая группировка — стандартный способ свернуть обороты до месяца. Вместо МЕСЯЦ можно указать ДЕНЬ, НЕДЕЛЯ, КВАРТАЛ, ГОД и другие периодичности, но для начала месяца нужен именно параметр МЕСЯЦ.

Если нужно отобрать записи только текущего месяца, вычислите границу в коде и передайте её в запрос параметром — это эффективнее, чем вычислять НАЧАЛОПЕРИОДА для каждой строки в условии ГДЕ:

Запрос.УстановитьПараметр("НачалоМесяца", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.Текст =

"ВЫБРАТЬ *

|ИЗ Документ.РеализацияТоваровУслуг КАК Реализация

|ГДЕ Реализация.Дата >= &НачалоМесяца";

Начало месяца произвольного периода: прошлый, следующий, смещение

На практике редко нужен только текущий месяц. Для смещения на заданное количество месяцев применяется функция ДобавитьМесяц(). Порядок вызова важен: сначала смещение, потом приведение к началу месяца — либо наоборот, в зависимости от задачи.

// Начало прошлого месяца

НачалоПрошлогоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДатаСеанса(), -1));

// Начало следующего месяца

НачалоСледующегоМесяца = НачалоМесяца(ДобавитьМесяц(ТекущаяДатаСеанса(), 1));

// Начало месяца, который был полгода назад

НачалоМесяцаСмещение = НачалоМесяца(ДобавитьМесяц(ТекущаяДатаСеанса(), -6));

Функция ДобавитьМесяц корректно обрабатывает крайние случаи: при добавлении месяца к 31 января результатом будет последний день февраля, а не несуществующая дата. Поэтому комбинация ДобавитьМесяц + НачалоМесяца безопасна для любых исходных дат.

Для вычисления начала месяца по номеру месяца в конкретном году удобен конструктор даты: НачалоМесяца = Дата(Год, НомерМесяца, 1). Это читаемее, чем арифметика с количеством секунд, и не подвержено ошибкам с длиной месяцев.

Порядок действий
  1. 1
    Определите исходную дату: текущая дата сеанса, дата документа или параметр отчёта
  2. 2
    Проверьте, что дата заполнена (не равна '00010101000000')
  3. 3
    При необходимости сместите период функцией ДобавитьМесяц
  4. 4
    Примените НачалоМесяца к полученной дате
  5. 5
    В запросе используйте НАЧАЛОПЕРИОДА(Поле, МЕСЯЦ) или передайте вычисленную границу параметром
  6. 6
    Проверьте результат выводом в сообщение или отладчиком

Проверка результата и контрольные точки

Убедиться, что дата начала месяца вычислена правильно, можно несколькими способами. Самый быстрый — вывести значение через Сообщить() или посмотреть в отладчике, поставив точку останова после вычисления.

Признаки корректного результата: день даты равен 1, время — 00:00:00, месяц и год совпадают с месяцем и годом исходной даты (если не было смещения через ДобавитьМесяц). Если время отличается от полуночи — скорее всего, вместо НачалоМесяца была использована исходная дата без обработки.

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

Контрольные точки

Как проверить результат

День полученной даты
Норма

Равен 1

Тревожный признак

Совпадает с днём исходной даты — функция не применена

Время полученной даты
Норма

00:00:00

Тревожный признак

Сохранилось исходное время, например 14:30:00

Месяц и год
Норма

Совпадают с исходной датой (без смещения)

Тревожный признак

Смещены на месяц — лишний вызов ДобавитьМесяц

Поведение на пустой дате
Норма

Возвращается пустая дата, есть проверка заполненности

Тревожный признак

Пустая дата попадает в запрос и ломает отбор

Типичные ошибки и ограничения

Первая распространённая ошибка — попытка получить начало месяца вычитанием дней: Дата - (День(Дата) - 1) * 86400. Такой код работает только при строгом контроле типов и времени, плохо читается и ломается при переходе на границу года, если день вычислен неверно. Встроенная функция решает задачу одной строкой.

Вторая ошибка — использование начала месяца как правой границы периода. Условие Дата <= НачалоМесяца(Дата) отберёт только документы ровно в полночь первого числа. Для правой границы нужен КонецМесяца или конструкция «меньше начала следующего месяца».

Третья ошибка — применение НачалоМесяца к строковому представлению даты. Функция принимает только тип Дата; если дата хранится как строка, её сначала нужно преобразовать, иначе будет ошибка выполнения. Аналогично в запросе НАЧАЛОПЕРИОДА не работает со строковыми полями.

Типичные ошибки
01
Вычисление через вычитание дней в секундах вместо НачалоМесяца — код хрупкий и трудно читается
02
Использование НачалоМесяца как конца периода — в выборку попадает только полночь первого числа
03
Вызов НачалоМесяца в тексте запроса — в запросах работает только НАЧАЛОПЕРИОДА
04
Передача незаполненной даты без проверки — пустая дата молча попадает в отборы
05
Использование ТекущаяДата() на сервере вместо ТекущаяДатаСеанса() — смещение периода из-за часового пояса

Альтернативные способы и когда они оправданы

Помимо НачалоМесяца, начало периода можно получить через функцию НачалоДня() в сочетании с конструктором даты: НачалоДня(Дата(Год(Д), Месяц(Д), 1)). Результат идентичен, но код длиннее — такой вариант оправдан только если внутри выражения уже вычисляются год и месяц для других целей.

В типовых конфигурациях (БСП — библиотека стандартных подсистем) есть общие модули для работы с датами, например функции получения начала периода в календарных расчётах. Если конфигурация построена на БСП, стоит использовать её механизмы для единообразия кода, но для простой задачи встроенной функции достаточно.

В пользовательском режиме без программирования начало месяца можно задать в настройках отчёта через стандартные варианты периода: «Этот месяц», «Прошлый месяц» и подобные. Это удобно для аналитиков и пользователей, которым не нужно писать код.

Сравнение вариантов

НачалоМесяца() в коде

Основной способ в модуле. Ограничение: только тип Дата на входе

НАЧАЛОПЕРИОДА в запросе

Для группировки и отборов в запросах. Не работает вне текста запроса

Дата(Год, Месяц, 1)

Когда известны номер месяца и год, а не готовая дата

Стандартный период в отчёте

Для пользователя без программирования; не подходит для произвольной логики

Итог

Что важно запомнить

Начало месяца в коде получают функцией НачалоМесяца(Дата), в запросах — НАЧАЛОПЕРИОДА(Поле, МЕСЯЦ). Для смещения по месяцам добавляйте ДобавитьМесяц, для правой границы периода — КонецМесяца. Перед вызовом проверяйте, что дата заполнена и имеет тип Дата.

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

Что вернёт НачалоМесяца, если передать пустую дату?

Функция вернёт пустую дату '00010101000000' без ошибки. Поэтому перед вызовом желательно проверять заполненность, иначе пустое значение может попасть в параметр запроса и исказить отбор.

Как получить начало месяца в запросе 1С?

Используйте конструкцию НАЧАЛОПЕРИОДА(ПолеДаты, МЕСЯЦ). Функцию НачалоМесяца из встроенного языка в тексте запроса вызвать нельзя — это разные синтаксисы.

Чем НачалоМесяца отличается от НачалоДня?

НачалоДня возвращает ту же дату с временем 00:00:00, не меняя число. НачалоМесяца дополнительно устанавливает день в 1. Для первого числа месяца результаты обеих функций совпадают.

Как получить начало прошлого месяца?

Скомбинируйте функции: НачалоМесяца(ДобавитьМесяц(ТекущаяДатаСеанса(), -1)). ДобавитьМесяц корректно обрабатывает переход через год и разную длину месяцев.

Почему в отчёт попадают лишние или не попадают нужные документы при отборе по месяцу?

Чаще всего границы периода заданы неверно: начало месяца использовано как правая граница или время в дате не сброшено. Правильная пара границ — НачалоМесяца и КонецМесяца от одной и той же даты.

Работает ли НачалоМесяца с високосными годами и 31 числом?

Да. Функция просто устанавливает день в 1 и время в полночь, поэтому исходное число месяца и високосность года на результат не влияют.