1С вычесть дату из даты

Содержание

В 1С 8 нет специальной встроенной функции для программного добавления дней к переменной типа Дата. Но есть несколько способов, которые помогут в 1с прибавить к дате день.

Программно в 1с прибавить к дате день. Способ 1

К дате можно прибавлять (и убавлять) секунды, при помощи оператора +.

В одном дне: 24*60*60 = 86400 секунд.

Таким образом для добавления дня к дате к ней необходимо прибавить 86400.

Пример. Пусть в переменной МояДата содержится искомая дата.

ДатаПлюсДень = МояДата + 86400;

В 1с добавить день к дате. Способ 2

Если вам необходимо получить начало следующего дня от заданной даты, то можно воспользоваться встроенной функцией КонецДня(<Дата>), после чего добавить к полученной дате одну секунду.

Пример 2:

НоваяДата = КонецДня(МояДата) + 1;

Таким образом мы прибавили к концу заданного дня одну секунду и получили начало следующего дня.

Отметим, что для добавления месяцев в 1С 8 существует отдельная встроенная функция ДобавитьМесяц(<Дата>, <ЧислоМесяцев>). Для того что бы отнять необходимое количество месяцев, нужно что бы параметр ЧислоМесяцев был отрицательным.

Способ 3

Также добавить день к искомой дате в 1С 8 можно при помощи запроса. В языке запросов есть специальная функция ДОБАВИТЬКДАТЕ(<Дата>, <Тип>, <Количество>) предназначенная для изменения дат. Параметр Тип может принимать значения: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, НЕДЕЛЯ, МЕСЯЦ и т.д., что позволяет изменять даты на любые промежутки времени.

Пример 3.

Запрос = Новый Запрос; Запрос.УстановитьПараметр(«Дата», ТекущаяДата()); Запрос.Текст = «ВЫБРАТЬ | ДОБАВИТЬКДАТЕ(&Дата, ДЕНЬ, 1) КАК НоваяДата»; Результат = Запрос.Выполнить().Выбрать(); Результат.Следующий(); НоваяДата = Результат.НоваяДата;

Если вы не умеете писать запросы на встроенном языке 1с, то советую вам прочитать статью Язык запросов 1с — оператор Выбрать, в ней подробно описывается из каких блоков состоит запрос в 1С 8 и как его правильно использовать. После этой статьи прочтите следующую ее часть Запросы 1с 8 — Программная работа. Изучение языка запросов поможет вам стать более грамотным программистом. На этом все, теперь вы знаете три способа, как программно в 1с прибавить к дате день.

Для вычислений длительности временных интервалов удобней всего использовать недокументированную функцию РАЗНДАТ( ) , английский вариант DATEDIF().

Если Вам требуется рассчитать стаж (страховой) в годах, месяцах, днях, то, пожалуйста, воспользуйтесь расчетами выполненными в статье Расчет страхового (трудового) стажа в MS EXCEL .

Функции РАЗНДАТ( ) нет в справке EXCEL2007 и в Мастере функций ( SHIFT + F 3 ), но она работает, хотя и не без огрех.

Синтаксис функции:

РАЗНДАТ(начальная_дата; конечная_дата; способ_измерения)

Аргумент начальная_дата должна быть раньше аргумента конечная_дата .

Аргумент способ_измерения определяет, как и в каких единицах будет измеряться интервал между начальной и конечной датами. Этот аргумент может принимать следующие значения:

Значение

Описание

«d»

разница в днях

«m»

разница в полных месяцах

«y»

разница в полных годах

«ym»

разница в полных месяцах без учета лет

«md»

разница в днях без учета месяцев и лет ВНИМАНИЕ! Функция для некоторых версий EXCEL возвращает ошибочное значение, если день начальной даты больше дня конечной даты (например, в EXCEL 2007 при сравнении дат 28.02.2009 и 01.03.2009 результат будет 4 дня, а не 1 день). Избегайте использования функции с этим аргументом. Альтернативная формула приведена ниже.

«yd»

разница в днях без учета лет ВНИМАНИЕ! Функция для некоторых версий EXCEL возвращает ошибочное значение. Избегайте использования функции с этим аргументом.

Ниже приведено подробное описание всех 6 значений аргумента способ_измерения , а также альтернативных формул (функцию РАЗНДАТ() можно заменить другими формулами (правда достаточно громоздкими). Это сделано в файле примера ).

