加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

python pytz时区设置模块

发布时间:2020-12-20 10:06:05 所属栏目:Python 来源:网络整理
导读:如果你的程序要考虑时区,可以使用pytz。 pytz官方文档:http://pytz.sourceforge.net/ 我使用的python版本:3.7.1 datetime模块中有tzinfo相关的东西,但是它是一个抽象类,文档上说: tzinfo is an abstract base clase,meaning that this class should no

如果你的程序要考虑时区,可以使用pytz。
pytz官方文档:http://pytz.sourceforge.net/
我使用的python版本:3.7.1

datetime模块中有tzinfo相关的东西,但是它是一个抽象类,文档上说:
tzinfo is an abstract base clase,meaning that this class should not be instantiated directly. You need to derive a concrete subclass,and (at least) supply implementations of the standard tzinfo methods needed by the datetime methods you use. The datetime module does not supply any concrete subclasses of tzinfo.

上面是说tzinfo是一个抽象类,不应该被直接实例化。你需要派生子类,提供相应的标准方法。datetime模块并不提供tzinfo的任何子类。
所以你可能会使用pytz这个模块。通过easy_install可以安装。

关于时区使用的几点想法:
1. 如果你的网站可能有来自其它时区的,可能你要考虑这个问题。都是一个地区的话,还要看服务器是否与用户在一个地区,如果不在,也要考虑。
2. 因此,基本上要考虑服务器时区与用户时区。服务器时区可以配置在系统中,全局生效。而用户时区则与用户相关,可以由用户自已进行设置。
3. 在生成相关时间对象时要加入时区的信息,并在输出时进行合适的转换。


而pytz提供了创建某个时区对象的方法,如:
# 查看中国时区
>>> import pytz
>>> pytz.country_timezones('cn')
['Asia/Shanghai','Asia/Urumqi']

可以看到,中国的时区有:'Asia/Shanghai','Asia/Urumqi'。

# 创建一个时区对象:
>>> tz = pytz.timezone('Asia/Shanghai')
# 然后在创建时间对象时进行指定:
>>> import datetime
>>> datetime.datetime.now(tz)
datetime.datetime(2009,2,21,15,12,33,906000,tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>> datetime.datetime(2009,tzinfo=tz)
datetime.datetime(2009,tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)
>>> datetime.date(2009,tzinfo=tz)
Traceback (most recent call last):
File "<stdin>",line 1,in <module>
TypeError: 'tzinfo' is an invalid keyword argument for this function
>>> datetime.time(15,tzinfo=tz)
datetime.time(15,tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)

从上面可以看出now(),datetime(),time()都是可以指定tzinfo信息的,而date是不行的,不知道为什么。所以最好的方法是内部使用datetime对象,需要时进行时区转换,然后再输出。

时区转换:
>>> utc = pytz.utc
>>> n = datetime.datetime.now(tz)
>>> n
datetime.datetime(2009,16,41,843000,tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>> new = n.astimezone(utc)
>>> new
datetime.datetime(2009,7,tzinfo=<UTC>)
>>> utc.normalize(n.astimezone(utc))
datetime.datetime(2009,tzinfo=<UTC>)

utc是世界标准时间。
上面的代码通过astimezone(utc)将中国时间转为utc标准时间,可以看到不同的时区时间已经不一样了。不过在pytz的文档上说:
Converting between timezones also needs special attention. This also needs to use the normalize method to ensure the conversion is correct.

要注意什么呢?是 daylight savings time,中文叫【日光节约时间】或【夏令时】。对于有采用了夏时制的要使用normzlize来处理,不采用的,直接使用astimezone来处理。所以在通常情况下使用astimezone()就足够了。

另外pytz还提供了全部的timezone信息,如:

>>> from pytz import all_timezones
>>> len(all_timezones)
591
>>> from pytz import common_timezones
>>> len(common_timezones)
439

时区转换时发现的问题:
>>> import pytz,datetime
>>> tz = pytz.timezone('Asia/Shanghai')
>>> tz
<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>

可以看到,它有一个LMT,这是Local Mean Time的缩写,网上查一查意思是本地平均时。而且时间是+8:06,说明与UTC的时差不是8个小时整。先不管它,让我们转换一下试试。

>>> d = datetime.datetime(2009,23,18,5,tzinfo=tz)
>>> d
datetime.datetime(2009,tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)

这时,时区与tz是一样的,没问题。

>>> x = d.astimezone(pytz.utc)
>>> x
datetime.datetime(2009,tzinfo=<UTC>)

我们转为UTC时区,时间上有差异,没问题。

再转回来。

>>> x.astimezone(tz)
datetime.datetime(2009,tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)

奇怪,看到了吧,变成了CST了。时差也成了+8:00了。CST就是Central Standard Time的意思。但这样就造成了转换的不一致。我们应该使用CST标准才对。

让我们再看一下:

>>> datetime.datetime.now(tz)
datetime.datetime(2009,22,11,125000,tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
>>> datetime.time(23,tzinfo=tz)
datetime.time(23,tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>)

可以看到now()函数得到的是CST的,而time传入tzinfo是LMT的。(date不支持tzinfo参数)所以我们要进行修订,怎么做,使用timezone对象的localize()方法,如:

>>> d = datetime.datetime(2009,5)
>>> tz.localize(d)
datetime.datetime(2009,tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)

所以我才明白pytz的文档上说的:

Creating localtimes is also tricky,and the reason why working with local times is not recommended. Unfortunately,you cannot just pass a ‘tzinfo’ argument when constructing a datetime.

所以我的建议是生成带时区的时间时,一定要使用timezone.localize()来生成。不要在时间对象的构造函数中传入tzinfo的方式来实现,为些我封装了一些函数放在了uliweb/utils/date.py中。

另外关于北京时间。在pytz中,我无法找到Asia/Beijing和GMT+8这样的时区设置,但是有些时间转换的工具却有。按理说pytz使用的是标准的时区数据库,我特意下载了查看,的确是没有。

时区处理的确是挺麻烦的事。象有些数据库也支持这样的功能,如postgres支持set timezone的命令,这是在django中看到的。

?

done!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读