Разница между двумя объектами timedelta, с часовыми поясами

Я хотел бы подсчитать, сколько часов в интервале дат: например, "2014.03.29-30" должно дать 47 из-за перехода на летнее время.

Мой метод делает два объекта datetime, в следующем примере:

datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)
datetime.datetime(2014, 3, 30, 23, 59, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)
return (date2-date1) + timedelta(minutes=1)

Тем не менее, он дает "2 дня, 0:00:00", что не правильно. Как я могу сделать объект timedelta, который принимает во внимание часовые пояса и dst? Кроме того, если есть более простое решение для всей проблемы, я открыт для этого.

Спасибо!

1 ответ

Решение

До 1901-12-13 20:45:52 UTC 'Europe/Budapest' часовой пояс был LMT+1:16:00 STD. В настоящее время по состоянию на 2016-05-05 гг. 'Europe/Budapest' часовой пояс CET+2:00:00 DST.

Если вы используете Pytz's localize метод, то pytz выберет часовой пояс (utcoffset и dstoffset) для 'Europe/Budapest' который подходит для данной наивной даты и времени:

import datetime as DT
import pytz

tzone = pytz.timezone('Europe/Budapest')
date1 = tzone.localize(DT.datetime(2014, 3, 29, 0, 0), is_dst=None)
# datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' CET+1:00:00 STD>)

Напротив, если вы поставите tzinfo=tzone прямо к datetime.datetime, как в:

wrong_date1 = datetime.datetime(2014, 3, 29, 0, 0, tzinfo=tzone)
# datetime.datetime(2014, 3, 29, 0, 0, tzinfo=<DstTzInfo 'Europe/Budapest' LMT+1:16:00 STD>)

тогда datetime.datetime неправильно выбирает самый первый часовой пояс, связанный с 'Europe/Budapest' независимо от того, был ли это часовой пояс, действующий на 2014-3-29.

Поэтому при использовании pytz всегда используйте tzone.localize чтобы сделать наивные даты и времени с учетом часовых поясов:

import datetime as DT
import pytz
tzone = pytz.timezone('Europe/Budapest')
date1 = tzone.localize(DT.datetime(2014, 3, 29, 0, 0), is_dst=None)
date2 = tzone.localize(DT.datetime(2014, 3, 30, 23, 59), is_dst=None)
print(((date2-date1) + DT.timedelta(minutes=1)).total_seconds()/3600.)
# 47.0

Не использовать tzinfo=tzone если tzone является pytz.utc (или часовой пояс, который всегда одинаков на протяжении всей своей истории.)


Откуда взялась дата 1901-12-13 20:45:52 UTC родом из?

Вы можете посмотреть время перехода UTC в часовом поясе Pytz (и связанную с ним информацию о переходе), используя его tzone._utc_transition_times а также tzone._transition_info личные атрибуты:

In [43]: [(utcdate, utcoffset, dstoffset, tzabbrev) for utcdate, (utcoffset, dstoffset, tzabbrev) in zip(tzone._utc_transition_times, tzone._transition_info)][:2]
Out[43]: 
[(datetime.datetime(1, 1, 1, 0, 0),
  datetime.timedelta(0, 4560),
  datetime.timedelta(0),
  'LMT'),
 (datetime.datetime(1901, 12, 13, 20, 45, 52),
  datetime.timedelta(0, 3600),
  datetime.timedelta(0),
  'CET')]

Это показывает, что с даты 1-1-1 UTC в 1901-12-13 20:45:52 UTC сокращение часового пояса было LMT и utcoffset был 4560 секунд, что равно 1 часу и 16 минутам:

In [47]: print(DT.timedelta(0, 4560))
1:16:00

Отсюда первый часовой пояс, связанный с 'Europe/Budapest' является LMT+1:16:00 STD,

Другие вопросы по тегам