我有 YMD hms 格式的字符串,其中的时区被去除了。但我知道他们在东部时间,夏令时。
我正在尝试将它们转换为 UTC 时间的纪元时间戳。
我写了下面的函数:
def ymdhms_timezone_dst_to_epoch(input_str, tz="US/Eastern"):
print(input_str)
dt = datetime.datetime.fromtimestamp(time.mktime(time.strptime(input_str,'%Y-%m-%d %H:%M:%S')))
local_dt = pytz.timezone(tz).localize(dt)
print(local_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
utc_dt = local_dt.astimezone(pytz.utc)
print(utc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
e = int(utc_dt.strftime("%s"))
print(e)
return e
Given string `2015-04-20 21:12:07` this prints:
2015-04-20 21:12:07
2015-04-20 21:12:07 EDT-0400 #<- so far so good?
2015-04-21 01:12:07 UTC+0000 #<- so far so good?
1429596727
根据纪元时间戳看起来没问题。但是http://www.epochconverter.com/epoch/timezones.php?epoch=1429596727说应该毛到 格林威治标准时间 2015 年 4 月 21 日 06:12:07 UTC。
怎么了?
请您参考如下方法:
I have strings in YMD hms format that had the timezone stripped. But I know they are in Eastern time with daylight savings time.
一种可移植的方式是使用pytz:
#!/usr/bin/env python
from datetime import datetime
import pytz # $ pip install pytz
naive_dt = datetime.strptime('2015-04-20 21:12:07', '%Y-%m-%d %H:%M:%S')
tz = pytz.timezone('US/Eastern')
eastern_dt = tz.normalize(tz.localize(naive_dt))
print(eastern_dt)
# -> 2015-04-20 21:12:07-04:00
I am trying to convert them into epoch timestamps for UTC time.
timestamp = (eastern_dt - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1429578727.0
参见 Converting datetime.date to UTC timestamp in Python .
您的代码中存在多个问题:
<time.mktime()可能会为不明确的输入时间返回错误结果(50% 的几率),例如,在秋季的“回退”DST 转换期间 如果
time.mktime()和datetime.fromtimestamp()无法访问历史时区数据库,则它们可能会在过去/ future 日期失败系统(尤其是 Windows)localize(dt)可能会为不明确或不存在的时间返回错误结果,即在 DST 转换期间。如果您知道时间对应于夏令时,则使用is_dst=True。tz.normalize()是必要的,以调整输入中可能不存在的时间utc_dt.strftime("%s")is not portable and it does not respect tzinfo object .它将输入解释为本地时间,即,除非您的本地时区是 UTC,否则它会返回错误的结果。
Can I just always set is_dst=True?
如果您不介意在模棱两可或不存在的时间获得不精确的结果,例如,在美国/纽约时区的秋季有 DST 转换:
>>> from datetime import datetime
>>> import pytz # $ pip install pytz
>>> tz = pytz.timezone('America/New_York')
>>> ambiguous_time = datetime(2015, 11, 1, 1, 30)
>>> time_fmt = '%Y-%m-%d %H:%M:%S%z (%Z)'
>>> tz.localize(ambiguous_time).strftime(time_fmt)
'2015-11-01 01:30:00-0500 (EST)'
>>> tz.localize(ambiguous_time, is_dst=False).strftime(time_fmt) # same
'2015-11-01 01:30:00-0500 (EST)'
>>> tz.localize(ambiguous_time, is_dst=True).strftime(time_fmt) # different
'2015-11-01 01:30:00-0400 (EDT)'
>>> tz.localize(ambiguous_time, is_dst=None).strftime(time_fmt)
Traceback (most recent call last):
...
pytz.exceptions.AmbiguousTimeError: 2015-11-01 01:30:00
时钟倒转at 2a.m. on the first Sunday in November :
is_dst 消歧标志可以有三个值:
False-- 默认,假定冬令时True-- 假设夏令时None-- 为不明确/不存在的时间引发异常。
is_dst 值对于现有的唯一本地时间将被忽略。
这是来自 PEP 0495 -- Local Time Disambiguation 的情节说明 DST 转换:
本地时间在折页中重复两次(夏令时 - 折页前,冬令时 - 折页后)。
为了能够自动消除本地时间的歧义,您需要一些额外的信息,例如,如果您阅读了一系列本地时间,那么如果您知道它们已排序可能会有所帮助:Parsing of Ordered Timestamps in Local Time (to UTC) While Observing Daylight Saving Time .
