2016-11-28 7 views
0

Я не уверен, почему «200011» анализирует до 2000-11-01 с «% Y% m» в качестве формата, когда «200013» с «% Y% m» терпит неудачу, а «200011» - «% Y% m% d 'преуспевает. См. Код:Какова логика анализа даты и времени с годами и месяцами?

>>> datetime.datetime.strptime('200013', '%Y%m') 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
    File ".../lib/python3.5/_strptime.py", line 510, in _strptime_datetime 
    tt, fraction = _strptime(data_string, format) 
    File ".../lib/python3.5/_strptime.py", line 346, in _strptime 
    data_string[found.end():]) 
ValueError: unconverted data remains: 3 
>>> datetime.datetime.strptime('200011', '%Y%m') 
datetime.datetime(2000, 11, 1, 0, 0) 
>>> datetime.datetime.strptime('200011', '%Y%m%d') 
datetime.datetime(2000, 1, 1, 0, 0) 

Любые идеи, что происходит?

+0

Поскольку '% Y% m' будет анализироваться как' YYYYMM', поэтому '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'на вашем примере, –

+0

"* Я не уверен, почему« 200011 »анализирует до 2000-01-01 с«% Y% m »как формат *» - это не так. Как показывает ваш код, он анализирует 2000-11-1. –

+0

@ Robᵩ Спасибо, что заметили это! – cammil

ответ

3

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.

2

Там нет соответствующего месяца для целого числа 13, так что вам придется добавить спецификатор для разбора 3 после 1 был проанализирован как месяц:

>>> datetime.datetime.strptime('200013', '%Y%m%d') 
datetime.datetime(2000, 1, 3, 0, 0) 

'200011' работы, потому что 11 соответствует ноябрю и может быть безопасно проанализирован как месяц, в то время как день по умолчанию равен 1, если не указано.

+0

Это правильный ответ. Я действительно не знаю, почему кто-то отказался от этого. –

+1

Но% m и% d должны быть 2 цифры? Итак, почему они соответствуют отдельным цифрам? – cammil

0

Пример: месяц, день, час и мин отсутствует, поэтому они устанавливаются значения по умолчанию:

datetime.datetime.strptime ('2000', '% Y') даты и времени .datetime (2000, 1, 1, 0, 0)

месяц, час и мин установлено значение по умолчанию:

datetime.datetime.strptime ('200012', '% Y% d') datetime.datetime (2000, 1, 12, 0, 0)

В вашем примере, его искали в месяц в качестве второго пар, но нет «13» месяца - datetime.datetime.strptime («200013», «% Y% м»)

но когда вы говорите, DateTime .datetime.strptime ('200013', '% Y% m% d '), он ищет год: 2000, месяц, с 13 недействителен, занимает 1 месяц и 3 как день

Наконец, в этом случае: datetime.datetime.strptime (' 200011 ' , '% Y% m'), он ищет год, 2000 год действителен, ищет месяц, 11 - месяц. Теперь rest установлен в значения по умолчанию (точно так же, как примеры, которые я дал на самом верху).

На этой заметке следующая команда, по умолчанию месяц и занимает 13 в качестве действительной даты.

datetime.datetime.strptime ('200013', '% Y% d') datetime.datetime (2000, 1, 13, 0, 0)

 Смежные вопросы

  • Нет связанных вопросов^_^