本文共 3699 字,大约阅读时间需要 12 分钟。
转自:http://www.keakon.net/2010/12/14/%E7%94%A8datetime%E5%92%8Cpytz%E6%9D%A5%E8%BD%AC%E6%8D%A2%E6%97%B6%E5%8C%BA
Python标准库里提供了time、datetime和calendar这3个模块来进行时间和日期的处理,其中应用最广的是datetime,而转换时区也是靠它来做的。
时区这个玩意非常抽象,处理它时经常弄得我头晕,只好记录下来,免得以后再犯晕。
首先要知道时区之间的转换关系,其实这很简单:把当地时间减去当地时区,剩下的就是格林威治时间了。
例如北京时间的18:00就是18:00+08:00,相减以后就是10:00+00:00,因此就是格林威治时间的10:00。
而把格林威治时间加上当地时区,就能得到当地时间了。
例如格林威治时间的10:00是10:00+00:00,转换成太平洋标准时间就是加上-8小时,因此是02:00-08:00。
而太平洋标准时间转换成北京时间转换也一样,时区相减即可。
例如太平洋标准时间的02:00-08:00,与北京时间相差-16小时,因此结果是18:00+08:00。
而Python的datetime可以处理2种类型的时间,分别为offset-naive和offset-aware。前者是指没有包含时区信息的时间,后者是指包含时区信息的时间,只有同类型的时间才能进行减法运算和比较。
不幸的是datetime模块的函数在默认情况下都只生成offset-naive类型的datetime对象,例如now()、utcnow()、fromtimestamp()、utcfromtimestamp()和strftime()。
其中now()和fromtimestamp()可以接受一个tzinfo对象来生成offset-aware类型的datetime对象,但是标准库并不提供任何已实现的tzinfo类,只能自己动手丰衣足食了…
下面就是实现格林威治时间和北京时间的tzinfo类的例子:
ZERO_TIME_DELTA = timedelta(0)LOCAL_TIME_DELTA = timedelta(hours=8) # 本地时区偏差class UTC(tzinfo): def utcoffset(self, dt): return ZERO_TIME_DELTA def dst(self, dt): return ZERO_TIME_DELTAclass LocalTimezone(tzinfo): def utcoffset(self, dt): return LOCAL_TIME_DELTA def dst(self, dt): return ZERO_TIME_DELTA def tzname(self, dt): return '+08:00'一个tzinfo类需要实现utcoffset、dst和tzname这3个方法。其中utcoffset需要返回夏时令的时差调整;tzname需要返回时区名,如果你不需要用到的话,也可以不实现。
>>> from datetime import datetime>>> import pytz>>> tz = pytz.timezone(pytz.country_timezones('cn')[0])>>> tz>>> datetime.now(tz)datetime.datetime(2010, 12, 14, 19, 26, 12, 656000, tzinfo= )
>>> dt = datetime.now(tz)>>> dtdatetime.datetime(2010, 12, 14, 19, 32, 23, 281000, tzinfo=用同一个tz生成的datetime对象,居然会出现不相等的结果,而且连它们的tzinfo都不一样…)>>> dt2 = datetime(2010, 12, 14, 19, 32, 23, 281000, tzinfo=tz)>>> dt2datetime.datetime(2010, 12, 14, 19, 32, 23, 281000, tzinfo= )>>> dt == dt2False>>> dt - dt2datetime.timedelta(0, 360)>>> dt.tzinfo >>> dt2.tzinfo
>>> dt3 = datetime(2010, 12, 14, 19, 32, 23, 281000)>>> dt3 = tz.localize(dt3)>>> dt3datetime.datetime(2010, 12, 14, 19, 32, 23, 281000, tzinfo=)>>> dt == dt3True
>>> eastern = pytz.timezone('US/Eastern')>>> dt4 = datetime(2002, 10, 27, 1, 0)>>> dt4 = eastern.localize(dt4)>>> print dt42002-10-27 01:00:00-05:00>>> dt5 = dt4 - timedelta(minutes=10)>>> print dt52002-10-27 00:50:00-05:00>>> dt6 = eastern.normalize(dt5)>>> print dt62002-10-27 01:50:00-04:00>>> dt5.tzinfo可以看到,normalize以后,就能正确处理夏时令的变更了。>>> dt6.tzinfo
转载地址:http://bxxci.baihongyu.com/