Как реализовать учет миллисекунд в 1С для корректного списания по ФИФО?

Программист 1С v8.3 (Управляемые формы) Управленческий учет Финансы и профессиональные услуги
← На главную

При автоматизации учета финансовых операций, особенно в случае интеграции с брокерскими отчетами, разработчики часто сталкиваются с фундаментальным ограничением платформы 1С:Предприятие — стандартный тип данных Дата поддерживает точность только до секунды. Если в рамках одной секунды происходит несколько сделок (что является нормой для биржевой торговли), стандартный механизм сортировки документов перестает гарантировать соблюдение последовательности ФИФО. Это приводит к некорректному расчету себестоимости и остатков ценных бумаг.

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

Почему стандартной даты недостаточно?

Рассмотрим ситуацию: в брокерском отчете зафиксированы две операции по одной и той же ценной бумаге. Первая сделка (покупка) прошла в 14:00:05.120, а вторая (продажа) — в 14:00:05.450. Для платформы 1С обе эти записи будут иметь время 14:00:05. Если записывать их "в лоб", порядок списания партий может нарушиться, так как система не увидит разницы во времени между ними. В худшем случае продажа может попытаться выполниться "раньше" покупки в рамках одной секунды, что вызовет ошибку нехватки остатков или неверный расчет прибыли.

Вариант 1. Использование механизма «Момента времени»

В платформе 1С существует понятие МоментВремени. Это объект, состоящий из Даты и Ссылки на документ. В пределах одной и той же секунды документы упорядочиваются по уникальному идентификатору (GUID) ссылки. Рассмотрим особенности этого метода:

  1. Оперативное проведение: При оперативном проведении (в реальном времени) платформа гарантирует, что каждый следующий документ будет иметь "момент времени" больше, чем предыдущий.
  2. Загрузка исторических данных: При загрузке брокерского отчета "задним числом" мы создаем объекты программно. Порядок генерации ссылок (GUID) не всегда совпадает с хронологией сделок в файле. UUID версии 4, используемый в современных системах, не гарантирует возрастания.
  3. Метод УстановитьМоментВремени(): Мы можем использовать этот метод, но он работает ограниченно.

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

Вариант 2. Добавление дополнительного реквизита «Миллисекунды»

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

Проанализируем шаги реализации:

  1. Добавим в документ реквизит Миллисекунды с типом Число(3, 0).
  2. При чтении брокерского отчета (например, из JSON или CSV) будем извлекать дробную часть времени.
  3. При проведении документа в запросах по расчету остатков будем использовать УПОРЯДОЧИТЬ ПО Дата, Миллисекунды.

Рассмотрим пример кода для обработки строки времени в формате ISO 8601:


// Пример строки: "2023-10-27T10:00:00.456Z"
СтрокаВремени = "2023-10-27T10:00:00.456Z";
ПозицияТочки = Найти(СтрокаВремени, ".");
Если ПозицияТочки > 0 Тогда
    МиллисекундыСтрокой = Сред(СтрокаВремени, ПозицияТочки + 1, 3);
    Миллисекунды = Число(МиллисекундыСтрокой);
Иначе
    Миллисекунды = 0;
КонецЕсли;

Вариант 3. Использование числового Timestamp (Unix Time)

Для еще большей надежности, чтобы избежать зависимости от типа Дата при сортировке, мы можем хранить полное время операции в одном числовом поле. Это количество миллисекунд, прошедших с начала эпохи (1 января 1970 года).

Преимущества данного метода:

Для реализации в 1С (начиная с 8.3.10) можно использовать встроенные функции, если получение данных идет в реальном времени:


Мс = ТекущаяУниверсальнаяДатаВМиллисекундах();
// Записываем 'Мс' в реквизит с типом Число(15, 0)

Вариант 4. Искусственное смещение времени («Виртуальные секунды»)

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

Сделка 1: 12:00:00.100 -> Записываем как 12:00:00

Сделка 2: 12:00:00.200 -> Записываем как 12:00:01

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

Особенности работы с СУБД

Важно понимать, как 1С взаимодействует с базой данных (например, MS SQL Server). Тип данных DATETIME в SQL технически поддерживает точность до 3.33 миллисекунды. Однако платформа 1С при записи данных принудительно обнуляет значения миллисекунд. Поэтому попытка записать миллисекунды напрямую в стандартное поле через прямые SQL-запросы является недопустимой — платформа просто "не увидит" эти данные или может работать с ними некорректно.

Практические рекомендации по реализации

Рассмотрим пошаговый алгоритм внедрения надежного учета миллисекунд в вашу конфигурацию:

  1. Создание реквизитов: В документах сделок создайте реквизит ТочноеВремя (Число, 15, 0). Обязательно установите для него свойство Индексировать.
  2. Загрузка данных: При парсинге отчета брокера не полагайтесь на функции 1С типа ТекущаяДата(). Извлекайте время именно из текстового файла или API брокера, так как задержка сетевого пакета может изменить реальную последовательность сделок.
  3. Работа с регистрами: Если вы используете Регистры Сведений, в измерениях также должно присутствовать поле с миллисекундами (или Timestamp). В Регистре Накопления (для ФИФО) порядок будет определяться позицией регистратора, поэтому важно, чтобы выборка документов при проведении была строго упорядочена по вашему новому полю.
  4. Корректировка запросов: Во всех алгоритмах списания партий (ФИФО) замените стандартную сортировку.

    Вместо:

    УПОРЯДОЧИТЬ ПО Ссылка.Дата

    Используйте:

    УПОРЯДОЧИТЬ ПО Ссылка.ТочноеВремя

Проблема системного таймера

Выясним еще одну важную деталь: точность системного таймера Windows. По умолчанию она составляет около 10-16 мс. Если ваш алгоритм сам генерирует время для сделок, используйте ТекущаяУниверсальнаяДатаВМиллисекундах(), но помните, что при очень высокой интенсивности (высокочастотный трейдинг) даже этой функции может быть недостаточно, и значения могут дублироваться. В таких случаях используйте дополнительный счетчик-итератор для каждой записи внутри транзакции.

Заключение

Для решения проблемы миллисекунд в 1С мы рекомендуем отказаться от попыток "втиснуть" данные в стандартную Дату. Использование дополнительного числового поля для хранения Timestamp — это "золотой стандарт", который гарантирует точность ФИФО, сохраняет корректность календарных суток и обеспечивает высокую производительность при сортировке в запросах.

← На главную