При автоматизации учета финансовых операций, особенно в случае интеграции с брокерскими отчетами, разработчики часто сталкиваются с фундаментальным ограничением платформы 1С:Предприятие — стандартный тип данных Дата поддерживает точность только до секунды. Если в рамках одной секунды происходит несколько сделок (что является нормой для биржевой торговли), стандартный механизм сортировки документов перестает гарантировать соблюдение последовательности ФИФО. Это приводит к некорректному расчету себестоимости и остатков ценных бумаг.
В этой статье мы подробно разберем, как обойти это ограничение, проанализируем различные подходы и выберем наиболее надежный метод для обеспечения высокой точности учета.
Рассмотрим ситуацию: в брокерском отчете зафиксированы две операции по одной и той же ценной бумаге. Первая сделка (покупка) прошла в 14:00:05.120, а вторая (продажа) — в 14:00:05.450. Для платформы 1С обе эти записи будут иметь время 14:00:05. Если записывать их "в лоб", порядок списания партий может нарушиться, так как система не увидит разницы во времени между ними. В худшем случае продажа может попытаться выполниться "раньше" покупки в рамках одной секунды, что вызовет ошибку нехватки остатков или неверный расчет прибыли.
В платформе 1С существует понятие МоментВремени. Это объект, состоящий из Даты и Ссылки на документ. В пределах одной и той же секунды документы упорядочиваются по уникальному идентификатору (GUID) ссылки. Рассмотрим особенности этого метода:
Вывод: Полагаться только на стандартный МоментВремени при загрузке внешних данных рискованно, так как порядок следования ссылок в базе данных может не соответствовать порядку сделок в отчете.
Это наиболее надежный и часто используемый на практике метод. Мы добавим в документ (или регистр) дополнительное числовое поле, которое будет отвечать за хранение миллисекунд или порядкового номера операции внутри секунды.
Проанализируем шаги реализации:
Миллисекунды с типом Число(3, 0).УПОРЯДОЧИТЬ ПО Дата, Миллисекунды.Рассмотрим пример кода для обработки строки времени в формате ISO 8601:
// Пример строки: "2023-10-27T10:00:00.456Z"
СтрокаВремени = "2023-10-27T10:00:00.456Z";
ПозицияТочки = Найти(СтрокаВремени, ".");
Если ПозицияТочки > 0 Тогда
МиллисекундыСтрокой = Сред(СтрокаВремени, ПозицияТочки + 1, 3);
Миллисекунды = Число(МиллисекундыСтрокой);
Иначе
Миллисекунды = 0;
КонецЕсли;
Для еще большей надежности, чтобы избежать зависимости от типа Дата при сортировке, мы можем хранить полное время операции в одном числовом поле. Это количество миллисекунд, прошедших с начала эпохи (1 января 1970 года).
Преимущества данного метода:
Для реализации в 1С (начиная с 8.3.10) можно использовать встроенные функции, если получение данных идет в реальном времени:
Мс = ТекущаяУниверсальнаяДатаВМиллисекундах();
// Записываем 'Мс' в реквизит с типом Число(15, 0)
Некоторые разработчики предпочитают прибавлять по 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-запросы является недопустимой — платформа просто "не увидит" эти данные или может работать с ними некорректно.
Рассмотрим пошаговый алгоритм внедрения надежного учета миллисекунд в вашу конфигурацию:
ТочноеВремя (Число, 15, 0). Обязательно установите для него свойство Индексировать.ТекущаяДата(). Извлекайте время именно из текстового файла или API брокера, так как задержка сетевого пакета может изменить реальную последовательность сделок.Вместо:
УПОРЯДОЧИТЬ ПО Ссылка.Дата
Используйте:
УПОРЯДОЧИТЬ ПО Ссылка.ТочноеВремя
Выясним еще одну важную деталь: точность системного таймера Windows. По умолчанию она составляет около 10-16 мс. Если ваш алгоритм сам генерирует время для сделок, используйте ТекущаяУниверсальнаяДатаВМиллисекундах(), но помните, что при очень высокой интенсивности (высокочастотный трейдинг) даже этой функции может быть недостаточно, и значения могут дублироваться. В таких случаях используйте дополнительный счетчик-итератор для каждой записи внутри транзакции.
Для решения проблемы миллисекунд в 1С мы рекомендуем отказаться от попыток "втиснуть" данные в стандартную Дату. Использование дополнительного числового поля для хранения Timestamp — это "золотой стандарт", который гарантирует точность ФИФО, сохраняет корректность календарных суток и обеспечивает высокую производительность при сортировке в запросах.