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

Период и момент

1С "выросла" из бухгалтерии. Поэтому в 7-ой версии тип "дата" был представлен с точностью до дня. Это соответствовало сложившейся задолго до появления компьютеров практике, а также одному из основных принципов бухгалтерского учета. А именно принципу существенности. Действительно, для бухгалтерского учета не так уж и важно в какую секунду произошло то или иное событие. Достаточно указать день.

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

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

Итак, теперь в восьмерке дата с точностью до секунды и просто остаток, без явного указания на его "начальность" или "конечность". Остаток на некий момент времени. А момент времени у нас в самом простом случае дата, т.е. секунда. Но секунда это ведь тоже период времени. У нее есть начало и есть конец. И когда мы обращаемся к платформенной функции получения остатка, мы получаем остаток на начало секунды. Так решили разработчики.

Вот тут кроется "засада". Мы отказались от понятий "начальный остаток" и "конечный остаток". Но понятия "начало периода" и "конец периода" никуда не делись. От них невозможно избавиться. Поэтому неопытный разработчик ничтоже сумняшеся пытается получить остаток, к примеру, "на конец месяца". Но конец месяца это может быть 31 января 23:59:59. Т.е. в системе понятий 1С конец это... начало! Но вовсе не начало следующего месяца, что было бы логичным. Конец месяца это начало последней секунды этого месяца. И если забыть об этом, то можно получить неверные результаты.

Очень неприятная особенность. Потому что она может "прятаться" до тех пор, пока не начнут вводить документы последней секундой месяца.

Уникальность момента

Вообще эта проблема имеет чуть ли не философский характер. Дело в том, что время это континуум. А наши информационные системы дискретны по своей сути. Поэтому моделирование времени в информационной системе та еще задача. В попытках решить ее, разработчики платформы ввели еще два понятия. "Момент времени" и "Граница". В одну и ту же секунду могут быть зарегистрированы тысячи документов. Платформа это позволяет. Момент и граница используются для навигации внутри секунды. И то и другое может включать в себя ссылку на документ. Момент времени используют, когда надо "встать" перед документом. Границу, когда надо "встать" сразу после документа (привет, начальный и конечный остаток!)

Как видите, не получилось упростить. Лично я считаю, что раз уж двинулись от дня в сторону континуума, то надо было к континууму и приходить. Т.е. определить тип дата с точностью до практической бесконечности. Это означало бы что все значения типа дата уникальны. В сущности, это сейчас и реализовывается с помощью "моментов" и "границ". Но лучше было бы упаковать это в один тип. Это логичнее, а кроме того решило бы еще одну проблему связанную со временем.

Речь идет о получении последних значений чего-либо. В 1С это называют "срез последних" и регистр сведений кое как умеет делать этот самый срез последних. В чем тут проблема. Мы конечно можем с помощью "моментов" и "границ" позиционироваться внутри секунды, но для хранения в базе мы используем тип "дата". И в типе "дата" у нас точность ограничена секундой. И теперь если, например, два значения зарегистрированы в одну секунду, у нас возникает необходимость решать, какое из этих двух значений будет последним.

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

Дата

Склад

Товар

Цена

01.01.23

Основной

Чайник

150

01.01.23

Основной

Кружка

110

21.02.23

Резервный

Чайник

160

21.02.23

Резервный

Кружка

120

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

Изменим таблицу.

Дата

Склад

Товар

Цена

01.01.23

Основной

Чайник

150

01.01.23

Основной

Кружка

110

01.01.23

Резервный

Чайник

160

01.01.23

Резервный

Кружка

120

Вот теперь у нас нет последних в принципе. Даже запрос выдаст по два значения для каждого товара и нам надо будет как-то выбирать из этих двух одно. Если бы тип "дата" подразумевал уникальность, у нас такой проблемы не было бы.

Машина времени

Но все эти проблемы меркнут по сравнению с тем, что у нас случается, когда мы ненароком запускаем машину времени. Обратите внимание, я пишу это словосочетание без кавычек. Что я имею ввиду. Мы регистрируем в нашей системе документы. Каждый документ имеет дату. В данном случае не важно какая точность у этой даты. По сути мы моделируем процессы, разворачивающиеся во времени. Но, при этом, мы сами находимся внутри временного потока (куда деваться!) Документы в информационной системе выстраиваются в определенном порядке, в соответствии с датами документов. Но и как таковая регистрация этих документов в информационной системе тоже происходит в каком-то порядке. И два этих порядка не обязаны совпадать. На практике, они и не совпадают почти никогда.

В этом не было бы ничего страшного, если бы не центральная концепция 1С, которая подразумевает связку документов с регистрами. Документ не только регистрируется в системе, он еще и "проводится", т.е. отражается в регистрах. И тут все зависит от того, как это отражение реализовано. Если отражение зависит только от самого документа, тогда проблем не будет. А если отражение зависит от других документов, например, мы считаем в момент проведения себестоимость по методу FIFO, то тут возникают трудно решаемые проблемы. Мы провели документ, себестоимость рассчиталась. После чего мы садимся в машину времени и проводим другой документ датой до того, который провели только что. Причем это "до" может быть сколь угодно далеко. Нашей машине времени бензин не нужен. Куда отправим, туда и доедет.

Понятно, что изменения, произведенные в прошлом, влекут за собой необходимость сделать пересчет с момента изменения и до... прекрасного будущего, которое наступит 1 января 4000 года (максимальная дата в 1С + 1 секунда). Такой пересчет не всегда реально сделать. Как по причине того, что это требует значительных вычислительных ресурсов. Так и по причине: "а мы уже сдали отчеты, не смейте ничего трогать!"

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

