我怎么知道今天是否是由于改变民用当地时间的一天,例如标准 python 和 pandas 时间戳中的夏令时?
How do I know if today is a day due to change civil local time e.g. daylight saving time in standard python and pandas timestamps?
根据英国夏令时/夏令时(https://www.gov.uk/when-do-the-clocks-change)的规则时钟:
- 3 月的最后一个星期日凌晨 1 点快进 1 小时,
- 10 月最后一个星期日凌晨 2 点后退 1 小时。
2019 年这个民用当地时间更改发生在 3 月 31 日和 10 月 27 日,但是每年的日子都会略有变化。有没有一种清晰的方法来了解每个输入年份的这些日期?
我需要自动检查这些 "changing time" 日期,有没有办法避免 for 循环来检查每个日期的详细信息以查看它是否是 "changing time" 日期?
目前我正在探索 2019 年的这些日期,只是想找出一个 reproducible/automatic 程序,我发现了这个:
# 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
循环来 查明当前日期是否是该月的最后一个星期日 ,或者比较 "hour delta"当前日期和后一天的日期以查看是否有 +1,但我想知道是否有更简洁的方法来执行此操作?
是否有与年份相关的东西,例如知道输入年份是 2019
那么我们肯定知道三月的 "change date" 将是第 31 天?
使用 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()
returns 从给定 month
的第一天算起的接下来的 5 个星期日,因为一个月最多可以有 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
我知道这个话题现在已经很老了。然而,我今天有同样的问题,最后我找到了一个对我来说似乎很简单的解决方案,只使用标准日期时间:
我想检查我的日期 refdate 是否是 10 月夏令时 - 我是按以下方式进行的:
refdate 是我的标准日期时间对象。
如果您有熊猫时间戳,则可以使用 .to_pydatetime()
将其转换为本机日期时间
if refdate.month == 10 and refdate.weekday() == 6 and (refdate + dt.timedelta(weeks = 1)).month == 11:
oct_dst = 1
根据英国夏令时/夏令时(https://www.gov.uk/when-do-the-clocks-change)的规则时钟:
- 3 月的最后一个星期日凌晨 1 点快进 1 小时,
- 10 月最后一个星期日凌晨 2 点后退 1 小时。
2019 年这个民用当地时间更改发生在 3 月 31 日和 10 月 27 日,但是每年的日子都会略有变化。有没有一种清晰的方法来了解每个输入年份的这些日期?
我需要自动检查这些 "changing time" 日期,有没有办法避免 for 循环来检查每个日期的详细信息以查看它是否是 "changing time" 日期?
目前我正在探索 2019 年的这些日期,只是想找出一个 reproducible/automatic 程序,我发现了这个:
# 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
循环来 查明当前日期是否是该月的最后一个星期日 ,或者比较 "hour delta"当前日期和后一天的日期以查看是否有 +1,但我想知道是否有更简洁的方法来执行此操作?
是否有与年份相关的东西,例如知道输入年份是 2019
那么我们肯定知道三月的 "change date" 将是第 31 天?
使用 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()
returns 从给定 month
的第一天算起的接下来的 5 个星期日,因为一个月最多可以有 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
我知道这个话题现在已经很老了。然而,我今天有同样的问题,最后我找到了一个对我来说似乎很简单的解决方案,只使用标准日期时间:
我想检查我的日期 refdate 是否是 10 月夏令时 - 我是按以下方式进行的:
refdate 是我的标准日期时间对象。
如果您有熊猫时间戳,则可以使用 .to_pydatetime()
if refdate.month == 10 and refdate.weekday() == 6 and (refdate + dt.timedelta(weeks = 1)).month == 11:
oct_dst = 1