В файле примера значение аргумента начальная_дата помещена в ячейке А2 , а значение аргумента конечная_дата – в ячейке В2 .

1. Разница в днях («d»)

Формула =РАЗНДАТ(A2;B2;»d») вернет простую разницу в днях между двумя датами.

Пример1: начальная_дата 25.02.2007, конечная_дата 26.02.2007 Результат: 1 (день).

Этот пример показыват, что при подсчете стажа необходимо использовать функцию РАЗНДАТ() с осторожностью. Очевидно, что если сотрудник работал 25 и 26 февраля, то отработал он 2 дня, а не 1. То же относится и к расчету полных месяцев (см. ниже).

Пример2: начальная_дата 01.02.2007, конечная_дата 01.03.2007 Результат: 28 (дней)

Пример3: начальная_дата 28.02.2008, конечная_дата 01.03.2008 Результат: 2 (дня), т.к. 2008 год — високосный

Эта формула может быть заменена простым выражением =ЦЕЛОЕ(B2)-ЦЕЛОЕ(A2) . Функция ЦЕЛОЕ() округляет значение до меньшего целого и использована для того случая, если исходные даты введены вместе с временем суток ( РАЗНДАТ() игнорирует время, т.е. дробную часть числа, см. статью Как Excel хранит дату и время ).

Примечание : Если интересуют только рабочие дни, то к оличество рабочих дней между двумя датами можно посчитать по формуле =ЧИСТРАБДНИ(B2;A2)

2. Разница в полных месяцах («m»)

Формула =РАЗНДАТ(A2;B2;»m») вернет количество полных месяцев между двумя датами.

Пример1: начальная_дата 01.02.2007, конечная_дата 01.03.2007 Результат: 1 (месяц)

Пример2: начальная_дата 01.03.2007, конечная_дата 31.03.2007 Результат: 0

При расчете стажа, считается, что сотрудник отработавший все дни месяца — отработал 1 полный месяц. Функция РАЗНДАТ() так не считает!

Пример3: начальная_дата 01.02.2007, конечная_дата 01.03.2009 Результат: 25 месяцев

Формула может быть заменена альтернативным выражением: =12*(ГОД(B2)-ГОД(A2))-(МЕСЯЦ(A2)-МЕСЯЦ(B2))-(ДЕНЬ(B2)

Внимание : В справке MS EXCEL (см. раздел Вычисление возраста) имеется кривая формула для вычисления количества месяце между 2-мя датами:

=(ГОД(ТДАТА())-ГОД(A3))*12+МЕСЯЦ(ТДАТА())-МЕСЯЦ(A3)

Если вместо функции ТДАТА() — текущая дата использовать дату 31.10.1961, а в А3 ввести 01.11.1962, то формула вернет 13, хотя фактически прошло 12 месяцев и 1 день (ноябрь и декабрь в 1961г. + 10 месяцев в 1962г.).

3. Разница в полных годах («y»)

Формула =РАЗНДАТ(A2;B2;»y») вернет количество полных лет между двумя датами.

Пример1: начальная_дата 01.02.2007, конечная_дата 01.03.2009 Результат: 2 (года)

Пример2: начальная_дата 01.04.2007, конечная_дата 01.03.2009 Результат: 1 (год)

Подробнее читайте в статье Полный возраст или стаж .

Формула может быть заменена альтернативным выражением: =ЕСЛИ(ДАТА(ГОД(B2);МЕСЯЦ(A2);ДЕНЬ(A2))

4. Разница в полных месяцах без учета лет («ym»)

Формула =РАЗНДАТ(A2;B2;»ym») вернет количество полных месяцев между двумя датами без учета лет (см. примеры ниже).

Вся эта вакханалия нужна, например, для подсчета сколько полных дней, месяцев и лет прошло с определенной даты до сегодняшнего дня. Подробнее читайте в одноименной статье Сколько лет, месяцев, дней прошло с конкретной даты .

Формула может быть заменена альтернативным выражением: =ОСТАТ(C7;12) В ячейке С7 должна содержаться разница в полных месяцах (см. п.2).

5. Разница в днях без учета месяцев и лет («md»)

Формула =РАЗНДАТ(A2;B2;»md») вернет количество дней между двумя датами без учета месяцев и лет. Использовать функцию РАЗНДАТ() с этим аргументом не рекомендуется (см. примеры ниже).

Пример2: начальная_дата 28.02.2007, конечная_дата 28.03.2009 Результат2: 0, т.к. сравниваются конечная дата 28.03.2009 и модифицированная начальная дата 28. 03 . 2009 (год и месяц начальной даты заменяется годом и месяцем конечной даты)

Версия EXCEL 2007 с SP3:

Результат – 143 дня! Больше чем дней в месяце!

Версия EXCEL 2007:

Разница между 28.02.2009 и 01.03.2009 – 4 дня!

Причем в EXCEL 2003 с SP3 формула возвращает верный результат 1 день. Для значений 31.12.2009 и 01.02.2010 результат вообще отрицательный (-2 дня)!

Данная формула лишь эквивалетное (в большинстве случаев) выражение для РАЗНДАТ() с параметром md. О корректности этой формуле читайте в разделе «Еще раз о кривизне РАЗНДАТ()» ниже.

6. Разница в днях без учета лет («yd»)

Формула =РАЗНДАТ(A2;B2;»yd») вернет количество дней между двумя датами без учета лет. Использовать ее не рекомендуется по причинам, изложенным в предыдущем пункте.

Результат, возвращаемый формулой =РАЗНДАТ(A2;B2;»yd») зависит от версии EXCEL.

Еще раз о кривизне РАЗНДАТ()

Найдем разницу дат 16.03.2015 и 30.01.15. Функция РАЗНДАТ() с параметрами md и ym подсчитает, что разница составляет 1 месяц и 14 дней. Так ли это на самом деле?

Имея формулу, эквивалентную РАЗНДАТ() , можно понять ход вычисления. Очевидно, что в нашем случае количество полных месяцев между датами = 1, т.е. весь февраль. Для вычисления дней, функция находит количество дней в предыдущем месяце относительно конечной даты, т.е. 28 (конечная дата принадлежит марту, предыдущий месяц — февраль, а в 2015г. в феврале было 28 дней). После этого отнимает день начала и прибавляет день конечной даты = ДЕНЬ(КОНМЕСЯЦА(ДАТАМЕС(B6;-1);0))-ДЕНЬ(A6)+ДЕНЬ(B6) , т.е. 28-30+16=14. На наш взгляд, между датами все же 1 полный месяц и все дни марта, т.е 16 дней, а не 14! Эта ошибка проявляется, когда в предыдущем месяце относительно конечной даты, дней меньше, чем дней начальной даты. Как выйти из этой ситуации?

Модифицируем формулу для расчета дней разницы без учета месяцев и лет:

= ЕСЛИ(ДЕНЬ(A18)>ДЕНЬ(B18);ЕСЛИ((ДЕНЬ(КОНМЕСЯЦА(ДАТАМЕС(B18;-1);0))-ДЕНЬ(A18))

При применении новой функции необходимо учитывать, что разница в днях будет одинаковой для нескольких начальных дат (см. рисунок выше, даты 28-31.01.2015). В остальных случаях формулы эквивалентны. Какую формулу применять? Это решать пользователю в зависимости от условия задачи.

Дата — это один из примитивных типов данных существующих в 1С. Также как числа и строки используется абсолютно повсеместно, и следовательно знание основных функций и принципов работы с типом «Дата” приобретают просто драматическую важность.

В начале скажем, что значение типа дата в 1С содержит точную (с точностью до 0,1 миллисекунды) дату григорианского календаря.

Типовой порядок частей даты принятый в 1С — год, месяц, день, час, минута, секунда.

Собственно простейший способ создания новой переменной типа дата является приравнивание к переменной строки цифр в одинарных кавычках (обязательно) вида ‘ГГГГММДДччммсс’ где:

  • ГГГГ — четыре цифры года (включая тысячелетие и век);
  • ММ — две цифры месяца;
  • ДД — две цифры даты;
  • чч — две цифры часа (в 24-х часовом формате);
  • мм — две цифры минут;
  • сс — две цифры секунд.

Часы, минуты и секунды можно не указывать, при этом они приравниваются к нулю.

Функции работы с датами

Дата

Функция Дата() служит для создания значения типа «Дата”. Использовать ее можно двумя способами:

  • Дата(x) — где параметр «x” это строка вида «ГГГГММДДччммсс”, часы, минуты и секунды можно опустить, т.е. преобразуем строку в дату;
  • Дата(x, y, z, w, v, c) — в этом случае параметры «x”, «y”, «z”, «w”, «v” и «c” являются числами и означают год, месяц, день, час, минуту и секунду соответственно. Как и в предыдущем случае час, минуту и секунду можно опустить.

ТекущаяДата

Функция ТекущаяДата() просто возвращает текущую дату того компьютера на котором она исполняется. В клиент-серверных системах будет разумно инкапсулировать эту функцию в общем модуле (с исполнением на сервере) и использовать ее только таким образом.

1 2 3 4 &НаСервере Функция ДатаНаСервере(Команда) Возврат ТекущаяДата(); КонецФункции

ТекущаяУниверсальнаяДатаВМиллисекундах

Функция ТекущаяУниверсальнаяДатаВМиллисекундах() позволяет узнать дату в миллисекундах. Данная функция доступна начиная с версии платформы 8.2.17. Замечание о клиент-серверных системах из функции выше справедливо и для этой функции.

1 2 3 4 &НаКлиенте Процедура ТестДата(Команда) Сообщить(ТекущаяУниверсальнаяДатаВМиллисекундах()); //63 628 364 816 246 КонецПроцедуры

Год, Месяц, День, Час, Минута, Секунда

Начало…

Функции вида «Начало…(x)” получают дату в параметре «x” и возвращают дату начала периода времени в соответствии с названием конкретной функции. Существуют следующие функции:

  • НачалоГода;
  • НачалоКвартала;
  • НачалоМесяца;
  • НачалоНедели;
  • НачалоДня;
  • НачалоЧаса;
  • НачалоМинуты.

Конец…

Функции вида «Конец…(x)” получают дату в параметре «x” и возвращают дату окончания периода времени в соответствии с названием конкретной функции. Существуют следующие функции:

  • КонецГода;
  • КонецКвартала;
  • КонецМесяца;
  • КонецНедели;
  • КонецДня;
  • КонецЧаса;
  • КонецМинуты.

НеделяГода, ДеньГода

Функции НеделяГода(x) И ДеньГода(x) возвращают соответственно номер недели и номер дня в году для указанной даты «x”.

ДеньНедели

Функция ДеньНедели(x) возвращает номер дня недели для указанной даты «x”.

1 2 3 4 &НаКлиенте Процедура ТестДата(Команда) Сообщить(ДеньНедели(‘20170410’)); //1 КонецПроцедуры

ДобавитьМесяц

Функция ДобавитьМесяц(x, y) добавляет к дате «x” количество месяцев «y”, которое может быть отрицательным, в этом случае происходит вычитание месяцев из даты «x”.

МоментВремени

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

1 2 3 4 5 6 7 8 &НаКлиенте Процедура ТестДата(Команда) МоментВремени1 = Новый МоментВремени(‘20161231235959’, ТекущийДокумент); МоментВремени2 = ТекущийДокумент.МоментВремени(); Если МоментВремени1.Сравнить(МоментВремени2) = 0 Тогда КонецЕсли; КонецПроцедуры

ВвестиДату

Функция ВвестиДату(x, y, z) вызывает диалог для ввода даты, введенная дата записывается в переменную «x”, кроме этого можно указать подсказку «y”, а также какую часть даты нужно ввести «z” Функция возвращает Истина — если ввод был произведен, Ложь — если пользователь отказался от ввода.

Выглядит это окно примерно так:

Окно ввода даты

Типовые задачи представления данных

Разность даты в днях, количество дней между датами

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

Кроме этого можно воспользоваться функцией «РАЗНОСТЬДАТ» из языка запросов:

Таким образом можно узнать следующие типы разности дат:

  • СЕКУНДА;
  • МИНУТ;
  • ЧАС;
  • ДЕНЬ;
  • МЕСЯЦ;
  • КВАРТАЛ;
  • ГОД.

Разница между датами в месяцах, количество месяцев между датами

Здесь все в точности также, как и в предыдущем пункте.

Прибавить день к дате, вычесть день из даты, отнять от даты день

Прибавить месяц к дате, вычесть месяц из даты, отнять месяц от даты

Для прибавления/вычитания месяцев существует встроенная функция:

День недели по дате

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

Так как дата в 1С это по сути количество секунд прошедшее с начала нашей эры (т.е. число) то и сравнение производится так же как и числами. У объекта «МоментВремени» существует специальный метод «Сравнить» который позволяет сравнить один объект «МоментВремени» с другим.

1 2 3 4 5 6 &НаКлиенте Процедура ТестДата(Команда) Если МоментВремени1.Сравнить(МоментВремени2) = 0 Тогда Сообщить(«Моменты времени равны»); КонецЕсли; КонецПроцедуры

Дата равна нулю (проверка на заполненность), проверка на пустую дату

Если Вы нашли ошибку или неточность, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.

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

  • С помощью языка запросов;
  • С помощью арифметических операций.

Разберем первый способ. Для вычисления разности дат используется стандартная функция языка запросов РАЗНОСТЬДАТ, она имеет три параметра: первый параметр — вычитаемая дата; второй параметр — исходная дата; третий параметр — тип разности, одно из: СЕКУНДА, МИНУТА, ЧАС, ДЕНЬ, МЕСЯЦ, КВАРТАЛ, ГОД. Но помним, что функция рассчитывает календарную разницу между двумя датами, поэтому ее нельзя использовать в местах, где необходимо рассчитать количество банковских или рабочих дней между двумя датами.
Напишем функцию:
Функция ПолучитьРазностьДатВДняхЗапрос(НачалоПериода, КонецПериода)
Запрос = Новый Запрос;
Запрос.Текст =
«ВЫБРАТЬ
| РАЗНОСТЬДАТ(&ДатаНачалаПериода, &ДатаОкончанияПериода, ДЕНЬ) КАК Результат»;
Запрос.УстановитьПараметр(«ДатаНачалаПериода», НачалоДня(НачалоПериода));
Запрос.УстановитьПараметр(«ДатаОкончанияПериода», НачалоДня(КонецПериода));
РезультатЗапроса = Запрос.Выполнить();
ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();
КоличествоДней = 0;
Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
КоличествоДней = ВыборкаДетальныеЗаписи.Результат;
КонецЦикла;
Возврат КоличествоДней;
КонецФункции
Из плюсов данного способа можно отметить: простота реализации, не надо ничего делить и вычитать; третий параметр функции языка запросов, отвечающий за тип разности, можно параметризировать, то есть можно легко получить разность дат не только в днях, но и в минутах, часах и так далее. Из минусов стоит отметить исполнение функции только на стороне сервера, так как используется объект Запрос.
Во втором способе нужно уметь делить и знать сколько секунд в минуте, минут в часах и так далее. Если на платформе 1С произвести вычитание над датами, то получим целое число — это разница между датами в секундах. Если исходная дата больше чем вычитаемая, то получим положительное количество секунд, если исходная дата меньше чем вычитаемая, то отрицательное количество секунд.
Напишем функцию, которая будет вычислять разность между двумя датами в днях:
Функция ПолучитьРазностьДатВДнях(НачалоПериода, КонецПериода)
РазностьВСекундах = НачалоДня(КонецПериода) — НачалоДня(НачалоПериода);
КоличествоДней = Окр(РазностьВСекундах / 60 / 60 / 24);
Возврат КоличествоДней;
КонецФункции
Хочу заметить, что как и в первом способе, рассчитывается календарная разница между датами. Из плюсов хочу отметить исполнение функции в любом контексте, из минусов — для параметризации типа разности придется написать сочинение из условий или как-то так.
На практике мне встретился тот факт, что программисты предпочитают пользоваться первым способом, и я так же последовал этому мейнстриму и применил первый способ в одном из тяжелых алгоритмов, где вычисление разницы между двумя датами в днях выполнялось тысячи раз.
После запуска алгоритма огорчила скорость его выполнения, решил замерить производительность и выяснить где проседает алгоритм, и был бурно (бл#, пзд#ц) удивлен. Не малую часть времени уходит на вычисление разницы дат. После перехода на второй способ ситуация улучшилась.
Привожу демонстрацию замера производительности системы при вычислении разница дат обоими способами, выполнив 10000 раз (см. рисунок 1).

Рисунок 1. Замер производительности вычисления разности дат

Как видите, почти 70% от общего времени уходит на первый способ, и 30% на второй. Будьте внимательны, и проверяйте то, что советуют на просторах интернета.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *