Ошибки Python strptime при разборе вывода strftime

Я пытаюсь сохранить дату в удобочитаемом формате. Для этого я сохраняю и считываю строку, содержащую дату. Я использую date.min для обозначения даты перед любой другой.

from datetime import datetime, date

d = date.min
s = datetime.strftime(d, "%Y-%m-%d")
print(s) 
# 1-01-01

d2 = datetime.strptime(s, "%Y-%m-%d")
# ValueError: time data '1-01-01' does not match format '%Y-%m-%d'

Однако, когда я пытаюсь проанализировать дату, используя strptime, которая была выведена strftime, я получаю только ошибку. Кажется, что strptime ожидает ведущие нули, такие как 0001, которые strftime не выводит.

Можно было бы использовать None. Есть ли другие способы обойти то, что мне кажется ошибкой?


person user3141592    schedule 03.01.2021    source источник
comment
Я не получаю сообщение об ошибке на 3.9, какая у вас версия Python? Также почему вы используете метод format?   -  person Mandera    schedule 03.01.2021
comment
Я использую версию 3.8.5. Какой еще метод вы бы предложили мне использовать?   -  person user3141592    schedule 03.01.2021
comment
Я также не получаю ошибок с вашим кодом. Он генерирует 0001-01-01, а не 1-01-01 (Python 3.9). Также s=f'{date.min:%Y-%m-%d}' является более прямым способом создания строки.   -  person Mark Tolonen    schedule 03.01.2021
comment
Метод format у вас лишний, достаточно s = datetime.strftime(d, "%Y-%m-%d")   -  person Mandera    schedule 03.01.2021
comment
@MarkTolonen зависит от платформы. Я получаю 1 в Linux, но 0001 в Windows   -  person Nick    schedule 03.01.2021
comment
@Nick Спасибо, я искал отчет об ошибке.   -  person user3141592    schedule 03.01.2021
comment
Не благодарите меня, благодарите ответившего...   -  person Nick    schedule 03.01.2021
comment
@Nick Я только что заметил, что ... также в документации говорится, что %Y делает 0001 и т. Д., Но нашел примечание ниже, что это зависит от платформы.   -  person Mark Tolonen    schedule 03.01.2021


Ответы (3)


Вам нужно добавить ведущие нули:

попробуйте заменить:

s = {datetime.strftime(d, "%Y-%m-%d")}

с:

s = f'{d.year:04d}-{datetime.strftime(d, "%m-%d")}'

Если вы хотите легко работать с датами, я могу порекомендовать библиотеку Arrow.
https://pypi.org/project/arrow/

person Daniel Gilon    schedule 03.01.2021
comment
Оба ответа работают, но я нахожу этот способ заполнения немного более элегантным. Или используйте обновленную версию Python с исправленной ошибкой. - person user3141592; 03.01.2021
comment
Мне нравится решение @mhawke, так как оно не требует форматирования. - person Daniel Gilon; 03.01.2021
comment
@DanielGilon: спасибо, тогда вы можете подумать о голосовании :) - person mhawke; 03.01.2021

Python 3.9 в Linux демонстрирует проблему, как и ожидалось во многих комментариях к этому вопросу. Одним из обходных путей, который должен работать на всех платформах, является использование формата ISO для строки даты с date.isoformat():

>>> from datetime import date, datetime
>>> s = date.min.isoformat()
>>> s
'0001-01-01'
>>> d = datetime.strptime(s, "%Y-%m-%d")
>>> d
datetime.datetime(1, 1, 1, 0, 0)
>>> assert d.date() == date.min

Вместо этого вы также можете использовать date.fromisoformat(). из strptime():

>>> date.fromisoformat(date.min.isoformat())
datetime.date(1, 1, 1)
person mhawke    schedule 03.01.2021

strftime не может добавлять ведущие нули к году. Он вызывает базовую функцию C, и его поведение при добавлении начальных нулей к году зависит от платформы. Вы можете обойти это, отформатировав объект даты самостоятельно. Просто проверьте, меньше ли d.year 1000, и добавьте необходимое количество начальных нулей:

d = date.min
year_str = ''.join(['0' for _ in range(4 - len(str(d.year)))]) + str(d.year)
s = '{year}-{md}'.format(year=year_str, md=datetime.strftime(d, "%m-%d"))
d2 = datetime.strptime(s, "%Y-%m-%d")
# now d2 is equal to datetime.datetime(1, 1, 1, 0, 0)
person Ali Tou    schedule 03.01.2021