Как я узнаю, что сегодня выходной день из-за изменения местного времени, например летнего времени в стандартных точках времени Python и Pandas?
В соответствии с правилами британского летнего времени / летнего времени ( https://www.gov.uk/when-do-the-clocks-change) часы:
- идти вперед на 1 час в 1 час ночи в последнее воскресенье марта,
- вернуться в 1 час в 2 часа ночи в последнее воскресенье октября.
В 2019 году эта гражданская смена местного времени происходит 31 марта и 27 октября, но дни слегка меняются каждый год. Есть ли чистый способ узнать эти даты для каждого года ввода?
Мне нужно проверить эти даты "меняющегося времени" автоматически, есть ли способ избежать цикла for, чтобы проверить детали каждой даты, чтобы узнать, является ли она датой "меняющегося времени"?
В настоящий момент я изучаю эти даты на 2019 год, просто чтобы попытаться выяснить воспроизводимую / автоматическую процедуру, и я нашел это:
# using datetime from the standard library
march_utc_30 = datetime.datetime(2019, 3, 30, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
march_utc_31 = datetime.datetime(2019, 3, 31, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
april_utc_1 = datetime.datetime(2019, 4, 1, 0, 0, 0, 0, tzinfo=datetime.timezone.utc)
# using pandas timestamps
pd_march_utc_30 = pd.Timestamp(march_utc_30) #, tz='UTC')
pd_march_utc_31 = pd.Timestamp(march_utc_31) #, tz='UTC')
pd_april_utc_1 = pd.Timestamp(april_utc_1) #, tz='UTC')
# using pandas wrappers
pd_local_march_utc_30 = pd_march_utc_30.tz_convert('Europe/London')
pd_local_march_utc_31 = pd_march_utc_31.tz_convert('Europe/London')
pd_local_april_utc_1 = pd_april_utc_1.tz_convert('Europe/London')
# then printing all these dates
print("march_utc_30 {} pd_march_utc_30 {} pd_local_march_utc_30 {}".format(march_utc_30, pd_march_utc_30, pd_local_march_utc_30))
print("march_utc_31 {} pd_march_utc_31 {} pd_local_march_utc_31 {}".format(march_utc_31, pd_march_utc_31, pd_local_march_utc_31))
print("april_utc_1 {} pd_april_utc_1 {} pd_local_april_utc_1 {}".format(april_utc_1, pd_april_utc_1, pd_local_april_utc_1))
Выход тех print
заявления это:
march_utc_30 2019-03-30 00:00:00+00:00 pd_march_utc_30 2019-03-30 00:00:00+00:00 pd_local_march_utc_30 2019-03-30 00:00:00+00:00
march_utc_31 2019-03-31 00:00:00+00:00 pd_march_utc_31 2019-03-31 00:00:00+00:00 pd_local_march_utc_31 2019-03-31 00:00:00+00:00
april_utc_1 2019-04-01 00:00:00+00:00 pd_april_utc_1 2019-04-01 00:00:00+00:00 pd_local_april_utc_1 2019-04-01 01:00:00+01:00
Я мог бы использовать for
Цикл, чтобы узнать, является ли текущая дата последним воскресеньем месяца, или сравнить "часовую дельту" между текущей датой и датой следующего дня, чтобы увидеть, есть ли +1, но мне интересно, есть ли более чистый способ сделать это?
Есть ли что-то привязанное к году, например, зная, что год ввода 2019
тогда мы точно знаем, что "дата изменения" в марте будет 31-го числа?
1 ответ
С помощью dateutil.rrule
может помочь (установить с pip install python-dateutil
).
Поскольку мы можем получать даты по неделям, нам не нужны никакие циклы,
from dateutil.rrule import rrule, WEEKLY
from dateutil.rrule import SU as Sunday
from datetime import date
import datetime
def get_last_sunday(year, month):
date = datetime.datetime(year=year, month=month, day=1)
# we can find max 5 sundays in a months
days = rrule(freq=WEEKLY, dtstart=date, byweekday=Sunday, count=5)
# Check if last date is same month,
# If not this couple year/month only have 4 Sundays
if days[-1].month == month:
return days[-1]
else:
return days[-2]
def get_march_switch(year):
# Get 5 next Sundays from first March
day = get_last_sunday(year, 3)
return day.replace(hour=1, minute=0, second=0, microsecond=0)
def get_october_switch(year):
day = get_last_sunday(year, 10)
return day.replace(hour=2, minute=0, second=0, microsecond=0)
print('2019:')
print(' {}'.format(get_march_switch(2019)))
print(' {}'.format(get_october_switch(2019)))
print('2021:')
print(' {}'.format(get_march_switch(2021)))
print(' {}'.format(get_october_switch(2021)))
get_sundays()
возвращает 5 следующих воскресений с первого дня данного month
потому что месяц может иметь максимум 5 воскресений.
Тогда я просто проверяю (в течение get_(march|october)_switch()
) если последнее воскресенье дано из ожидаемого месяца, если не очень хорошо, в этом месяце есть только 4 воскресенья, я взял это.
Наконец я фиксирую часы, секунды и микросекунды.
Выход:
2019:
2019-03-31 01:00:00
2019-10-27 02:00:00
2021:
2021-03-28 01:00:00
2021-10-24 02:00:00
Я знаю, что тема довольно старая. Однако сегодня у меня был тот же вопрос, и в конце я нашел решение, которое мне кажется довольно простым, с использованием только стандартного datetime:
Я хочу проверить, соответствует ли дата обновления моей даты октябрьскому летнему времени - я сделал это следующим образом:
refdate - мой стандартный объект datetime. Если у вас есть метка времени панды, вы можете преобразовать ее в собственное datetime, используя.to_pydatetime()
if refdate.month == 10 and refdate.weekday() == 6 and (refdate + dt.timedelta(weeks = 1)).month == 11:
oct_dst = 1