如果日期是进行 DST(夏令时)更改的实际日期,有没有办法在 Python 中推断?
Posted
技术标签:
【中文标题】如果日期是进行 DST(夏令时)更改的实际日期,有没有办法在 Python 中推断?【英文标题】:Is there a way to infer in Python if a date is the actual day in which the DST (Daylight Saving Time) change is made? 【发布时间】:2021-11-27 16:24:28 【问题描述】:我想在 Python 中推断日期是否是一年中由于 DST(夏令时)而改变小时的实际日期。
使用库pytz
,您可以本地化日期时间,并正确完成实际的 DST 更改。此外,库datetime
的方法dst()
允许您推断实际日期是在夏季还是冬季(example)。但是,我想推断 DST 更改的实际日期。
具体来说,我需要一个函数(例如is_dst_change(date, timezone)
),它接收日期并仅在一年中确实有小时变化的那些日子返回True。例如:
import pytz
import datetime
def is_dst_change(day, timezone):
# Localize
loc_day = pytz.timezone(timezone).localize(day)
# Pseudocode: Infer if a date is the actual day in which the dst hour change is made
if loc_day is dst_change_day:
return True
else:
return False
# In the timezone 'Europe/Madrid', the days in which the DST change is made in 2021 are 28/03/2021 and 31/10/2021
is_dst_change(day=datetime.datetime(year=2021, month=3, day=28), timezone = 'Europe/Madrid') # This should return True
is_dst_change(day=datetime.datetime(year=2021, month=10, day=31), timezone = 'Europe/Madrid') # This should return True
is_dst_change(day=datetime.datetime(year=2021, month=2, day=1), timezone = 'Europe/Madrid') # This should return False
is_dst_change(day=datetime.datetime(year=2021, month=7, day=1), timezone = 'Europe/Madrid') # This should return False
因此,在上面的示例中,函数 is_dst_change(day, timezone='Europe/Madrid')
将返回 True
的仅有的 2021 天是 2021 年 3 月 28 日和 2021 年 10 月 31 日。对于 2021 年的其余日子,它必须返回 False
。有没有办法用 Python 来推断?
【问题讨论】:
亚利桑那州和新墨西哥州处于同一时区,但亚利桑那州不会更改为夏令时。 @Barmar 我认为这可以通过使用[Country]/[City]
时区标识符来缓解,不是吗?与使用更广泛的仅限时区的标识符相反,例如 EST
/EDT
、PST
/PDT
?
@esqew 没错,我没有想到这种情况。
@Barmar 你必须在这里使用IANA time zone name
@esqew 缩写,如 EST/EDT、PST/PDT 不是地理意义上的时区,它们只是告诉您某些时区在特定时间段内的 UTC 偏移量那一年。而且很多都是模棱两可的,比如搜索BST。
【参考方案1】:
如果今天的 UTC 偏移量与明天的不同,那么今天是 DST 更改。
def is_dst_change(day: datetime.datetime, timezone):
# Override time to midnight
day = day.replace(hour=0, minute=0, second=0, microsecond=0)
tz = pytz.timezone(timezone)
return(tz.utcoffset(day+datetime.timedelta(days=1)) !=
tz.utcoffset(day))
“今天”在此代码中定义为午夜到午夜。
【讨论】:
打败我! Repl.it demo 我认为这可能是确定这一点的最平衡的方法,除非pytz
OOTB 提供了超优化的is_dst_change
-esque 函数。
如果day
是一个日期时间对象并且小时属性是在 DST 更改之后,我认为这不会给出正确的结果。您可能希望标准化为日期。【参考方案2】:
您可以使用datetime.dst()(UTC 偏移量的变化不一定是 DST 转换):
from datetime import datetime, time, timedelta
from zoneinfo import ZoneInfo # Python 3.9+
def is_date_of_DSTtransition(dt: datetime, zone: str) -> bool:
"""
check if the date part of a datetime object falls on the date
of a DST transition.
"""
_d = datetime.combine(dt.date(), time.min).replace(tzinfo=ZoneInfo(zone))
return _d.dst() != (_d+timedelta(1)).dst()
例如对于 tz Europe/Berlin:
for d in range(366):
if is_date_of_DSTtransition(datetime(2021, 1, 1) + timedelta(d), "Europe/Berlin"):
print((datetime(2021, 1, 1) + timedelta(d)).date())
# 2021-03-28
# 2021-10-31
注意:我在这里使用zoneinfo 而不是pytz
;对于遗留代码,有一个pytz deprecation shim。无论如何,这是一个pytz
版本(需要额外的normalize
):
import pytz
def is_date_of_DSTtransition(dt: datetime, zone: str) -> bool:
_d = pytz.timezone(zone).localize(datetime.combine(dt.date(), time.min))
return _d.dst() != pytz.timezone(zone).normalize(_d+timedelta(1)).dst()
【讨论】:
以上是关于如果日期是进行 DST(夏令时)更改的实际日期,有没有办法在 Python 中推断?的主要内容,如果未能解决你的问题,请参考以下文章