Python fromtimestamp OSError

По какой-то причине при построении datetimes с использованием fromtimestamp я получаю "OSDrror [Errno22] Invalid Argument", когда я использую отрицательные времена меньше -43200 (-12 часов). Я нахожусь на 64-битной версии Win7 и python 3.5.1. Здесь код, создающий ошибку.

>>> import datetime
>>> import pytz
>>> datetime.datetime.fromtimestamp(-43200, pytz.utc)
datetime.datetime(1969, 12, 31, 12, 0, tzinfo=<UTC>)
>>> datetime.datetime.fromtimestamp(-43201, pytz.utc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

В примере используется pytz для упрощения информации о часовом поясе, но ошибка также возникает без нее.

Ответ 1

Если вы получаете эту ошибку и не используете явно неправильную временную метку, проверьте свои единицы измерения.

fromtimestamp ожидает метку времени в секундах, тогда как метки времени в миллисекундах довольно часто (например, я обнаружил это при попытке проанализировать метку времени, созданную из Moment.js в виджете календаря).

Возьмите метку времени 1523443804214 - это 11 апреля 2018 года, примерно за 15 минут до того, как я сделал этот пост. Согласно Epoch Converter, нет проблем, но обратите внимание: "Предполагая, что эта метка времени в миллисекундах:".

В Python это возвращает OSError:

In [15]: datetime.fromtimestamp(1523443804214.0)
---------------------------------------------------------------------------
OSError Traceback (most recent call last)
<ipython-input-15-0c8efd251031> in <module>()
----> 1 datetime.fromtimestamp(1523443804214.0)

Однако, если мы разделим на тысячу:

In [17]: datetime.fromtimestamp(1523443804.214)
Out[17]: datetime.datetime(2018, 4, 11, 11, 50, 4, 214000)

результат - то, что мы ожидаем.

Ответ 2

Если временная метка находится вне диапазона значений, поддерживаемых функциями платформы C localtime() или gmtime(), datetime.fromtimestamp() может вызвать исключение, как вы видите.

В платформе Windows этот диапазон иногда может быть ограничен годами с 1970 по 2038 год. Я никогда не видел эту проблему в системе Linux.

Ответ 3

Ответ @wim правильный, но любой, кто прибудет сюда, может быть заинтересован в его тестировании (при желании настройте диапазон):

import datetime
import platform
print(
    "Running on Python ver.{} on {} {}\n" \
    .format(
        platform.python_version(),
        platform.system(),
        platform.release()
        )
)
for timestamp in range(1, 100000000):
    try:
        dt = datetime.datetime.fromtimestamp(timestamp)
    except:
        pass
    else:
        break
print(
    "Smallest accepted Unix timestamp by {}: '{}' ({})" \
    .format(platform.system(), timestamp, dt)
)

Что я получил было:

A:\src\X.utilities>test.py
Running on Python ver.3.6.1 on Windows 7

Smallest accepted Unix timestamp by Windows: '86400' (1970-01-02 02:00:00)

Ответ 4

Чтобы решить эту проблему, разделите значение метки времени на 1000.

В Windows номер временной метки умножается на коэффициент 1000.

Ответ 5

Отметка времени - это количество секунд с 1 января 1970 года, и это всегда положительное значение.