Получить количество дней в месяце 1с
В статье рассмотрен механизм учета производственных графиков и рабочих дней. Предложен простой и быстрый алгоритм решения типичных задач: добавление рабочих дней к дате и нахождение разницы между датами в рабочих днях. Все вычисления производятся исключительно запросом, т.е. решение пригодно для СКД и динамических списков.
Работа с производственными календарями, рабочими графиками часто встречается в практике разработки. Большинство задач можно свести к двум: 1) Добавить к дате (отнять от даты) некоторое количество рабочих дней и 2) найти разницу в рабочих днях между двумя датами. Несмотря на кажущуюся простоту, в этих задачах достаточно подводных камней, как методических, так и технологических. Естественно эта тема не была обойдена вниманием разработчиков типовых конфигураций и членов нашего сообщества. Простой поиск дает несколько результатов:
На мой взгляд, предлагаемые решения обладают теми или иными недостатками. В их числе:
- сложность полученных запросов: применение временных таблиц, использование группировок больших таблиц, получаемых в результате соединения
- не все решения хорошо работает с некоторыми входными данными, например в качестве входных параметров-дат могут быть использованы выходные дни
- некоторые решения предполагают дополнительную обработку программным кодом промежуточных данных, полученных в результате запроса
- часто решается узкая задача, т.е. решение не универсально.
Предлагаю свой вариант решения.
Постановка задачи:
Предположим, на предприятии ведется учет выполняемых работ. Каждая работа выполняется целое число дней, всегда начинается в начале дня, а заканчивается через несколько дней в конце дня. Продолжительность работ может быть от 1 дня, до нескольких лет (важность условия этого будет упомянута ниже). Необходимо иметь инструмент, позволяющий выполнять расчеты дат начала, окончания работ, продолжительностей работ, временных промежутков между работами. Все расчеты выполнять в рабочих днях. Решение должно позволять использование его в запросах.
В чем могут быть "подводные камни" при решении? Например токарь работает по стандартному рабочему графику - пятидневке. 01 апреля 2019 он начинает изготавливать деталь №1, тратит на ее изготовление 5 дней, и начинает изготавливать следующую деталь №2. Когда он закончит изготовление детали №1? Когда начнет изготавливать деталь №2? Казалось бы в обоих случаях ответ: через 5 рабочих дней после 01 апреля, т.е. к 01.04.2019 надо прибавить 5 рабочих дней. Но в первом случае ответ - 05.04.2019, а во втором - 08.04.2019.
Решение:
Решение поставленной задачи неожиданно получилось довольно простым.
Для учета рабочих графиков (производственных календарей) используем вспомогательный регистр сведений:
РабочийГрафик - ссылка на справочник "РабочиеГрафики" - если на предприятии используется несколько графиков (пятидневка, пятидневка с праздниками, семидневка и т.п.)
Дата - дата графика (без времени)
ЭтоРабочийДень - флаг рабочий/нерабочий день
КолВоДнейСНачалаПериода - Число рабочих дней, прошедших до начала даты записи, начиная с определенной, наперед заданной даты. В моем примере используется 01.01.2000.
Регистр необходимо заполнить на весь период, в пределах которого будут производится расчеты.
Теперь для нахождения разницы дат нам надо в регистре найти два числа, соответствующие этим датам и определить их разницу. Для добавления к дате некоторого числа рабочих дней, надо в регистре найти соответствующее дате число, добавить к нему число рабочих дней, и по результату найти в регистре соответствующую дату рабочего дня. Осталось учесть упомянутые выше сложности и получим следующее:
Примеры использования
Как видим запросы получаются довольно простыми, не используются ни временные таблицы, ни группировки с агрегатными функциями, ни постобработка. Ничего не мешает производить расчет в запросе для нескольких записей. В прилагаемом файле реализован пример отчета по выполненным работам: дана дата начала, предполагаемая плановая продолжительность работы и фактическая дата завершения, определяется плановая дата завершения и отставание факта от плана.
Может возникнуть вопрос: оправдано ли с точки зрения производительности использование дополнительного регистра такой структуры, ведь при изменении флага рабочего/выходного дня надо пересчитывать все записи с большей датой? Я считаю, что вполне. Во-первых, изменение производственного календаря происходит обычно не чаще одного раза в месяц, а полный пересчет и сохранение набора записей за 100 лет(~40000 записей) по выбранному графику занимает считанные секунды. А во-вторых, выгода от использования быстрого массового расчета как правило с лихвой перекроет все время, потраченное на предварительную подготовку.
А что же БСП?
Опытный разработчик, использующий БСП, может сказать: "Так ведь в БСП реализовано почти что то же самое!". Да, действительно в БСП есть аналогичный регистр:
Есть также программный интерфейс модулей "ГрафикиРаботы", "КалендарныеГрафики" с функциями "РазностьДатПоКалендарю", "ДатыПоГрафику" и т.п. Но если присмотреться, то можно увидеть, что в регистре имеется измерение "Год". То есть в этом регистре отсчет количества дней идет с начала каждого года. Когда мы работаем с датами в пределах одного года, то подход при расчете совпадает с рассмотренным. Но если даты попадают в разные года, а особенно если рассматривается промежуток в несколько лет, то алгоритм получается весьма сложным. Все интересующиеся могут самостоятельно сравнить объем программного кода в библиотеке и в предложенном решении. Скорее всего, разработчики БСП стремились к упрощению процедуры заполнения - каждый год рабочего графика заполняется отдельно и не зависит от других. Но в результате мы получаем существенное усложнение алгоритмов при решении практических задач. Я бы рекомендовал использовать регистры БСП как источник для заполнения регистра "РабочиеДни", а все дальнейшие операции производить уже с ним.
UPD 25.06.2019:
Для конфигураций с БСП добавлено заполнение регистра на основе данных из типовых объектов - регистра КалендарныеГрафики и справочника Календари. В процессе обработки заполняется регистр за период с 2000 г. по примерно 2109 г. - 40000 дней.
К статье приложена информационная база, в которой реализован описанный функционал, примеры отчетов, а также процедура заполнения и пересчета регистра.
Автоматическая выгрузка загрузка данных используя регламентное задание 12
Для обмена данными между программами необходимо сделать следующее: 1. При помощи Конвертации Данных создать правила выгрузки данных 2. Нужно чтобы в конфигурации была обработка УниверсальныйОбменДаннымиXML , желательно последней версии! (При помо Ввод данных по командировкам в программе ЗУП 0
Ввод сведений о командировках в программе 1С: Зарплата и управление персоналом 8 (ред.30) осуществляется в Разделе Кадры - Все кадровые документы - Создать - Командировка Откроется документ: Ввод сведений о командировках в программ Ввод дополнительного ежегодного отпуска 2
Вид расчета, используемый для начисления оплаты дополнительного ежегодного отпуска , описывается в плане видов расчета Основные начисления организаций . Новый вид расчета удобнее создать копированием предопределенного вида расчета Оплата отпуска п Вычислить возраст человека и выразить его прописью 0
Основная функция будет использовать в себе три вспомогательных: Функция РазностьМеждуДатамиВМесяцах(Дата1,Дата2) Год1 = Год(Дата1); Год2 = Год(Дата2); Месяц1 = Месяц(Дата1); Месяц2 = Месяц(Дата2); День1 = День(Дата1); День2 = День(Дата2); Рез Данные Графика регистра расчета 0
Виртуальная таблица " РегистрРасчета. ИмяРегистра .ДанныеГрафика " определена для тех регистров расчета, которые поддерживают период действия . При конфигурировании с таким регистром расчета необходимо связать непериодический регистр сведений кото Посмотреть все результаты поиска похожих
Еще в этой же категории
Момент Времени и Граница, назначение, примеры использования 39
Момент времени: Фирма 1С описывает так: Предназначен для получения и хранения момента времени для объекта в базе данных. Содержит дату и время, а также ссылку на объект базы данных. Используется в качестве значений свойств и параметров методо Преобразование даты 1С в unixtime (Unix Time Stamp) 17
Как известно, unixtime содержит количество секунд, прошедших с 1 января 1970 года. Поэтому, для преобразования даты 1С в дату unixtime нам всего то нужно от нашей даты отнять дату 01.01.1970 и перевести получившееся значения в удобоваримый формат. Функция месяц прописью 11
// пример от glory01 А = Формат(20020820153309, " ДФ=ММММ" ) // А = " Август" А = Формат(ТекущаяДата(), " ДФ=ММММ" ) // А = " Март" Функция МесяцПрописью(НомерМесяца) Экспорт НомерМесяца=Число(НомерМесяца); Если НомерМесяца = 1 Тогда Воз Как вычислить разницу между двумя датами в месяцах 11
Функция РазницаДатВМесяцах(Дата1, Дата2) Экспорт ДатаНач = ?(Дата1 Дата2, Дата1, Дата2); ДатаКон = ?(Дата1 Дата2, Дата2, Дата1); Годы = Год( датаКон ) - Год( датаНач ); Месяцы = Месяц( датаКон ) - Месяц( датаНач ); Разность = месяцы + Как вычислить разницу между двумя датами в часах и минутах 10
Функция РазностьВремени(Время1, Время2); Разность = Время1 - Время2; Если Разность 0 Тогда Часов = Цел(Разность / 3600); Минут = Цел((Разность - Часов * 3600) / 60); Возврат Дата(1, 1, 1, Часов, Минут, 0); Иначе Возврат Дата(1,1,1,0,0,0); Посмотреть все в категории Работа с Датами (Временем)
Ввод данных по командировкам в программе ЗУП 0
Ввод сведений о командировках в программе 1С: Зарплата и управление персоналом 8 (ред.30) осуществляется в Разделе Кадры - Все кадровые документы - Создать - Командировка Откроется документ: Ввод сведений о командировках в программ Ввод дополнительного ежегодного отпуска 2
Вид расчета, используемый для начисления оплаты дополнительного ежегодного отпуска , описывается в плане видов расчета Основные начисления организаций . Новый вид расчета удобнее создать копированием предопределенного вида расчета Оплата отпуска п Ввод по строке - поиск по первым символам или в любом месте наименования 6
При разработке конфигурации, для упрощении ввода документов потребовалось настроить ввод номенклатуры по совпадению любой части наименования! В 1С 8.3 по умолчанию настройки справочника номенклатуры такие: При такой настройке, механизм поиска в Журнал регистрации 0
Журнал регистрации относится к информационной базе и служит для сохранения информации о событиях, возникающих в процессе работы пользователей с данной информационной базой . Эта информация может быть важной с организационной точки зрения , но не Как в запросе одно строковое поле разделить на два ( ПОДСТРОКА )? 0
Задача состояла в том, что нужно было из реквизита документа Сответствие выделить две строки и сделать сортировку по ним. Соответствие счета, такого вида: 779000/004599. Как разбить это значение на два? У функции ПОДСТРОКА три параметра. В качестве Посмотреть все результаты поиска похожих
Еще в этой же категории
Как вычислить разницу между двумя датами в часах и минутах 10
Функция РазностьВремени(Время1, Время2); Разность = Время1 - Время2; Если Разность 0 Тогда Часов = Цел(Разность / 3600); Минут = Цел((Разность - Часов * 3600) / 60); Возврат Дата(1, 1, 1, Часов, Минут, 0); Иначе Возврат Дата(1,1,1,0,0,0); Перевод, преобразование Даты в Строку и Обратно 6
// Перевод Даты в Строку и Обратно //ТекущаяДата() - 28.02.2010 23:58:59 //Переведем текущую дату в строку СтрокаДата = Формат(ТекущаяДата(), " ггггММддЧЧммсс" ); // Получаем: 20100228235859 //Переведем строку в дату ТекДата = Дата(СтрокаДат Как вычислить количество дней между датами 6
Запрос=Новый Запрос(" ВЫБРАТЬ | РАЗНОСТЬДАТ( НачалоПериода, КонецПериода,МЕСЯЦ) КАК Месяцев, | РАЗНОСТЬДАТ( НачалоПериода, КонецПериода,ДЕНЬ) КАК Дней" ); // или КоличествоДней = (ДатаКонец - ДатаНачала) / 60 / 60 / 24; КоличествоДней = ДатаКо Разница между датами в рабочих днях, подсчет рабочих дней в 1С 5
Разрабатывая некий функционал в 1С, бывает, необходимо посчитать количество рабочих дней после какой-то даты. В этой статье примеры кода и запросы в которых считается количество рабочих дней: Код, при вычислении определяет только по дню недели, ви Как посчитать разницу между двумя датами? 5
Код уникален и сработает везде. Функция ПолучитьКоличествоДней() Счетчик = 1; НачалоПериода = Объект.НачалоПериода; Пока НачалоПериода Объект.КонецПериода Цикл Счетчик = Счетчик + 1; Посмотреть все в категории Работа с Датами (Временем)
Автоматическая выгрузка загрузка данных используя регламентное задание 12
Для обмена данными между программами необходимо сделать следующее: 1. При помощи Конвертации Данных создать правила выгрузки данных 2. Нужно чтобы в конфигурации была обработка УниверсальныйОбменДаннымиXML , желательно последней версии! (При помо Ввод данных по командировкам в программе ЗУП 0
Ввод сведений о командировках в программе 1С: Зарплата и управление персоналом 8 (ред.30) осуществляется в Разделе Кадры - Все кадровые документы - Создать - Командировка Откроется документ: Ввод сведений о командировках в программ Ввод дополнительного ежегодного отпуска 2
Вид расчета, используемый для начисления оплаты дополнительного ежегодного отпуска , описывается в плане видов расчета Основные начисления организаций . Новый вид расчета удобнее создать копированием предопределенного вида расчета Оплата отпуска п Ввод по строке - поиск по первым символам или в любом месте наименования 6
При разработке конфигурации, для упрощении ввода документов потребовалось настроить ввод номенклатуры по совпадению любой части наименования! В 1С 8.3 по умолчанию настройки справочника номенклатуры такие: При такой настройке, механизм поиска в Вычислить возраст человека и выразить его прописью 0
Основная функция будет использовать в себе три вспомогательных: Функция РазностьМеждуДатамиВМесяцах(Дата1,Дата2) Год1 = Год(Дата1); Год2 = Год(Дата2); Месяц1 = Месяц(Дата1); Месяц2 = Месяц(Дата2); День1 = День(Дата1); День2 = День(Дата2); Рез Посмотреть все результаты поиска похожих
Еще в этой же категории
Момент Времени и Граница, назначение, примеры использования 39
Момент времени: Фирма 1С описывает так: Предназначен для получения и хранения момента времени для объекта в базе данных. Содержит дату и время, а также ссылку на объект базы данных. Используется в качестве значений свойств и параметров методо Преобразование даты 1С в unixtime (Unix Time Stamp) 17
Как известно, unixtime содержит количество секунд, прошедших с 1 января 1970 года. Поэтому, для преобразования даты 1С в дату unixtime нам всего то нужно от нашей даты отнять дату 01.01.1970 и перевести получившееся значения в удобоваримый формат. Функция месяц прописью 11
// пример от glory01 А = Формат(20020820153309, " ДФ=ММММ" ) // А = " Август" А = Формат(ТекущаяДата(), " ДФ=ММММ" ) // А = " Март" Функция МесяцПрописью(НомерМесяца) Экспорт НомерМесяца=Число(НомерМесяца); Если НомерМесяца = 1 Тогда Воз Как вычислить разницу между двумя датами в месяцах 11
Функция РазницаДатВМесяцах(Дата1, Дата2) Экспорт ДатаНач = ?(Дата1 Дата2, Дата1, Дата2); ДатаКон = ?(Дата1 Дата2, Дата2, Дата1); Годы = Год( датаКон ) - Год( датаНач ); Месяцы = Месяц( датаКон ) - Месяц( датаНач ); Разность = месяцы + Как вычислить разницу между двумя датами в часах и минутах 10
Функция РазностьВремени(Время1, Время2); Разность = Время1 - Время2; Если Разность 0 Тогда Часов = Цел(Разность / 3600); Минут = Цел((Разность - Часов * 3600) / 60); Возврат Дата(1, 1, 1, Часов, Минут, 0); Иначе Возврат Дата(1,1,1,0,0,0); Посмотреть все в категории Работа с Датами (Временем)
В 1С значение типа «Дата» – это календарная дата григорианского календаря (с 01 января 0001 года по 31 декабря 3999 год) и время с точностью до 0,1 миллисекунды. Разработчику неизбежно приходится сталкиваться с данным типом, поэтому в этой статье предлагаю ознакомиться с его основными функциями и принципами работы.
«Дата» в модулях 1С
Как инициализировать дату
С помощью литерала встроенного языка
С помощью функции 1С Дата()
Как указать пустую дату
Функции для работы с датой
Получить текущую дату
Получить отдельные части даты
Следует заметить, что пробел в номере года вставляется при установках по умолчанию (подразумевается, что не установлен признак группировки в региональных установках).
Определить дату и время начала некоторого периода из даты
Для решения таких задач существует набор функций НачалоГода(), НачалоКвартала(), НачалоМесяца(), НачалоНедели(), НачалоДня(), НачалоЧаса(), НачалоМинуты(). В параметр задаётся значение даты начало периода, которого необходимо определить.
Определить дату и время конца некоторого периода из даты
Для получения конца периода из даты, можно использовать специальные функции НачалоГода(), НачалоКвартала(), НачалоМесяца(), НачалоНедели(), НачалоДня(), НачалоЧаса(), НачалоМинуты(). Параметр принимает значение «нашей даты», аналогично, как и в функции Начало…().
Определить номер недели или дня в году
Определить номер дня в неделе
Как отнять или прибавить к дате в 1С год, месяц, день, час, минуту, секунду
Если вы только начинаете программировать в 1С или просто хотите систематизировать свои знания - попробуйте Школу программирования 1С нашего друга Владимира Милькина. Пошаговые и понятные уроки даже для новичка с поддержкой учителя.
Попробуйте бесплатно по ссылке >>
Чтобы прибавить, вычесть месяц или год правильно использовать функцию ДобавитьМесяц(, ). Если параметру задать отрицательное значение, то число месяцев отнимается.
Формат даты в 1С
Функция Формат(, ). В параметре перечисляются параметры форматирования через символ «;». Возвращаемый тип строка.
Для задания параметра можно воспользоваться «конструктором форматной строки». При написании кода вызвать его не составляет труда. Необходимо только нажать правую кнопку «мыши» и из контекстного меню выбрать одноимённый конструктор.
На вкладке «Дата» задаём нужный нам формат.
Как вызвать диалоговое окно для ввода даты
Не модальный режим:
«Дата» в запросах 1С
Инициализация даты в запросах
Функция ДАТАВРЕМЯ()
Стоит отметить, что параметры данной функции принимают только литералы в отличие от схожей на неё функции для работы с датой в модулях Дата(). Например запись с передачей в функцию полей выборки из временной таблицы ДАТАВРЕМЯ(вт.Год, вт.Месяц, вт.День) выдаст ошибку.
Пустая дата
Текущая дата и работа с условием по дате в запросе
Так же не стоит забывать, что передать в запрос дату можно с помощью параметра. Для указания текущей даты это единственный вариант.
Получить отдельные части даты. Функции: ГОД, КВАРТАЛ, МЕСЯЦ, ДЕНЬ, ЧАС, МИНУТА, СЕКУНДА
В запросе получить отдельные части даты возможно с помощью одноимённых функций ГОД(), КВАРТАЛ(), МЕСЯЦ(), ДЕНЬ(), ЧАС(), МИНУТА(), СЕКУНДА().
Получить начало, конец некоторого периода
Существует две функции для решения таких задач. Соответственно НАЧАЛОПЕРИОДА(, ) и КОНЕЦПЕРИОДА(, ).
Где в параметр указывается «наша дата», а в параметр задаётся значение периода (Год, Полугодие, Квартал, Месяц, Декада, Неделя, День, Час, Минута).
Аналогично и для функции КОНЕЦПЕРИОДА().
Добавить сдвиг к дате
Для решения таких задач пригодится функция ДОБАВИТЬКДАТЕ(, , ). В параметр задаётся «наша дата», в параметр временной интервал (Год, Полугодие, Месяц и т.д.).
Использование функции РАЗНОСТЬДАТ()
Читайте также: