Datetime使用pytz进行时区转换 [英] Datetime Timezone conversion using pytz

查看:274
本文介绍了Datetime使用pytz进行时区转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这只是 pytz 之间的另一篇文章。

This is just another post on pytz.

有两个函数可以在两个时区之间转换datetime对象。第二个功能适用于所有情况。两种情况(3)和(4)中的第一个功能失败。类似的 SO post 没有这样的问题。基于 localize(datetime.datetime) replace(tzinfo)之间的差异的任何解释将是一个很大的帮助。

There are two functions to convert datetime objects between two timezones. The second functions works for all cases. The first function fails in two cases, (3) and (4). Similar SO post did not have an issue like this. Any explanation based on the difference between localize(datetime.datetime) and replace(tzinfo) would be a great help.

>>> from dateutil.parser import parse
>>> import pytz



第一个功能(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)

注意现在四个datetime转换。

Notice the four datetime conversion now.

(1)从UTC到EST - OK

(1) from UTC to EST -- OK

>>> 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 - - OK

(2) from UTC to EDT -- OK

>>> 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小时

(3) from EST to UTC -- Not OK. Time offset is 4 hours 56 minutes. It is supposed to be 5 hours

>>> 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个小时。不考虑夏令时。

(4) from EDT to UTC -- Not OK. Time offset is 4 hours 56 minutes. It is supposed to be 4 hours. Daylight saving is not considered.

>>> 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>)



第二个功能(完美的工作)



下面的函数使用 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 - OK

(1) from UTC to EST -- OK

>>> 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 - - OK

(2) from UTC to EDT -- OK

>>> 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 - - OK。

(3) from EST to UTC -- OK.

>>> 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 - OK 。

(4) from EDT to UTC -- OK.

>>> 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 实例)失败?

  • 为什么第二个函数适用于所有提供的示例?

  • why does the first function work for UTC timezone?
  • why does it fail for 'US/Eastern' timezone (DstTzInfo instance)?
  • why does the second function work for all provided examples?

第一个函数不正确,因为它使用 d.replace(tzinfo = dsttzinfo_instance)而不是 dsttzinfo_instance.localize(d)

The first function is incorrect because it uses d.replace(tzinfo=dsttzinfo_instance) instead of dsttzinfo_instance.localize(d) .

第二个功能大部分时间是正确的,除了在不明确或不存在的时间内,例如,在DST转换期间,您可以通过将 is_dst 参数传递到 .localize() False (defaul t)/ True / (引发例外)。

The second function is correct most of the time except during ambiguous or non-existing times e.g., during DST transitions -- you can change the behaviour by passing is_dst parameter to .localize(): False(default)/True/None(raise an exception).

第一个函数适用于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 版本可能会返回不同的值 - 当前版本可能返回对应于zoneinfo可用的最早日期的 tzinfo 实例 - 大多数时候您不想要此值:我认为背后的动机默认值的选择是突出显示错误(将 pytz.timezone 传递到 datetime 构造函数或 .replace()方法)。

The first function works for UTC timezone because it has a fixed utc offset (zero) for any date. Other timezones such as America/New_York may have different utc offsets at different times (Daylight saving time, war time, any time that some local politician might think is a good idea -- it can be anything -- the tz database works in most cases). To implement tzinfo.utcoffset(dt), tzinfo.tzname(dt), tzinfo.dst(dt) methods pytz uses a collection of DstTzInfo instances each with a different set of (_tzname, _utcoffset, _dst) attributes. Given dt (date/time) and is_dst, .localize() method chooses an appropriate (in most cases but not always) DstTzInfo instance from the collection. pytz.timezone('America/New_York') returns a DstTzInfo instance with (_tzname, _utcoffset, _dst) attributes that correspond to some undocumented moment in time (different pytz versions may return different values -- the current version may return tzinfo instance that corresponds to the earliest date for which zoneinfo is available -- you don't want this value most of the time: I think the motivation behind the choice of the default value is to highlight the error (passing pytz.timezone to datetime constructor or .replace() method).

总结: .localize()选择适当的utcoffset,tzname,dst值, .replace()使用默认值(不适当的)值UTC只有一组utcoffset,tzname,dst因此是默认值可以使用 .replace()方法适用于UTC时区,您需要传递dateti我的对象和 is_dst 参数来选择其他时区的适当值,例如'America / New_York'

To summarize: .localize() selects appropriate utcoffset, tzname, dst values, .replace() uses the default (inappropriate) value. UTC has only one set of utcoffset, tzname, dst therefore the default value may be used and .replace() method works with UTC timezone. You need to pass a datetime object and is_dst parameter to select appropriate values for other timezones such as 'America/New_York'.

原则上, pytz 可以调用 localize()方法来实现 utcoffset() tzname() dst()方法即使 dt.tzinfo == self :它会使这些方法O(log n)在其中 n 是不同的(utcoffset,tzname,dst)值的间隔数,但 datetime 构造函数和 .replace()将工作也就是说,显式的 localize()调用将只需要通过 is_dst

In principle, pytz could have called localize() method to implement utcoffset(), tzname(), dst() methods even if dt.tzinfo == self: it would make these methods O(log n) in time where n is number of intervals with different (utcoffset, tzname, dst) values but datetime constructor and .replace() would work as is i.e., the explicit localize() call would be necessary only to pass is_dst.

这篇关于Datetime使用pytz进行时区转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