默认情况下,所有datetime对象都是幼稚的。要使其具有时区意识,您必须附加一个tzinfo对象,该对象提供UTC偏移量和时区缩写作为日期和时间的函数。
固定偏移时区
对于与UTC有固定偏移量的时区,在Python 3.2+中,该datetime模块提供了timezone类的具体实现,该类tzinfo带有timedelta和一个(可选)name参数:
from datetime import datetime, timedelta, timezone JST = timezone(timedelta(hours=+9)) dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=JST) print(dt) # 2015-01-01 12:00:00 + 09:00 print(dt.tzname()) # UTC + 09:00 dt = datetime(2015, 1, 1, 12, 0, 0, tzinfo=timezone(timedelta(hours=9), 'JST')) print(dt.tzname) # 'JST'
对于3.2之前的Python版本,有必要使用第三方库,例如dateutil。dateutil提供了一个等效的类,tzoffset(从2.5.3版开始)采用形式为的参数,其中以秒为单位指定:dateutil.tz.tzoffset(tzname, offset)offset
from datetime import datetime, timedelta from dateutil import tz JST = tz.tzoffset('JST', 9 * 3600) # 每小时3600秒 dt = datetime(2015, 1, 1, 12, 0, tzinfo=JST) print(dt) # 2015-01-01 12:00:00 + 09:00 print(dt.tzname) # 'JST'
夏令时的区域
对于具有夏令时的区域,python标准库不提供标准类,因此有必要使用第三方库。pytz并且dateutil是提供时区类的流行图书馆。
除了静态时区,dateutil还提供使用夏时制的时区类(请参阅该tz模块的文档)。您可以使用该方法获取时区对象,然后将其直接传递给构造函数:tz.gettz()datetime
from datetime import datetime from dateutil import tz local = tz.gettz() # 当地时间 PT = tz.gettz('US/Pacific') # 太平洋时间 dt_l = datetime(2015, 1, 1, 12, tzinfo=local) # 我在美国东部时间 dt_pst = datetime(2015, 1, 1, 12, tzinfo=PT) dt_pdt = datetime(2015, 7, 1, 12, tzinfo=PT) # DST是自动处理的 print(dt_l) # 2015-01-01 12:00:00-05:00 print(dt_pst) # 2015-01-01 12:00:00-08:00 print(dt_pdt) # 2015-07-01 12:00:00-07:00
注意:从2.5.3版开始,dateutil不能正确处理不明确的日期时间,并且始终默认为较晚的日期。无法使用dateutil时区表示表示时间的对象,例如2015-11-01 1:30 EDT-4,因为这是在夏令时过渡期间。
使用时,所有的边缘案件得到妥善处理pytz,但pytz时区应该不是通过构造函数直接连接到时区。而是pytz应使用时区的localize方法附加时区:
from datetime import datetime, timedelta import pytz PT = pytz.timezone('US/Pacific') dt_pst = PT.localize(datetime(2015, 1, 1, 12)) dt_pdt = PT.localize(datetime(2015, 11, 1, 0, 30)) print(dt_pst) # 2015-01-01 12:00:00-08:00 print(dt_pdt) # 2015-11-01 00:30:00-07:00
请注意,如果您在pytz-aware时区上执行日期时间算术,则必须以UTC执行计算(如果您希望绝对经过的时间),或者必须调用normalize()结果:
dt_new = dt_pdt + timedelta(hours=3) # 这应该是太平洋标准时间上午2:30 print(dt_new) # 2015-11-01 03:30:00-07:00 dt_corrected = PT.normalize(dt_new) print(dt_corrected) # 2015-11-01 02:30:00-08:00