【问题标题】:Python daylight savings timePython 夏令时
【发布时间】:2011-02-22 06:53:55
【问题描述】:

如何检查夏令时是否有效?

【问题讨论】:

    标签: python time dst


    【解决方案1】:

    您可以使用time.localtime 并查看返回值中的tm_isdst 标志。

    >>> import time
    >>> time.localtime()
    (2010, 5, 21, 21, 48, 51, 4, 141, 0)
    >>> _.tm_isdst
    0
    

    使用time.localtime(),您可以在任意时间询问相同的问题,以查看 DST 是否对您当前的时区有效。

    【讨论】:

    • 使用 time.daylight 属性可能会更清楚一点。如果您当前的时区有 DST,它将返回非零结果。
    • @brian buck:不过这不一样。对于给定的时区,time.daylight 是恒定的,因为日光区要么存在,要么不存在。另一方面,tm_isdst 标志反映给定时间是否在在 DST 开始和结束日期内。
    • 这种对time.daylight 的混淆似乎是一个更大的问题:bugs.python.org/issue7229。
    • 应该是_.tm_isdst > 0(-1 值是可能的)。
    • 啊!我讨厌 Python 问题的这类答案,因为它是一个命令行示例,并没有说明(对我而言)如何将其放入函数中。 (我尝试 time.localtime().tm_isdst 的天真努力没有奏效。)所以我将进一步研究并增加答案。
    【解决方案2】:

    如果您在笔记本电脑上运行代码,则接受的答案很好,但大多数 python 应用程序在使用 UTC 作为本地时间的服务器上运行,因此它们 根据接受的答案,永远不会处于夏令时。

    第二个问题是不同地区实行夏令时 不同的日子和时间。因此,即使您有明确的时间,例如 datetime.utcnow(),可能是某个时区的夏令时,但不是 在另一个。

    那么我们能做的最好的事情就是判断给定时间是否在 DST 期间发生 特定的时区,我能找到的最好的方法已经有了 由pytz localize 函数实现,我们可以使用它来获得一个 很好的答案,适用于我们的笔记本电脑和服务器。

    import pytz
    
    from datetime import datetime
    
    def is_dst(dt=None, timezone="UTC"):
        if dt is None:
            dt = datetime.utcnow()
        timezone = pytz.timezone(timezone)
        timezone_aware_date = timezone.localize(dt, is_dst=None)
        return timezone_aware_date.tzinfo._dst.seconds != 0
    

    一些例子

    >>> is_dst() # it is never DST in UTC
    False
    >>> is_dst(datetime(2019, 1, 1), timezone="US/Pacific")
    False
    >>> is_dst(datetime(2019, 4, 1), timezone="US/Pacific")
    True
    >>> is_dst(datetime(2019, 3, 10, 2), timezone="US/Pacific")
    NonExistentTimeError
    >>> is_dst(datetime(2019, 11, 3, 1), timezone="US/Pacific")
    AmbiguousTimeError
    

    在我们的is_dst 函数中,我们指定is_dst=None 作为参数 timezone.localize,这会导致废话时间抛出错误。你 可以使用is_dst=False 忽略这些错误并为这些错误返回False 次。

    【讨论】:

    • 我遇到了一个错误,因为 tzinfo 没有属性_dst。
    • @otocan 随时分享您运行的代码、python 版本以及其他可能相关的内容。
    • 我得到 AttributeError: 'str' object has no attribute 'tzinfo' in is_dst timezone_aware_date = timezone.localize(dt, is_dst=None) File "C:\Applicazioni_Tommaso\Phyton\lib\site-packages \pytz\tzinfo.py",第 317 行,如果 dt.tzinfo 不是 None:AttributeError: 'str' object has no attribute 'tzinfo'
    • @Tms91 dt 应该是日期时间,而不是字符串。您可以通过使用datetime.strptime 解析字符串来创建日期时间对象
    【解决方案3】:

    假设您想在 datetime 上执行此操作

    使用pytz 让它知道时区,然后检查它的dst 属性:

    import datetime
    import pytz
    
    def is_dst(dt,timeZone):
       aware_dt = timeZone.localize(dt)
       return aware_dt.dst() != datetime.timedelta(0,0)
    
    timeZone = pytz.timezone("Europe/London")
    
    dt = datetime.datetime(2019,8,2)
    is_dst(dt,timeZone)
    True
    
    dt = datetime.datetime(2019,2,2)
    is_dst(dt,timeZone)
    False
    

    【讨论】:

    • 我真的不喜欢不需要的东西,比如 True 和 False 周围的括号,但是整个 if 语句也不需要,只需返回比较。
    • 我认为 if/else 有助于一目了然地理解逻辑,但基本上你是对的。
    【解决方案4】:

    以上都没有帮助我,所以我找到了自己的解决方法。

    我与https://gist.github.com/dpapathanasiou/09bd2885813038d7d3eb 中实现的逻辑有关,虽然仍然存在问题,但它显然在现实生活中不起作用:(

    目前我在以色列,我们在月底调时钟, 在澳大利亚,他们已经改变了时钟。 对于Asia/Jerusalem 和Australia/Sydney,所有代码都返回True。

    最终我使用了外部 3rd 方 API - https://worldtimeapi.org/ - 通过它我分析 utc_offset 是否为 11 小时(而不是 10:05)。

    from requests import get as Get
    
    is_dst = True
    try:
        tz_check = Get('https://worldtimeapi.org/api/timezone/Australia/Sydney')
        is_dst = tz_check.json().get('utc_offset') == '+11:00'
    except Exception as e:
        print('!!! Error getting timezone', e)
    

    我同意这是一个私人案例,但我希望这可以帮助某人:)

    【讨论】:

    • 谢谢,帮助了很多人不要重新发明轮子
    【解决方案5】:

    我会将此作为对上述@mehtunguh 答案的评论发布,但我目前的声誉级别不允许我发表评论。

    我认为is_dst 函数在省略dt 参数时可能存在问题。

    当省略 dt 参数时,dt 设置为 datetime.utcnow(),它返回一个表示当前 UTC 时间的 naive 日期时间。将其传递给pytz.localize 时,生成的本地化时间不是指定时区的当前 时间,而是具有相同小时、分钟的本地时间,第二,作为当前的UTC时间。

    因此,例如,当我写这篇文章时,它是美国/东部时区的美国东部标准时间上午 10:50,datetime.utcnow() 返回带有hour=15 和minute=50 的日期时间值。正如所写,当以is_dst(timezone='US/Eastern') 调用时,is_dst 不检查当前当地时间上午 10:50 EST 是否处于夏令时,而是检查下午 3:50 EST 是否处于夏令时。

    我认为is_dst 应该编码如下:

    import datetime
    import pytz
    
    def is_dst(dt=None, timezone='UTC'):
        timezone = pytz.timezone(timezone)
        if dt is None:
            dt = datetime.datetime.now(datetime.timezone.utc)
        if dt.tzinfo is None:
            tz_aware_dt = timezone.localize(dt, is_dst=None)
        else:
            tz_aware_dt = dt.astimezone(timezone)
        return tz_aware_dt.tzinfo._dst.seconds != 0
    

    此版本允许传递 naive 日期时间值或 时区感知 日期时间值作为 @ 987654334@ 参数。当 dt 参数被省略时,它使用当前 UTC 时间的时区感知版本,因此当它本地化到指定时区时,它代表该时区的当前时间。

    【讨论】:

      【解决方案6】:

      扩展上面@Greg Hewgill 的答案,加上处理本地时区(在pip install tzlocal 的帮助下),你会得到:

      import time
      from datetime import datetime, timedelta
      from tzlocal import get_localzone
      
      def to_local(dt):
          """From any timezone to local datetime - also cope with DST"""
          localtime = time.localtime()
          if localtime.tm_isdst:
              utctime = time.gmtime()
              hours_delta = timedelta(hours=(localtime.tm_hour - utctime.tm_hour))
              dt = dt - hours_delta
      
          return dt.replace(tzinfo=get_localzone())
      

      【讨论】:

        【解决方案7】:

        我来自英国,这就是我处理服务器半年返回错误时间的方式:

        import pytz
        from typing import Optional
        from datetime import datetime
        
        class BritishTime(datetime):
            timezone = pytz.timezone('Europe/London')
        
            @classmethod
            def dst(cls, dt: Optional[datetime] = None):
                dt = dt if dt is not None else cls.now()
                return cls.timezone.dst(dt)
        

        现在,如果我使用BritishTime 创建一个日期时间对象,它具有dst 方法,我可以使用它来检查和更新时间,如下所示:

        def get_correct_time(timestamp):
            updated = BritishTime.fromtimestamp(timestamp)
            return updated + updated.dst()
        

        效果很好。

        【讨论】:

          猜你喜欢
          • 2015-12-04
          • 2010-10-12
          • 1970-01-01
          • 2014-03-23
          • 2012-07-09
          • 1970-01-01
          • 2013-02-18
          • 2012-04-25
          相关资源
          最近更新 更多