检查“日期”是否在“无pytz时区”的夏令时中



由于某些原因,我的雇主不想使用pip安装第三方软件包,并希望我使用仅托管在trusty上的软件包。因此,我现在不能在代码中使用pytz。我该如何检查时区中的某个日期是否处于夏令时?这是我使用pytz的原始代码。

    import pytz
    import datetime
    ...
    target_date = datetime.datetime.strptime(arg_date, "%Y-%m-%d")
    time_zone = pytz.timezone('US/Eastern')
    dst_date = time_zone.localize(target_date, is_dst=None)
    est_hour = 24
    if bool(dst_date.dst()) is True:
        est_hour -= 4
    else:
        est_hour -= 5

在一般情况下,这是一个复杂的问题,不适合手工解决。依靠由专门负责任务的人审查和维护的外部模块(如pytz)是唯一明智的选择。

然而,考虑到你只对美国时区,特别是东部时区感兴趣的限制,可以编写一个简单的函数。这显然只对现行(2016年)规则有利,该规则上次更改是在2007年,随时可能再次更改。这些规则规定夏令时从3月的第二个星期日开始,到11月的第一个星期日结束。

这段代码基于我的算法,用于查找一个月中的特定日期。

def is_dst(dt):
    if dt.year < 2007:
        raise ValueError()
    dst_start = datetime.datetime(dt.year, 3, 8, 2, 0)
    dst_start += datetime.timedelta(6 - dst_start.weekday())
    dst_end = datetime.datetime(dt.year, 11, 1, 2, 0)
    dst_end += datetime.timedelta(6 - dst_end.weekday())
    return dst_start <= dt < dst_end

从Python 3.9开始有一个新功能:内置的zoneinfo模块。如果您的操作系统内置了时区信息,则此模块将在不需要任何额外安装的软件包的情况下访问该信息。

>>> import zoneinfo
>>> time_zone = zoneinfo.ZoneInfo('US/Eastern')
>>> dst_date = datetime.datetime(2022, 1, 1, tzinfo=time_zone)
>>> dst_date
datetime.datetime(2022, 1, 1, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='US/Eastern'))
>>> dst_date.dst()
datetime.timedelta(0)
>>> dst_date2 = datetime.datetime(2022, 3, 15, tzinfo=time_zone)
>>> dst_date2
datetime.datetime(2022, 3, 15, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='US/Eastern'))
>>> dst_date2.dst()
datetime.timedelta(seconds=3600)

在不使用pip的情况下安装pytz。

夏令时是任意的,由不同地区的立法选择,你无法真正计算它——例如,看看美国/东部的pytz来源,它实际上是未来20年夏令时变化的硬编码日期列表。

您可以自己这样做,从pytz所做的相同源提取数据(ZoneInfo/[或此链接](http://www.iana.org/time-zones))。或者从你的操作系统实现的tz,如果它有一个。。。

但是(除非是许可证的原因)让你的雇主查看pytz来源,确认它是可接受的无害的,并批准使用。

这个简单的函数对我有用:

from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
def is_dst(date:str or datetime, format:str = "%Y-%m-%d", zonename:str = "Europe/Paris"):
# print("checking date", date)
if isinstance(date, str):
    date = datetime.strptime(date, format)
if date.month==3 or date.month==10:
    zone = ZoneInfo(zonename)
    date_1 = date.astimezone(zone) + timedelta(hours=1)
    date_2 = date.astimezone(zone) + timedelta(hours=3)
    # print("t", date_1, "nt", date_2)
    return not date_1.utcoffset() == date_2.utcoffset()

每当发生这种情况时,它基本上会检查UTC偏移量之间是否不匹配,我添加了if date.month==3 or date.month==10,所以它只检查我们知道会提前夏令时的月份(例如,3月和10月)。

因此,is_dst("2023-03-26")返回Trueis_dst("2023-10-29")也返回True,2023内的任何其他日期返回False

相关内容

  • 没有找到相关文章

最新更新