Перечислите начало и конец перехода на летнее время за последние x лет - PullRequest
0 голосов
/ 22 января 2019

Есть ли способ извлечь начало и конец перехода на летнее время для данного часового пояса (в данном случае в Лондоне) для заданного года (лет).

Мне нужно начало и конец летнего времени в Лондоне за последние x лет в формате DateTime.

например. если лет = 3

2016        27 March 02:00      30 October 02:00

2017        26 March 02:00      29 October 02:00

2018        25 March 02:00      28 October 02:00

Есть ли способ автоматически извлечь это из библиотеки Python, или я должен просто найти его и создать свой собственный список?

1 Ответ

0 голосов
/ 24 января 2019

Вот функция, которая использует бинарный поиск, чтобы найти минуты, которые отмечают переходы в / из летнего времени. Он не зависит от каких-либо секретных внутренних структур данных.

import pytz
import datetime

def middle_date(d1, d2):
    diff = d2 - d1
    minutes = diff.total_seconds() // 60
    if minutes < 48 * 60:
        return d1 + datetime.timedelta(0, (minutes // 2) * 60)
    days = diff.days
    return d1 + datetime.timedelta(days // 2)

utc = pytz.utc

def saving_start_end(year, tz):
    t1 = datetime.datetime(year, 1, 1, tzinfo=tz).astimezone(utc)
    t4 = datetime.datetime(year, 12, 31, 23, 59, tzinfo=tz).astimezone(utc)
    t2 = t3 = middle_date(t1, t4)
    one_minute = datetime.timedelta(0, 60)
    dst_start = t1.astimezone(tz).dst()
    if dst_start == t2.astimezone(tz).dst():
        t2 = None
    else:
        while t1 < t2:
            mid = middle_date(t1, t2)
            if mid.astimezone(tz).dst() == dst_start:
                t1 = mid + one_minute
            else:
                t2 = mid
        t2 = (t2 - one_minute).astimezone(tz) + one_minute
    dst_mid = t3.astimezone(tz).dst()
    if dst_mid == t4.astimezone(tz).dst():
        t4 = None
    else:
        while t3 < t4:
            mid = middle_date(t3, t4)
            if mid.astimezone(tz).dst() == dst_mid:
                t3 = mid + one_minute
            else:
                t4 = mid
        t4 = (t4 - one_minute).astimezone(tz) + one_minute
    return t2, t4

Тесты:

>>> central = pytz.timezone('America/Chicago')
>>> for dt in saving_start_end(2019, central): print(dt.isoformat(' '))

2019-03-10 02:00:00-06:00
2019-11-03 02:00:00-05:00
>>> london = pytz.timezone('Europe/London')
>>> for year in (2016, 2017, 2018):
    start, end = saving_start_end(year, london)
    print(start.isoformat(' '), end.isoformat(' '))

2016-03-27 01:00:00+00:00 2016-10-30 02:00:00+01:00
2017-03-26 01:00:00+00:00 2017-10-29 02:00:00+01:00
2018-03-25 01:00:00+00:00 2018-10-28 02:00:00+01:00
...