Заключение

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


Как определить, какой программный продукт 1С подойдёт именно вашему предприятию / проекту? Это обсудим с коллегами из OTUS на открытом уроке 21 июня. На этой встрече мы:

  • Изучим функционал казначейства во флагманских продуктах 1С.

  • Обсудим преимущества и недостатки двух подсистем.

  • Определим критерии, благодаря которым мы сможем принять правильное решение о выборе программного продукта 1С для внедрения.

Записаться на открытый урок можно на странице курса «Бизнес-аналитик 1С».

Комментарии (10)


  1. Asmody
    16.06.2023 15:12
    +1

    " проектировать документы, которые отражаются в регистры независимо от других документов или состояний регистров " - это прям как "За все хорошее против всего плохого" - звучит прекрасно, на практике не реализуемо.


    1. exwill Автор
      16.06.2023 15:12
      -1

      Почему же не реализуемо? Реализуемо. Было бы желание


      1. bazafaka
        16.06.2023 15:12

        Надеемся ваш следующий пост будет о изобретенной вами прорывной и не имеющей аналогов суверенной технологии расчёта себестоимости.


        1. exwill Автор
          16.06.2023 15:12

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


  1. dprotopopov
    16.06.2023 15:12
    +1

    Реальное время - это типовая ошибка многих разработчиков бухгалтерских программ.

    В банках (в АБС) - это более-менее утресли через понятие ОПЕРАЦИОННЫЙ ДЕНЬ - то есть это некая абстракция (с форматом даты) в рамках которой осуществляется учёт первичных документов и проводок.

    Соответственно, имеем операции:

    Открытие операционного дня - разрешение добавление записей с данной датой

    Закрытие операционного дня - запрещение добавления записей с данной датой и подведение итогов.

    PS

    В данный календарный день документы могут разноситься по нескольким открытым операционным дням.

    Закрывать операционные дни желательно в естессвенной последовательности

    PPS

    Это даже как-то решает проблемы филиалов в разных временных зонах

    PPPS

    Ну 1С-ники просто эконимили на обслуживающем персонале - то есть не пользуются кожанными мешками - операторами по управлению операционными днями, а полагаются на чьи-то часы (непонятно чьими)


    1. exwill Автор
      16.06.2023 15:12
      -1

      В банках своя атмосфера


    1. yukon39
      16.06.2023 15:12

      В банках свои причины работать с такой абстракцией как опердень. И одна из этих причин - легаси: изначально банковское с его объемами транзакций по другому просто не умело.

      Подобные подход применяли и в бухгалтерском ПО - тот же БЕСТ например. Да и в самой 1С в 6.0 так было, в 7.7 даже отдельная процедура была открытия нового периода, а в регистрах расчетов даже закрытие.

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

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

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


    1. darst
      16.06.2023 15:12

      Что-то такое пытались реализовать в "Рознице". Там тоже есть такое понятие открытие и закрытие смены.


  1. KivApple
    16.06.2023 15:12

    Мне кажется, не случайно в СУБД существуют отдельно типы Date, Time и DateTime. Потому что тип в БД это отражение предметной области и если в предметной области значима только дата, без времени, то и не должно быть времени.


  1. VaalKIA
    16.06.2023 15:12
    +1

    Автор гонит какую-то дичь. Во первых, в 1С8, у реквизитов есть ограничение типа, которое позволяет конкретизировать тип: Дата или ДатаВремя, поэтому любые запросы к базе данных будут типизироваться правильно.

    Во вторых, автор вообще не понимает что такое типы, время в языке 1С дискретно поэтому 23.59.59, это всё равно что индекс 9 у массива из 10 элементов, у него нет никакого состояния конца 9го элемента или начала следующего, это конретный индекс.

    В третьих, у ссылок, например, на документы, есть уникальный идентификатор, который можно считать ключём и если в массив по индексу 9 поместить пачку документов, то всегда можно их перебрать в порядке возрастания этого ключа, то есть выстроить в определённую последовательность и даже, это можно сделать с разными типами документов в перемешку (UIUD он такой). Но при этом доступ к этим документам, как было по индексу 9, так и остётся, очвидно, что как бы мы не перебирали элементы внутри пачки, на индекс 9 и его связь с пачкой это никак не влияет. Как показывает практика, порядок документов - важен и выборка пачки документов каждый раз в разном порядке, может сильно влиять на вычисления, поэтому в 1С дали возмоность с таким упорядочиванием работать, обозначив позицию в последовательности как момент времени, а ГраницаПериода всего лишь новый тип данных, который хранит одновремено два значения (Дата+UUID). Фактически, вместо примитивного типа, дали объект и методы работы с ним, но применимость у этого объекта весьма узкая, хоть и сильно упрощает многие моменты. Да в 1С много объектных фишек на уровне языка запросов, подобного SQL, но всё довольно примитивно. С введением, в новой платфоре, возможности работать с UUID в запросах, нет никаких сложностей полностью отказаться от момента времени и границы и сортировать "вручную" и резать последовательности по UUID, получая в точности тот же результат, но работая при этом раздельно со Ссылкой и с Датой. без всяких "непонятных" сущностей.

    Статья типичного гумманитария, который познаёт цифровой мир через бесконеч-вечное и настолько преисполнился в своей мудрости, что готов изложить центральные концепции машины времени и вести нас в прекрасное будущее, которое наступит 1 января 4000 года .