【问题标题】:Calculate tm_isdst from date and timezone根据日期和时区计算 tm_isdst
【发布时间】:2012-11-07 23:27:34
【问题描述】:

当我跑线时

time.strptime("2012-06-01 12:00:00 "+time.strftime("%Z"), "%Y-%m-%d %H:%M:%S %Z")

它为我创建了一个结构,但标志 tm_isdst 是错误的。 6 月初 DST 处于活动状态,但无论我在什么日期输入 tm_isdst 标志始终设置为现在在 localtime() 中的值。我需要知道 DST 在我输入的日期是否有效。

【问题讨论】:

  • 或者换一种说法。我需要知道 dst 在给定的日期/时间是否处于活动状态。
  • 这可能会在Stack Overflow 上得到更多答案。

标签: python time timezone


【解决方案1】:

首先,不要在格式中包含time.strftime('%Z')。您正在告诉它您当前的 GMT 偏移量(包括关闭夏令时),并且它 [可能] 使用它来设置 tm_isdst。

没有它,你应该得到一个带有tm_isdst=-1的结构:

>>> time1 = time.strptime("2012-06-01 12:00:00", "%Y-%m-%d %H:%M:%S")
>>> time1
time.struct_time(tm_year=2012, tm_mon=6, tm_mday=1, tm_hour=12, tm_min=0,
tm_sec=0, tm_wday=4, tm_yday=153, tm_isdst=-1)

现在,您可以将其传递给 mktime,它会在给定 -1 值的情况下“猜测”夏令时值(我将“猜测”放在引号中,因为它总是正确的,除了凌晨 2 点不明确的情况)。这将以time() 格式给出绝对时间。

>>> time.mktime([previous value]) # my timezone is US Eastern
1338566400.0

然后你可以用这个值调用localtime,它会有一个正确设置的DST标志:

>>> time.localtime(1338566400).tm_isdst
1

您也可以跳过 strptime 步骤,直接将值传递给 mktime:

>>> time.mktime((2012,6,1,12,0,0,-1,-1,-1))
1338566400.0

【讨论】:

  • 这里有一个问题:我需要 time.strftime('%Z') 因为我输入的时间不需要与我现在在同一时区。
  • 我不认为time 模块中的函数可以处理您所在时区以外的时间。您应该使用pytz 或者(如果您的应用程序是单线程的)您可以将os.environ['TZ'] 设置为所需的时区并调用time.tzset()。在任何情况下,在 strptime 中指定一个显式的 %Z 偏移量将使它认为它可以从中判断它是否是 DST。
  • 问题是,仅仅因为你在同一个时区并不意味着你有相同的本地时间,因为 dst。反之亦然。
  • @Martin 我不知道最后一条评论是什么意思。我的观点是,strptime 或时间模块中的任何函数都不能处理任意时区。它们只能处理您当前的 (os.environ['TZ']) 时区,该时区正好有两个 GMT 偏移量,而不是其中的 24 个。
  • "我需要 time.strftime('%Z')..." 我不明白。这为您提供了系统时区。它怎么知道你指的时区?
【解决方案2】:

您的问题相当于如何将作为字符串给出的本地时间转换为附有本地时区信息的本地时间:

from datetime import datetime
from pytz.exceptions import InvalidTimeError # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

naive_dt = datetime.strptime("2012-06-01 12:00:00", "%Y-%m-%d %H:%M:%S")
local_tz = get_localzone()
try:
    local_dt = local_tz.localize(naive_dt, is_dst=None)
except InvalidTimeError as e:
    print("can't determine whether DST is active, reason: %s" % (e,))
else:
    assert local_dt.dst() is not None
    print("DST is %sactive" % ("" if local_dt.dst() else "not ",))

它使用Olson tz databasepytz 模块),因此:

  • 当 UTC 偏移可能因与 DST 无关的原因而不同时,它适用于过去的日期。
  • 当无法确定 DST 时,它会检测不明确或不存在的本地时间
  • 它适用于 Windows 和 *nix(tzlocal 模块)

注意:mktime()-based solution shown in @Random832'a answer

import time

isdst = time.localtime(time.mktime(naive_dt.timetuple())).tm_isdst > 0
  • 如果操作系统不提供自己的历史时区数据库,它可能会默默地为过去的日期提供错误的结果
  • 对于不明确或不存在的当地时间(在 DST 转换期间),它可能会默默地提供错误结果

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-09
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    相关资源
    最近更新 更多