检查日期是否处于没有使用pytz的时区的夏令时

6

出于某些原因,我的雇主不想使用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

你只关心美国的时区还是需要全球运营? - Mark Ransom
我唯一关心的时区是美国东部时区。 - DeadCake
如果众议院能够离开他们的位置并通过参议院引入的法案,我们就再也不用担心这个问题了! - Mark Ransom
4个回答

4
在一般情况下,这是一个复杂的问题,不适合手工解决。仅仅依赖一个由专人检查和维护的外部模块,例如pytz,才是唯一明智的选择。
然而,如果只对美国时区,尤其是东部时区感兴趣,那么可以编写一个简单的函数。显然,这个函数只适用于当前规则(2016年),这些规则在2007年最后一次更改,并且可能随时再次更改。这些规则表明夏令时从三月第二个星期日开始,到十一月第一个星期日结束
此代码基于我为查找某个月份特定日期所设计的算法
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

我想这是我能够不使用pytz的最接近方法了。感谢您的帮助。 - DeadCake

3

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)

干净的解决方案为我节省了几分钟,仍然适用于2022年!特别适用于Django 4.0+开发人员。谢谢。 - scūriolus

0

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

DST是根据不同地区的法规而任意选择的,无法计算。例如,看看pytz源代码中的US / Eastern时区,它实际上是一个包含未来二十年DST更改的硬编码日期列表。

你可以自己做,从与pytz相同的来源(ZoneInfo / [或此链接](http://www.iana.org/time-zones)) 获取数据,或者从操作系统实现的tz获取...

但是(除非涉及许可原因),请让您的雇主查看pytz源代码并确认其是无害的,并批准将其用于使用。


感谢您的建议。他们不想使用pip或任何软件包管理器的原因是,根据他们的说法,技术运营团队太小了,无法为每种语言管理软件包管理器,并且由于安全更新而必须处理跨所有语言的软件包更新“对他们来说很麻烦”。我怀疑他们会在没有pip的情况下批准安装pytz。希望他们能够理智地同意使用它。 - DeadCake

0
这个简单的函数对我很有用:
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, "\n\t", date_2)
    return not date_1.utcoffset() == date_2.utcoffset()

它基本上检查UTC偏移是否存在不匹配,当发生这种情况时,我添加了 if date.month==3 or date.month==10 来仅检查我们预先知道会有夏令时的月份(例如,三月和十月)。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接