Перейти к содержанию

Работа с неоднозначными датами

Модуль date_utils.py решает проблему неоднозначных форматов дат, которые возникают при оптическом распознавании текста. Например, строка 03/05/2023 может означать как 3 мая (ДД/ММ/ГГГГ), так и 5 марта (ММ/ДД/ГГГГ). Вместо того чтобы угадывать единственный вариант, модуль хранит все возможные толкования и ищет пересечение при сравнении.

Поддерживаемые форматы

Формат Пример Когда неоднозначен
ДД.ММ.ГГГГ 25.12.2023 Если первое число не превышает 12
ДД/ММ/ГГГГ 03/05/2023 Если первое число не превышает 12
ДД-ММ-ГГГГ 03-05-2023 Если первое число не превышает 12
ГГГГ-ММ-ДД 2023-05-03 Никогда (международный стандарт)
ГГГГММДД 20230503 Никогда
ДД.ММ.ГГ 03.05.23 Если первое число не превышает 12
ДД/ММ/ГГ 03/05/23 Если первое число не превышает 12

Для двузначных годов значения до 50 трактуются как 20XX, от 50 и выше --- как 19XX.

Разбор всех толкований

Функция parse_date_interpretations принимает строку и возвращает список троек: дата, тип формата и уверенность.

Примеры:

"03/05/2023" → [(2023-05-03, "DMY", 0.5), (2023-03-05, "MDY", 0.5)]
"25/12/2023" → [(2023-12-25, "DMY", 1.0)]
"2023-05-03" → [(2023-05-03, "ISO", 1.0)]

Логика определения однозначности:

  • Если первое число больше 12 --- это точно день, формат ДД/ММ, уверенность 1.0.
  • Если второе число больше 12 --- это точно месяц, формат ММ/ДД, уверенность 1.0.
  • Если оба числа не превышают 12 --- возвращаются обе интерпретации с уверенностью 0.5.
  • Форматы ГГГГ-ММ-ДД и ГГГГММДД всегда однозначны, уверенность 1.0.

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

Точное сравнение

Функция compare_dates разбирает обе даты на множества толкований и ищет пересечение:

Реестр:   "03/05/2023" → {2023-05-03, 2023-03-05}
Документ: "2023-05-03" → {2023-05-03}
Пересечение: {2023-05-03} → совпадение найдено

Оценка уверенности зависит от однозначности обеих дат:

Ситуация Оценка
Обе даты однозначны, совпадение 1.0
Одна дата неоднозначна, пересечение найдено 0.95
Обе даты неоднозначны, уникальное пересечение 0.85
Пересечения нет 0.0

Сравнение с допуском

Функция compare_dates_with_tolerance проверяет все пары толкований и ищет такие, где разница не превышает заданного количества дней. Оценка уверенности уменьшается пропорционально расстоянию: каждый день отнимает до 20 % от базовой уверенности, но не опускается ниже 0.8.

Например, при допуске в 1 день:

"03/05/2023" и "2023-05-04" → совпадение (разница 1 день), оценка ≈ 0.8

Обратно совместимые функции

  • normalize_date --- возвращает одну дату в формате ГГГГ-ММ-ДД. При неоднозначности предпочитает формат ДД/ММ. Используется в местах, где нужно единственное значение.
  • get_all_date_normalizations --- возвращает список всех возможных нормализаций. Используется при построении указателей для поиска.
  • parse_date_to_datetime --- возвращает объект даты. При неоднозначности предпочитает формат ДД/ММ.

Где используется модуль

  • matching.py --- сопоставление документов с реестром: сравнение дат и построение указателя по датам.
  • registry_search.py --- поиск по строкам реестра.
  • tasks.py --- фоновая задача сравнения дат в обработчике Celery.
  • grouping.py --- определение, относятся ли два документа к одной группе, по совпадению дат.
  • registry_import.py --- нормализация значений дат при импорте строк реестра.