Несогласованный ValueError со смещением часового пояса за пределами границ

Смещение часового пояса в отметке времени должно быть в диапазоне от -12 до +14 часов. Иначе это бессмысленно. Я работаю с полем строк временных меток в объявлении pandas dataframe, некоторые из моих временных меток бессмысленны из-за того, что смещение выходит за пределы этой границы -12 + 14 часов.

Хорошая временная метка:

good = '2019-11-11T07:08:09.640-4:00'

Неверное смещение часового пояса

bad = '2019-11-19T22:51:34.619000+17:00'

Еще одно неверное смещение часового пояса:

bad2 = '2019-11-11T07:08:09.640-31:00'

Теперь, если я попытаюсь преобразовать эти строки в изоформат:

Работает как положено:

import dateutil
dateutil.parser.parse(good).isoformat()
'2019-11-11T07:08:09.640000-04:00'

Не работает должным образом, возвращает метку времени:

dateutil.parser.parse(bad).isoformat()
'2019-11-19T22:51:34.619000+17:00'

Работает, как и ожидалось, я получаю сообщение об ошибке (которое я мог бы впоследствии использовать в блоке if else, try, catch)

dateutil.parser.parse(bad2).isoformat()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: offset must be a timedelta strictly between -timedelta(hours=24) and timedelta(hours=24).

Почему я получаю сообщение об ошибке на bad2 и неплохо, когда они оба имеют смещение часового пояса за пределами границ


person Doug Fir    schedule 23.12.2019    source источник
comment
Обратите внимание, что моя цель - получить исключение для bad, а не исправить ошибку для bad2.   -  person Doug Fir    schedule 23.12.2019
comment
Потому что мне нужно отформатировать даты, поэтому мне нужно определить те, у которых есть бессмысленные смещения часового пояса, и плохой не дает мне предупреждения   -  person Doug Fir    schedule 23.12.2019


Ответы (1)


Это просто границы смещения часовых поясов в Python — как указано в сообщении об ошибке, смещения ограничены максимум ± 24 часа, что согласуется с вашими выводами. Это не связано с текущими максимальным и минимальным смещениями в зонах реального времени, за исключением того факта, что было бы проблемой, если бы границы не позволяли представить все зоны реального времени.

Нет простого способа заставить datetime или dateutil работать так, как вы хотите, потому что границы не настраиваются. Если вы хотите обнаружить смещения за пределами +14/-12 или любого другого произвольного ограничения, вам нужно проверить utcoffset, например:

if not (timedelta(hours=-12) < dt.utcoffset() < timedelta(hours=14)):
    raise ValueError(...)

Тем не менее, я не рекомендую этот курс действий, если вы не знаете, что некоторые из ваших строк имеют этот конкретный режим ошибки. Одна вещь, которую вы узнаете, имея дело с датой и временем и часовыми поясами, заключается в том, что наложение произвольных ограничений на них редко бывает хорошей идеей, потому что какая-то случайная страна где-то решит установить правило, которое нарушает ваше аккуратное «практическое» ограничение. Я даже слегка настороженно отношусь к ограничению смещения ±24h в tzinfo, но оно встроено в язык, и маловероятно, что реальное смещение нарушит его в ближайшее время.

person Paul    schedule 23.12.2019
comment
Привет Павел, спасибо за ответ. Для большего контекста, хотя я могу нормально обрабатывать свой фрейм данных в пандах, проблема заключается в том, что затем я пытаюсь отправить его в postgres, используя алхимию sql. В принимающей таблице есть поле типа часовой пояс со смещением. Из журналов: sqlalchemy.exc.DataError: (psycopg2.errors.InvalidTimeZoneDisplacementValue) time zone displacement out of range: "2019-11-19T22:51:34.619000+17:00" Правило -12 + 14 не является произвольным... насколько мне известно, это единственная возможная граница, когда базовый часовой пояс - UTC. - person Doug Fir; 23.12.2019
comment
Я также не чувствую себя комфортно, пытаясь вручную настроить смещения. Я смутно припоминаю, что раньше работал с ISO и получил похожее сообщение об ошибке, но вместо того, чтобы быть в течение 24 часов, вместо этого он указал диапазон -14, +12. Но я не могу вспомнить, что это был за пакет - person Doug Fir; 23.12.2019
comment
Я также получаю синтаксическую ошибку с вашим блоком, если вы видите что-то не так, дайте мне знать? def rogue_tz_offsets(t): if not (timedelta(hours=-12) < t.utcoffset() < timedelta(hours=14): return dateutil.parser.parse(t).replace(tzinfo=None).isoformat() else: return dateutil.parser.parse(t).isoformat() - person Doug Fir; 23.12.2019
comment
@DougFir Я полагаю, вы уже разобрались, но я случайно опустил скобку в своем первоначальном ответе, извините за это. - person Paul; 23.12.2019
comment
@DougFir -12/+14 может быть текущим диапазоном смещений UTC, но это не обязательно единственно возможный диапазон. Учтите, что +14 кажется немного странным, не так ли, поскольку он охватывает 26 часов, а не 24. Вы можете легко представить себе страну, решившую, например, переключиться с +10 на -14 или любое другое произвольное смещение для своих собственные безумные причины. Для чего-то вроде sqlalchemy опасно занимать жесткую позицию в отношении диапазона допустимых смещений. - person Paul; 23.12.2019