使用pytz的Datetime时区转换
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用pytz的Datetime时区转换相关的知识,希望对你有一定的参考价值。
这只是关于pytz
的另一篇文章。
有两个函数可以在两个时区之间转换日期时间对象。第二个功能适用于所有情况。第一个函数在两种情况下失败,(3)和(4)。类似的SO post没有像这样的问题。任何基于localize(datetime.datetime)
和replace(tzinfo)
之间差异的解释都将是一个很大的帮助。
>>> from dateutil.parser import parse
>>> import pytz
First function (buggy)
下面的函数使用datetime.datetime.replace(tzinfo)
。
def buggy_timezone_converter(input_dt, current_tz='UTC', target_tz='US/Eastern'):
'''input_dt is a datetime.datetime object'''
current_tz = pytz.timezone(current_tz)
target_tz = pytz.timezone(target_tz)
target_dt = input_dt.replace(tzinfo=current_tz).astimezone(target_tz)
return target_tz.normalize(target_dt)
现在注意四个日期时间转换。
(1)从UTC到EST - 好的
>>> buggy_timezone_converter(parse('2013-02-26T04:00:00'))
Out[608]: datetime.datetime(2013, 2, 25, 23, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
(2)从UTC到EDT - 好的
>>> buggy_timezone_converter(parse('2013-05-26T04:00:00'))
Out[609]: datetime.datetime(2013, 5, 26, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
(3)从EST到UTC - 不行。时间偏移是4小时56分钟。它应该是5个小时
>>> buggy_timezone_converter(parse('2013-02-26T04:00:00'), target_tz='UTC', current_tz='US/Eastern')
Out[610]: datetime.datetime(2013, 2, 26, 8, 56, tzinfo=<UTC>)
(4)从EDT到UTC - 不行。时间偏移是4小时56分钟。它应该是4个小时。不考虑夏令时。
>>> buggy_timezone_converter(parse('2013-05-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC')
Out[611]: datetime.datetime(2013, 5, 26, 8, 56, tzinfo=<UTC>)
Second function (Works perfectly)
下面的函数使用pytz.timezone.localize(datetime.datetime)
。它完美地运作
def good_timezone_converter(input_dt, current_tz='UTC', target_tz='US/Eastern'):
current_tz = pytz.timezone(current_tz)
target_tz = pytz.timezone(target_tz)
target_dt = current_tz.localize(input_dt).astimezone(target_tz)
return target_tz.normalize(target_dt)
(1)从UTC到EST - 好的
>>> good_timezone_converter(parse('2013-02-26T04:00:00'))
Out[618]: datetime.datetime(2013, 2, 25, 23, 0, tzinfo=<DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>)
(2)从UTC到EDT - 好的
>>> good_timezone_converter(parse('2013-05-26T04:00:00'))
Out[619]: datetime.datetime(2013, 5, 26, 0, 0, tzinfo=<DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>)
(3)从EST到UTC - 好的。
>>> good_timezone_converter(parse('2013-02-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC')
Out[621]: datetime.datetime(2013, 2, 26, 9, 0, tzinfo=<UTC>)
(4)从EDT到UTC - 好的。
>>> good_timezone_converter(parse('2013-05-26T04:00:00'), current_tz='US/Eastern', target_tz='UTC')
Out[620]: datetime.datetime(2013, 5, 26, 8, 0, tzinfo=<UTC>)
我假设你有这些问题:
- 为什么第一个函数适用于UTC时区?
- 为什么它失败了
'US/Eastern'
时区(DstTzInfo
实例)? - 为什么第二个函数适用于所有提供的示例?
第一个函数是不正确的,因为它使用d.replace(tzinfo=dsttzinfo_instance)
而不是dsttzinfo_instance.localize(d)
。
第二个函数在大多数情况下是正确的,除非在模糊或不存在的时间期间,例如在DST过渡期间 - 您可以通过将is_dst
参数传递给.localize()
来改变行为:False
(默认)/ True
/ None
(引发异常)。
第一个函数适用于UTC时区,因为它对任何日期都有固定的utc偏移量(零)。其他时区如America/New_York
可能在不同的时间有不同的utc偏移(夏令时,战争时间,一些当地政治家可能认为是一个好主意的任何时间 - 它可以是任何东西 - tz数据库在大多数情况下工作)。为了实现tzinfo.utcoffset(dt)
,tzinfo.tzname(dt)
,tzinfo.dst(dt)
方法pytz
使用DstTzInfo
实例的集合,每个实例具有不同的(_tzname, _utcoffset, _dst)
属性集。给定dt
(日期/时间)和is_dst
,.localize()
方法从集合中选择适当的(在大多数情况下但不总是)DstTzInfo
实例。 pytz.timezone('America/New_York')
返回一个DstTzInfo
实例,其中(_tzname, _utcoffset, _dst)
属性对应于一些未记录的时刻(不同的pytz
版本可能会返回不同的值 - 当前版本可能会返回tzinfo
实例,该实例对应于zoneinfo可用的最早日期 - 您没有大多数时候都想要这个值:我认为选择默认值背后的动机是突出显示错误(将pytz.timezone
传递给datetime
构造函数或.replace()
方法)。
总结一下:.localize()
选择合适的utcoffset,tzname,dst值,.replace()
使用默认(不合适)值。 UTC只有一组utcoffset,tzname,dst因此可以使用默认值,.replace()
方法适用于UTC时区。您需要传递datetime对象和is_dst
参数,以便为其他时区选择适当的值,例如'America/New_York'
。
原则上,pytz
可以调用localize()
方法实现utcoffset()
,tzname()
,dst()
方法,即使dt.tzinfo == self
:它会使这些方法O(log n)及时n
是具有不同(utcoffset,tzname,dst)值的区间数但是datetime
构造函数和.replace()
将按原样工作,即明确的localize()
调用只需通过is_dst
。
以上是关于使用pytz的Datetime时区转换的主要内容,如果未能解决你的问题,请参考以下文章