【发布时间】:2011-09-19 01:39:46
【问题描述】:
我正在将 National Weather Service 警报馈送解析到 Web 应用程序中。我想在警报达到到期时间时清除它们。我还想以本地时间格式显示它们所属地理区域的到期时间。
警报覆盖整个美国,因此我认为最好的方法是存储和比较 UTC 时间戳中的时间。过期时间以如下字符串形式出现在提要中:2011-09-09T22:12:00-04:00。
我正在使用 Labix dateutils 包以可识别时区的方式解析字符串:
>>> from dateutil.parser import parse
>>> d = parse("2011-09-18T15:52:00-04:00")
>>> d
datetime.datetime(2011, 9, 18, 15, 52, tzinfo=tzoffset(None, -14400))
我还能够以小时为单位捕获 UTC 偏移量:
>>> offset_hours = (d.utcoffset().days * 86400 + d.utcoffset().seconds) / 3600
>>> offset_hours
-4
使用datetime.utctimetuple() 和time.mktime() 方法,我可以将解析的日期转换为UTC 时间戳:
>>> import time
>>> expiration_utc_ts = time.mktime(d.utctimetuple())
>>> expiration_utc_ts
1316393520.0
在这一点上,我感觉很好,我能够将原始字符串转换为代表 UTC 到期时间的时间戳。我可以将当前时间作为 UTC 时间戳与到期时间进行比较,并确定是否需要清除它:
>>> now_utc_ts = time.mktime(time.gmtime())
>>> now_utc_ts
1316398744.0
>>> now_utc_ts >= expiration_tc_ts
True
我遇到的困难是尝试将存储的 UTC 时间戳转换回原始的本地化格式。我从原始转换中存储了偏移小时数,并解析了一个字符串以存储时区标签:
>>> print offset_hours
-4
>>> print timezone
EDT
我想将 UTC 时间戳转换回本地格式的时间,但将其转换回 datetime 似乎不起作用:
>>> import datetime
>>> datetime.datetime.fromtimestamp(expiration_utc_ts) + datetime.timedelta(hours=offset_hours)
datetime.datetime(2011, 9, 18, 16, 52) # The hour is 16 but it should be 15
好像还有一个小时。我不确定错误是在哪里引入的?我进行了另一个测试并得到了类似的结果:
>>> # Running this at 21:29pm EDT
>>> utc_now = datetime.datetime.utcnow()
>>> utc_now_ts = time.mktime(right_now.utctimetuple())
>>> datetime.datetime.fromtimestamp(utc_now_ts)
datetime.datetime(2011, 9, 18, 22, 29, 47) # Off by 1 hour
谁能帮我找出我的错误?我不确定这是否是夏令时问题?我遇到了一些让我相信它可能试图本地化我的日期和时间的东西,但在这一点上我很困惑。我希望以与时区无关的方式进行所有这些计算/比较。
【问题讨论】:
-
我原以为您可以使用 datetime 对象完成所有这些操作,而不是转换为元组或时间戳。如果您创建了一个时区感知的“现在”日期时间对象,那么只需执行“如果 x
-
我也希望如此,但 PostgreSQL 一直想要本地化 datetime 值。 (我确信有办法解决这个问题,但我认为现在只存储 UTC 时间戳会更容易)
-
我查看了标记为可能重复的帖子,但没有帮助。使用
localize()得到了相同的结果。我怀疑问题出在我没有设置的某个地方的 DST 标志上?