Строка 03/04/2026 может означать и 3 апреля, и 4 марта. Даже если программа успешно её разобрала, это ещё не доказывает, что выбран верный смысл. Сначала нужно установить порядок полей по документации источника, а затем проверить, существует ли такая календарная дата. Исходную строку при этом сохраняют, а неразрешённые случаи помечают отдельно.
Рассмотрим полностью вымышленный учебный набор из шести записей. В протоколе указано, что для D01, D02, D03, D04 и D06 порядок полей такой: день, месяц, четырёхзначный год. Для D05 правило неизвестно: запись поступила из другого условного источника, поэтому переносить на неё соглашение остальных строк нельзя. Реальный файл или интерфейс Excel не проверялся. Контрольный код запускался на этих учебных строках в CPython 3.12.14.
Сохраните исходные строки и правило источника
В рабочей копии оставим исходный текст в поле raw_date, а рядом добавим date_iso для разобранной даты и status для результата проверки. Это имена полей в нашем примере. Исходную строку не заменяем, а для неизвестного формата не подбираем дату по умолчанию.
| ID | Исходный текст и документированный порядок |
|---|---|
| D01 | 03/04/2026; день / месяц / год. |
| D02 | 04/03/2026; день / месяц / год. |
| D03 | 29/02/2024; день / месяц / год. |
| D04 | 29/02/2025; день / месяц / год. |
| D05 | 03/04/2026; порядок не установлен. |
| D06 | Пустая строка; для поля задан порядок день / месяц / год. |

Формат поля, источник и принятое решение полезно записать рядом с данными. Состав такого описания разобран в примере README для исследовательского набора. Для D05 фиксируем конкретный пробел: неизвестен порядок дня и месяца.
Почему обе даты могут пройти проверку
Если читать 03/04/2026 как «день, месяц, год», получится 2026-04-03, то есть 3 апреля. При порядке «месяц, день, год» та же запись означает 2026-03-04, то есть 4 марта. Обе даты существуют в календаре. Поэтому для D05 нельзя выбирать вариант только потому, что его приняла функция, он соответствует настройкам компьютера или похож на соседние строки.
Для D05 нужно найти документацию именно того источника, откуда пришла запись, или уточнить правило у его владельца. Пока этого не сделано, исходную строку сохраняют, поле с нормализованной датой оставляют пустым, а статусом отмечают неизвестный формат. С D01 ситуация другая: для неё порядок дня и месяца задан в условии.
Полный результат для шести записей
В рабочей таблице разобранные даты записаны в порядке «год, месяц, день». Неизвестный формат, недопустимая дата и пустая строка остаются разными состояниями.
| ID | date_iso и status |
|---|---|
| D01 | 2026-04-03; ok — разбор по заданному формату успешен. |
| D02 | 2026-03-04; ok — разбор по заданному формату успешен. |
| D03 | 2024-02-29; ok — такая дата допустима. |
| D04 | Не заполнено; invalid_date — 29 февраля 2025 года недопустимо. |
| D05 | Не заполнено; format_unknown — порядок полей не установлен. |
| D06 | Не заполнено; missing — исходная строка пуста. |
Все шесть исходных строк остаются на месте. D04 не исправляем на 28 февраля или 1 марта, для D05 не угадываем дату, а в D06 не подставляем ноль, 1900 год или сегодняшнее число. Условие не даёт оснований для таких замен.
| Статус | Количество и записи |
|---|---|
| ok | 3: D01, D02, D03. |
| invalid_date | 1: D04. |
| format_unknown | 1: D05. |
| missing | 1: D06. |
| Всего | 6 сохранённых строк: 3 + 1 + 1 + 1. |
Если расположить три успешно разобранные даты в календарном порядке, получится так: D03 (2024-02-29), D02 (2026-03-04), D01 (2026-04-03). Сортировка исходных строк в формате «день/месяц/год» отвечает на другой вопрос и может нарушить хронологию. А три остальные записи не становятся корректными датами оттого, что их перенесли в конец списка.
Законченный контрольный код
Метод datetime.strptime разбирает строку по явно переданному формату. В используемых шаблонах %d обозначает день месяца, %m — месяц, %Y — год с веком. Для нашего документированного порядка задано %d/%m/%Y; перестановка первых двух кодов задаёт другой порядок.
from datetime import datetime
rows = [
("D01", "03/04/2026", "%d/%m/%Y"),
("D02", "04/03/2026", "%d/%m/%Y"),
("D03", "29/02/2024", "%d/%m/%Y"),
("D04", "29/02/2025", "%d/%m/%Y"),
("D05", "03/04/2026", None),
("D06", "", "%d/%m/%Y"),
]
def parse_row(row_id, raw, fmt):
if raw == "":
return row_id, None, "missing"
if fmt is None:
return row_id, None, "format_unknown"
try:
value = datetime.strptime(raw, fmt).date().isoformat()
except ValueError:
return row_id, None, "invalid_date"
return row_id, value, "ok"
for row in rows:
print(*parse_row(*row))
Для этих шести строк контрольный код выдал следующий результат:
D01 2026-04-03 ok
D02 2026-03-04 ok
D03 2024-02-29 ok
D04 None invalid_date
D05 None format_unknown
D06 None missing
None в выводе означает, что нормализованное значение не сформировано; это не исходная строка «None» и не дата. Для D04 перехвачена ошибка ValueError. В более общем входе такая ошибка может означать и несоответствие шаблону, а не только календарно невозможную дату. Название invalid_date в этом небольшом примере относится к конкретной D04.
Этот код не обещает строгую проверку обязательных ведущих нулей или длины произвольной строки: strptime не нужно выдавать за такую проверку. Если в вашем проекте требуется точный внешний шаблон, его ограничения проверяют отдельно. Здесь проверены именно шесть явно приведённых входов. Распознавание календарной даты также не устанавливает часовой пояс или момент события — часы и смещения в этой задаче не рассматриваются.
Что записать в журнал решений
- Укажите, для каких строк порядок полей известен, и назовите документ, в котором он задан.
- Запишите, по какому шаблону разобраны D01, D02 и D03 и какие значения получены.
- Объясните, почему D04 получила статус invalid_date и почему её не заменяли самостоятельно.
- Зафиксируйте, что нужно выяснить о D05, прежде чем выбирать день и месяц.
- Отметьте, что D06 содержит пустую строку. Это отдельное состояние, не равное неизвестному формату или ошибочной дате.
- Запишите, что исходные шесть записей сохранены, а количество строк по всем итоговым статусам в сумме равно шести.
Связь такого решения с конкретной исходной строкой показывает пример журнала очистки данных. Успешный разбор трёх строк — проверяемый результат этого учебного случая; он не подтверждает правильность неизвестных дат или всего исследования.
Если нужна помощь с подготовкой собственного набора к расчётам, можно обсудить статистический анализ данных. Заранее согласуйте вопрос, происхождение файлов и объём консультации. Неопределённое правило источника сначала нужно установить, а не заменить догадкой программы.
Источник о методе разбора
Официальная документация Python 3.12: datetime описывает strptime, ошибки разбора и коды формата. Таблицы и данные выше — самостоятельный авторский учебный пример, а не скопированный набор из документации.