Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Python中将时区感知日期字符串转换为UTC并返回_Python_Datetime_Timezone - Fatal编程技术网

在Python中将时区感知日期字符串转换为UTC并返回

在Python中将时区感知日期字符串转换为UTC并返回,python,datetime,timezone,Python,Datetime,Timezone,我正在将国家气象局警报源解析到一个web应用程序中。我想在警报到期时清除警报。我还想以本地时间格式显示它们所属地理区域的过期时间 警报覆盖整个美国,因此我认为最好的方法是以UTC时间戳存储和比较时间。过期时间以如下字符串的形式到达提要:2011-09-09T22:12:00-04:00 我使用Labix dateutils包以时区感知的方式解析字符串: >>> from dateutil.parser import parse >>> d = parse("2

我正在将国家气象局警报源解析到一个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

有人能帮我找到我的错误吗?我不确定这是否是夏令时的问题?我遇到了一些东西,让我相信这可能是试图本地化我的日期和时间,但在这一点上,我相当困惑。我希望以时区不可知的方式进行所有这些计算/比较。

问题是夏令时被应用了两次

一个简单的例子:

>>> time_tuple = datetime(2011,3,13,2,1,1).utctimetuple()
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=13, tm_hour=2, tm_min=1, tm_sec=1, tm_wday=6, tm_yday=72, tm_isdst=0)
>>> datetime.fromtimestamp(time.mktime(time_tuple))
datetime.datetime(2011, 3, 13, 3, 1, 1)
我相当确定故障在
time.mktime()内。正如它在其报告中所说:

这是localtime()的反函数。它的 参数是结构时间或完整的9元组(因为dst标志是 需要;使用-1作为dst标志(如果未知),它表示 以当地时间表示的时间,而不是UTC。它返回一个浮点数,例如 与时间的兼容性()。如果输入值不能表示为 将引发有效时间OverflowerError或ValueError(其中 取决于Python还是 底层C库)。它可以为其生成 时间取决于平台

当您将时间元组传递给
time.mktime()
时,它需要一个关于时间是否为夏令时的标志。如上所示,
utctimetuple()
返回一个标记为
0
的元组,正如它在其:

如果datetime实例d是幼稚的,则这与d.timetuple()相同 除了tm_isdst被强制为0,而与d.dst()无关 返回。在UTC时间内,DST从未生效

如果d是已知的,则通过减去 d、 utcoffset(),并且规范化时间的time.struct_time为 返回。tm_isdst被强制为0。请注意,结果是tm_年 如果d.year是MINYEAR或MAXYEAR,则成员可以是MINYEAR-1或MAXYEAR+1 UTC调整超出了一年的界限

由于您已告诉
time.mktime()
您的时间不是DST,它的工作是将所有时间转换为本地时间,并且您所在地区目前是夏令时,因此会增加一小时,使其成为夏令时。结果就是这样


虽然我手头没有这篇文章,但几天前我发现了一种方法,可以将时区感知的日期时间转换为本地时间的原始日期时间。这对于您的应用程序来说可能比您当前正在做的工作更好(使用优秀模块):


将“America/LosAngeles”替换为您自己的时区字符串,您可以在
pytz中找到。所有时区
datetime。fromtimestamp()
是从POSIX时间戳获取本地时间的正确方法。您的问题是,使用
time.mktime()
将aware datetime对象转换为POSIX时间戳是不正确的。这是:


可能是重复的,我原以为你可以用datetime对象完成所有这些,而不是转换成元组或时间戳。如果您使一个时区感知“now”datetime对象,那么只需执行“Ifxlocalize()
得到了相同的结果。我怀疑问题在于我没有设置的某个地方的DST标志?相关:它不正确
mktime()
在OP超过UTC时间时需要本地时间。如果本地时区不是UTC,则会失败。不要使用
naive\u datetime\u object.utctimetuple()
——它不会将其转换为UTC(OP使用
aware\u datetime.object.utctimetuple()
,按预期工作)。如果
aware\u dt
不在UTC中,您可能需要在
.astimezone()
之后调用
tz.normalize()
import pytz
def convert_to_local_time(dt_aware):
    tz = pytz.timezone('America/Los_Angeles') # Replace this with your time zone string
    dt_my_tz = dt_aware.astimezone(tz)
    dt_naive = dt_my_tz.replace(tzinfo=None)
    return dt_naive
expiration_utc_ts = (d - datetime(1970, 1, 1, tzinfo=utc)).total_seconds()
local_dt = datetime.fromtimestamp(expiration_utc_ts)