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

28.08.24

Разработка - Универсальные функции

Как оказалось, очевидное не всегда очевидно. Особенно для тех, кто только начинает создавать конфигурации на платформе "1С:Предприятие". Статья коснется вопросов работы с датами при написании программного кода.

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?]
Работа с датами в "1С:Предприятие":
.epf 9,63Kb
2
2 Скачать бесплатно

Начнем с самого простого. Всегда необходимо помнить, что при применении математических действий к датам, результат всегда будет в секундах. Если необходимо получить текущее время(в секундах) , необходимо от текущей даты отнять дату начала дня:

ТекущееВремя = ТекущаяДата() - НачалоДня(ТекущаяДата());
//36 728 = 28.08.2024 10:09:21 - 28.08.2024  0:00:00

Вставка 1.

 

1. Сравнение даты и времени.

Бывает необходимо сравнить дату имеющую тип дата только время, с текущим временем.  Например, при разработке систем контроля и учета рабочего времени, когда в конфигурации указывается время начала и конца рабочей смены (ВремяНачала - 08:00, ВремяКонца - 18:00). Если просто сравнивать с текущей датой, текущая дата будет всегда больше, потому что тип дата только время, возвращает дату в виде - 01.01.0001  8:00:00.  Для решения данной проблемы, можно получить значение обоих дат в секундах,  отняв от их значения нулевую дату.

НулеваяДата = Дата(01,01,0001,0,0,0);
//Значение нулевой даты будет 01.01.0001 0:00:00
ТекущееВремя = ТекущаяДата() - НачалоДня(ТекущаяДата());
//36 728 = 28.08.2024 10:09:21 - 28.08.2024  0:00:00
ВремяНачала = Дата(01,01,0001,8,00,00);
//Тип Дата только время
НачалоРабочегоДня = ВремяНачала - НулеваяДата;
//28 800 = 01.01.0001  8:00:00 - 01.01.0001 0:00:00

Вставка 2.

После этого сравнить количество секунд из обоих примеров и выполнить какие либо действия. Например:

Если ТекущееВремя > НачалоРабочегоДня Тогда
   //Как пример обозначает, что сотрудник опоздал. Соответственно
   //пишем программный код, обрабатывающий данное событие
КонецЕсли;

Вставка 3.

Так же, можно поступить по другому. Можно текущую дату привести к виду тип дата только время, и после этого производить сравнение:

НулеваяДата = Дата(01,01,0001,0,0,0);
ВремяНачала = Дата(01,01,0001,8,00,00);

ТекущееВремя = НулеваяДата + (ТекущаяДата() - НачалоДня(ТекущаяДата()));
//01.01.0001  8:39:09 = 01.01.0001 0:00:00 + 31 575

//Сравниваем даты (тип дата только время)
Если ТекущееВремя > ВремяНачала Тогда
   //Сотрудник опоздал
КонецЕсли;

Вставка 4.

Теперь попробуем узнать на какое время, все таки, опоздал сотрудник:

Опоздание = ВремяСейчас - НачалоРабочегоДня;
//10 965 = 39 765 - 28 800

ОпозданиеВремя = НулеваяДата + Опоздание;
//01.01.0001  3:02:45 = 01.01.0001 0:00:00 + 10 965
//Тип Дата только время

Вставка 5.

 

2. Разность дат.

Вот так, получим разность дат:

НулеваяДата = Дата(01,01,0001,0,0,0);
РазностьДат = ПроизвольнаяДатаВремя1 - ПроизвольнаяДатаВремя2;
//147 170 = 02.09.2024 17:26:55 - 01.09.2024  0:34:05
РазностьДатДата = НулеваяДата + РазностьДат;
//02.01.0001 16:52:50 = 01.01.0001 0:00:00 + 147 170

Вставка 6.

Нужно обратить внимание, что в результате добавился день. Может добавиться и месяц и год. Все зависит от того, на какой величины временной отрезок даты отстоят друг от друга. Так же необходимо помнить, что в нулевой дате уже присутствует один день, один месяц, и один год. Соответственно результат получится вида - 02.01.0001 16:52:50.  Мы можем используя стандартные функции платформы извлечь из даты необходимые нам данные, ну и дальше преобразовать их, как нам угодно. Вот эти функции:

ДатаГод     = Год(Дата);
ДатаМесяц   = Месяц(Дата);
ДатаДень    = День(Дата);
ДатаЧас     = Час(Дата);
ДатаМинута  = Минута(Дата);
ДатаСекунда = Секунда(Дата);

Вставка 7.

Вот так можно получить данные:

//Извлекаем из даты количество месяцев, дней, чесов, минут, секунд. Так как в нулевой дате уже 
//имеется один день, один месяц, один год, от полученных значений месяца и дня отнимаем 1
МесяцРазностьДатДата = Месяц(РазностьДатДата) - 1;
ДеньРазностьДатДата = День(РазностьДатДата) - 1;
ЧасРазностьДатДата = Час(РазностьДатДата);
МинутаРазностьДатДата = Минута(РазностьДатДата);
СекундаРазностьДатДата = Секунда(РазностьДатДата);
//В зависимости от полученных значений формируем сообщение пользователю
ТекстСообщения = "Разность дат составляет: "; 
//Если количество месяцев больше ноля, выводим месяцы в сообщении
Если МесяцРазностьДатДата > 0 Тогда
	ТекстСообщения = ТекстСообщения + "Месяцев - " + МесяцРазностьДатДата + " : ";
КонецЕсли;
//Если количество дней больше ноля, выводим дни в сообщении
Если ДеньРазностьДатДата > 0 Тогда
	ТекстСообщения = ТекстСообщения + "Дней - " + ДеньРазностьДатДата + " : ";
КонецЕсли;
//Добавляем к сообщению значения времени
ТекстСообщения = ТекстСообщения + "Часов - " + ЧасРазностьДатДата + " : Минут - " + МинутаРазностьДатДата + " : Секунд - " + СекундаРазностьДатДата;
//Выводим сообщение пользователю
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = ТекстСообщения ;
Сообщение.Сообщить();
//Разность дат составляет Дней - 1 : Часов - 16 : Минут - 52 : Секунд - 50

Вставка 8.

Деля и умножая значение даты в секундах, это в наших примерах РазностьДат, на 12, 24 или 60, можем получить количество лет, месяцев, дней, часов, минут, секунд:

//Дата в секундах
РазностьДат = 147 170;
//Количество часов
КоличествоЧасов = 147 170 / 60 / 60;
//Количество полных часов (40)
КоличествоПолныхЧасов = Цел(КоличествоЧасов);
//Количество минут из остатка (52)
КоличествоПолныхМинут = 60 * (КоличествоЧасов - КоличествоПолныхЧасов);

Вставка 9.

Ну и последнее в этом разделе, пример как от даты отнять время:

НулеваяДата = Дата(01,01,0001,0,0,0);
//От даты отнимаем время
РазностьДатаВремя = НулеваяДата + (ПроизвольнаяДатаВремя - ТолькоВремя);

Вставка 10.

 

3. Сложение дат.

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

Дата1Секунды = ПроизвольнаяДатаВремя1 - НулеваяДата;
//63 860 960 800 = 03.09.2024 11:46:40 - 01.01.0001 0:00:00
Дата2Секунды = ПроизвольнаяДатаВремя2 - НулеваяДата;
//63 860 745 600 = 01.09.2024  0:00:00 - 01.01.0001 0:00:00
СуммаДат = НулеваяДата + Дата1Секунды + Дата2Секунды;
//04.05.4048 11:46:40 =01.01.0001. 0:00:00 + 63 860 960 800 + 63 860 745 600

Вставка 11.

Необходимость сложения может возникнуть при расчете общего количества отработанного времени на предприятии, если сотрудник несколько раз увольнялся и повторно устраивался на работу. Допустим сотрудник работал с 01.01.2024 по 05.03.2024 затем уволился, но снова устроился на работу 20.07.2024 и работает по сей день. Например необходимо посчитать общее время которое он отработал:

НулеваяДата = Дата(01,01,0001,0,0,0);
//Первый период в секундах
ПервыйПериод = Период1Конец - Период1Начало;
//Второй период в секундах
ВторойПериод = ТекущаяДата() - Период2Начало;
//Общее количество отработанного времени тип Дата
ВсегоОтработано = НулеваяДата + ПервыйПериод + ВторойПериод;

//Или общее количество отработанного времени в секундах
ВсегоОтработано = ПервыйПериод + ВторойПериод;

Вставка 12.

Дальше, если необходимо получить количество в виде лет, месяцев, дней, часов, минут, секунд используем вариант на вставке 8.  если же нас интересует количество отработанных дней, часов, минут можно использовать вариант на вставке 9. 

Иногда, в частности при разработке систем контроля и учета времени, может понадобиться суммировать время. Смотри вставки 2 - 5. Как пример приведу функцию:

//ВидВозврата строка "Дата" либо "Секунда"

Функция СуммаВремя(ДатаККоторойПрибавить,ДатаСколькоПрибавить,ВидВозврата)

  Если ТипЗнч(ДатаККоторойПрибавить) <> Тип("Дата") ИЛИ ТипЗнч(ДатаСколькоПрибавить) <> Тип("Дата") Тогда
     //Если в параметрах передана не дата возвращаем пустую дату
     Возврат Дата(01,01,0001,0,0,0);
  КонецЕсли;

  Если ВидВозврата = "Дата" Тогда
     //Суммируем время
     РезультатСложения = ДатаККоторойПрибавить + (ДатаСколькоПрибавить - НулеваяДата);
     //Возвращаем сумму дат в виде даты
     Возврат РезультатСложения;
  ИначеЕсли ВидВозврата = "Секунда" Тогда
     //Получаем значение дат в секундах
     НулеваяДата = Дата(01,01,0001,0,0,0);
     Дата1 = ДатаККоторойПрибавить - НулеваяДата;
     Дата2 = ДатаСколькоПрибавить - НулеваяДата;
     РезультатСложения = Дата1 + Дата2;
     //Возвращаем сумму дат в виде количества секунд
     Возврат РезультатСложения;
  Иначе
     //Если третий параметр задан неправильно возвращаем пустую дату
     Возврат Дата(01,01,0001,0,0,0);
  КонецЕсли;

КонецФункции

Вставка 13.

Переменная СуммаВремя может быть какой то глобальной переменной, либо записью в регистре сведений и т. п.

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

дата1 = ТекущаяДата();
дата2 = дат1 + 0.1;
РавныЛи = дата1 = дата2;
//Ложь = 29.08.2024  9:04:00 = 29.08.2024  9:04:00
//Система визуально показывает, что даты одинаковые но они не равны!

Вставка 14.

Проверено на следующих конфигурациях и релизах:

  • Розница, редакция 3.0, релизы 3.0.3.169

Дата работа с датами сумма дат разность дат.

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Благодаря этим пяти строчкам можно больше не заморачиваться с загрузкой из внешних файлов. Пользуюсь везде, всегда и постоянно.

21.05.2024    17336    dimanich70    81    

135

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    3846    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    14439    atdonya    23    

56

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    5248    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    13678    YA_418728146    7    

165

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

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

2 стартмани

22.08.2023    3330    52    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18114    160    sapervodichka    112    

134
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. kuzyara 2077 28.08.24 11:06 Сейчас в теме
[FAQ 1С] » Работа с Датами (Временем)  
https://helpf.pro/faq/cat/36.html
eufes; alexsy; +2 Ответить
5. lv0v4ik 8 28.08.24 14:47 Сейчас в теме
(2) Спасибо за ссылку. Добавил себе в закладки. Хотя статья больше про выделение из даты времени и работы с ним.
3. SerVer1C 794 28.08.24 13:03 Сейчас в теме
Про самое интересное не написали: что можно к дате прибавить дробное значение секунд.
Визуально даты будут одинаковыми, но не равными программно. Вот где могут всплыть нежданчики.
дат1 = ТекущаяДата();
дат2 = дат1 + 0.1;
РавныЛи = дат1 = дат2;
Сообщить(дат1);
Сообщить(дат2);
Сообщить(РавныЛи);
4. lv0v4ik 8 28.08.24 14:44 Сейчас в теме
(3) Согласен. Только,если программист будет реализовать учетные задачи критичные к долям секунды, наверно он будет способен просчитать описанную вами ситуацию. Но все равно спасибо за Ваше уточнение, если Вы не против я его добавлю в статью. Статья писалась больше для тех кто впервые столкнулся с подобными задачами.
6. nuctoh 31 30.08.24 04:57 Сейчас в теме
Что за дичь я только что прочитал? Если надо временной интервал между датами, то я просто вычту из большей меньшую и прибавлю разность к нулевой дате. Одна строка кода:
Интервал = '00010101' + (ДатаБ - ДатаМ);
вместо монструозной процедуры.

С суммой еще бредовей. Если надо получить временной интервал, равный сумме времен суток (оставим вопрос - зачем вообще это может понадобиться), то делается это также одной строкой:
Интервал = '00010101' + (Дата1-НачалоДня(Дата1)) + (Дата2-НачалоДня(Дата2));
А в функции автора еще и косяк есть - если суммарных часов будет более 23, то 1С выдаст ошибку преобразования.

Вообще, этот опус выдает в авторе полнейшего нубаса в программировании - во-первых желание придумать свой непонятный способ решить простую задачу сложно, а во-вторых вместо "НЕ Вар1=Вар2" надо писать "Вар1<>Вар2" потому что "<>" это одна операция, а "НЕ =" - две, сравнения и отрицания.
7. lv0v4ik 8 04.09.24 13:07 Сейчас в теме
(6) Спасибо за Ваши советы. Я действительно не считаю себя гуру в программировании. Плохо, что в свое время, мне не попался кто то вроде Вас. Я перерыл море сайтов в интернете, везде описание только стандартных моментов работы с датами, типа период или прибавить день, час и т. п. Как я и написал в самом начале, не всегда очевидное - очевидно. Поэтому и написал статью для начинающих, надеясь дополнить ее, как раз опытом таких как Вы подключившихся к обсуждению.
8. nuctoh 31 28.09.24 06:31 Сейчас в теме
(7) достаточно почитать правила преобразования типов в 1С в базовом курсе и чуть чуть подумать. Да, и использовать главный принцип 1С, которого надо придерживаться примерно всегда при разработке - решай задачу максимально простым и тривиальным способом, иногда даже в ущерб производительности - чтобы человек, который будет дорабатывать твой код, понял что код делает и не сломал его.
Оставьте свое сообщение