Python 时间库 : how do I preserve dst with strptime and strftime

标签 python time timezone utc dst

我需要以可读格式存储时间戳,稍后我需要将其转换为纪元以供比较。

我试过这样做:

import time
format = '%Y %m %d %H:%M:%S +0000'
timestamp1 = time.strftime(format,time.gmtime())  # '2016 03 25 04:06:22 +0000'
t1 = time.strptime(timestamp1, format) # time.struct_time(..., tm_isdst=-1)
time.sleep(1)
epoch_now = time.mktime(time.gmtime())
epoch_t1 = time.mktime(t1)
print "Delta: %s" % (epoch_now - epoch_t1)

运行此程序,我得到的不是 1 秒的增量,而是 3601(1 小时 1 秒),始终如一。

进一步调查,似乎当我只执行 time.gmtime() 时,该结构具有 tm_isdst=0,而从 timestamp1 字符串转换的结构 t1 具有 tm_isdst=-1。

如何确保 isdst 保留为 0。我认为这可能是这里的问题。

或者是否有更好的方法以人类可读格式 (UTC) 记录时间,并且能够正确转换回纪元以计算时差?

更新: 昨晚做了更多研究后,我转而使用 datetime,因为它在 datetime 对象中保留了更多信息,下面的 albertoql 回答证实了这一点。

这是我现在拥有的:

from datetime import datetime
format = '%Y-%m-%d %H:%M:%S.%f +0000' # +0000 is optional; only for user to see it's UTC
d1 = datetime.utcnow()
timestamp1 = d1.strftime(format)
d1a = datetime.strptime(timestamp1, format)
time.sleep(1)
d2 = datetime.utcnow()
print "Delta: %s" % (d2 - d1a).seconds

我选择不添加 tz 以保持简单/更短;我仍然可以那样 strptime。

最佳答案

下面,首先是对问题的解释,然后是两个可能的解决方案,一个使用 time , 另一个使用 datetime .

问题解释

问题在于 OP 在问题中所做的观察:tm_isdst=-1tm_isdst 是一个标志,用于确定夏令时是否有效(更多详细信息请参见 https://docs.python.org/2/library/time.html#time.struct_time)。 具体来说,给定来自 OP 的时间字符串格式(符合 RFC 2822 Internet 电子邮件标准),[time.strptime] 4不存储时区信息,即+0000。因此,当 struct_time根据字符串中的信息再次创建,tm_isdst=-1,即unknown。计算时如何填写该信息的猜测是基于本地系统的。例如,如果系统指的是北美,那里实行夏令时,则设置 tm_isdst

时间解决

如果你只想使用time包,那么,直接解析信息最简单的方法就是指定时间为UTC,从而在格式中添加%Z。请注意,time 不提供在 struct_time 中存储时区信息的方法。因此,它不会打印与变量中保存的时间相关联的实际时区。时区是从系统中检索的。因此,不可能直接对time.strftime使用相同的格式。 .写入和读取字符串的代码部分如下所示:

format = '%Y %m %d %H:%M:%S UTC'
format2 = '%Y %m %d %H:%M:%S %Z'
timestamp1 = time.strftime(format, time.gmtime())
t1 = time.strptime(timestamp1, format2)

datetime 的解决方案

另一种解决方案涉及使用 datetimedateutil直接支持时区的包,代码可以是(假设需要保留时区信息):

from datetime import datetime
from dateutil import tz, parser
import time

time_format = '%Y %m %d %H:%M:%S %z'
utc_zone = tz.gettz('UTC')

utc_time1 = datetime.utcnow()
utc_time1 = utc_time1.replace(tzinfo=utc_zone)
utc_time1_string = utc_time1.strftime(time_format)
utc_time1 = parser.parse(utc_time1_string)
time.sleep(1)
utc_time2 = datetime.utcnow()
utc_time2 = utc_time2.replace(tzinfo=utc_zone)

print "Delta: %s" % (utc_time2 - utc_time1).total_seconds()

有几个方面需要注意:

  • 调用utcnow后,时区未设置,因为它是一个天真的 UTC 日期时间。如果不需要有关UTC的信息,可以将两次设置时区的两行都删除,结果是一样的,因为没有猜测DST。

  • 不可能使用datetime.strptime因为 %z,它没有被正确解析。如果字符串包含有关时区的信息,则应使用 parser

  • 可以直接执行 datetime 的两个实例的差值并将生成的增量转换为秒数。

  • 如果需要获取自纪元以来的秒数,则应进行显式计算,因为在datetime(当时的答案)。在代码下方,例如 utc_time2:

     epoch_time = datetime(1970,1,1)
     epoch2 = (utc_time2 - epoch_time).total_seconds()
    
  • datetime.resolution ,即两个不相等的 datetime 对象之间的最小可能差异。这会导致取决于分辨率的差异。

关于Python 时间库 : how do I preserve dst with strptime and strftime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36213899/

相关文章:

python - 在Python中使用Sapi语音时出错

php - Unix 时间戳和 JavaScript 时间;太大!

delphi - UTC 支持比较 2 个文件的日期/时间

php - 如何使用特定的 UTC 更改时区 laravel 5.4 版

java - 美国/马萨特兰时区无法解析的日期

python - 哪些 DHT 实现与 Python 3.x 兼容?

javascript - Angular 6 表单未将变量传递给 URL

php - 合并日期和时间

Java 日历在 MS Windows 中为 `America/Santiago` 区域返回错误的时间

python - 在 GPU 上结合使用 Flair 和 TensorFlow 会产生错误