python3 fromtimestamp генерирует ошибку OSError - PullRequest
0 голосов
/ 25 мая 2020

Мы столкнулись с интересной проблемой mtime, с которой столкнулись в этой области. Я планирую отправить отчет об ошибке, но хотел получить информацию со стороны.

Файл, хранящийся на сервере windows, имел дату последнего изменения '1/1/4501' (это 4501 год. ). os.path.getmtime() возвращает действительную метку времени, но когда мы пытаемся передать ее обратно в datetime.datetime.fromtimestamp(), мы получаем OSError.

Есть несколько дискуссий по SO, которые обсуждают эту проблему, например: Python fromtimestamp OSError . Однако в большинстве случаев, которые мы могли найти, ОП имели дело с датами производства, которые явно выходили за пределы поддерживаемого диапазона эпохи платформы. Генерация OSError, когда дата превышает поддержку эпохи на Windows, согласуется с python документами.

В нашем случае дата явно поддерживается Windows, о чем свидетельствует ее хранение в файловая система. Далее, мы можем воспроизвести ситуацию с помощью утилиты cygwin touch.

>>> import os, datetime
>>> os.system('touch -d "4501-01-01" file.txt')
>>> t = os.path.getmtime('file.txt')
>>> datetime.datetime.fromtimestamp(t)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

Что интересно, мы можем вручную преобразовать его с привязкой к эпохе

>>> datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=t)
datetime.datetime(4501, 1, 1, 5, 0)

Мы использовали Windows 10-Pro для наших тестов работает python 3.8.1.

1 Ответ

0 голосов
/ 27 мая 2020

Хорошо, это не ошибка, это задокументированное ограничение localtime()/gmtime() платформы. Хотя сам класс datetime может обрабатывать произвольные даты, любые ссылки на timestamp требуют прохождения через систему местного времени платформы. В моем случае это Windows 10, 64 бит.

Согласно документам: https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s?view=vs-2019

_localtime64_s, который использует структуру __time64_t, позволяет датам быть выраженным до 23:59:59 18 января 3001 г. по всемирному координированному времени (UT C)

Передача значения, превышающего год 3001, приводит к localtime64_s возвращению EINVAL . Согласно python docs:

Это может вызвать OverflowError, если временная метка выходит за пределы диапазона значений, поддерживаемых функцией платформы C localtime (), и OSError при сбое localtime () .

Мы видим более позднее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...