TL; DR: документация на Python не учитывает, что нулевой месяц заполнения необязателен.
>>> from datetime import datetime
>>> pattern = '%Y%m'
>>> datetime.strptime('20161', pattern).strftime(pattern)
'201601' # Note an extra "0" has appeared
время форматы для strptime
и strftime
приходят из стандартных C библиотек. Документация Python несколько не хватает нескольких важных деталей здесь, то relevant section в документации Python просто говорит:
% м Месяц как нулями десятичного числа.
Однако это также упоминается
Полный набор кодов форматов, поддерживаемых варьируется в зависимости от платформы, потому что Python вызывает функцию платформы C библиотеке STRFTIME(), а также вариации платформ являются общими.
поведение, которое вызывает удивительные результаты здесь, то есть обращение ведущих нулей, лучше документированы для C:
% Y Полный год {4}; ведущие нули должны быть разрешены, но не требуются. Ведущий символ «+» или «-» разрешается перед любыми ведущими нулями, но не требуется.
% m Номер месяца [01,12]; ведущие нули разрешены, но не требуются.
% d День месяца [01,31]; ведущие нули должны быть разрешены, но не требуются.
Emphasis mine. Источник here.
Так, с осознанием того, что ведущие нули могут или не могут присутствовать все случаи, упомянутые правильно учитываются:
datetime.strptime('200013', '%Y%m') # Can not parse
С 13 не действует месяц, разбор вынужден взять 1 - месяц с опущенными ведущими нулями. Затем вы получаете ValueError
, потому что парсер не знал, что делать с дополнительными данными «3».
datetime.datetime.strptime('200011', '%Y%m') # Parses to 1st Nov
Анализатор принимает ноябрь (11) как месяц. День просто по умолчанию равен 1. В качестве месяца здесь нельзя взять январь, потому что это оставит лишние данные без учета этого шаблона - будет лишний трейлинг «1». Поэтому парсер должен быть жадным и потреблять «11» за месяц.
datetime.datetime.strptime('200011', '%Y%m%d') # Parses to 1st Jan
Здесь мы видим, что '200011' может быть успешно разобран либо шаблон %Y%m
и %Y%m%d
. Если вы проанализируете шаблон %Y%m%d
, то вы должны принять месяц в качестве января (1), иначе нет оставшихся данных для заполнения %d
. Обратите внимание, что ведущие нули также являются необязательными для %d
.
Поскольку '% Y% m' будет анализироваться как' YYYYMM', поэтому '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'на вашем примере, –
"* Я не уверен, почему« 200011 »анализирует до 2000-01-01 с«% Y% m »как формат *» - это не так. Как показывает ваш код, он анализирует 2000-11-1. –
@ Robᵩ Спасибо, что заметили это! – cammil