1 时区处理
Python中时区信息来自第三方库pytz
。
import pytz
# 常用的时区列表(440个)
pytz.common_timezones[-5:]
# ['US/Eastern', 'US/Hawaii', 'US/Mountain', 'US/Pacific', 'UTC']
# 常用的时区集合
pytz.common_timezones_set
# {'Asia/Shanghai', 'Asia/Urumqi', ...}
# 1.pytz查询某个的时区:可以根据国家代码查找这个国家的所有时区
pytz.country_timezones('cn') # ['Asia/Shanghai', 'Asia/Urumqi']
# 2.pytz创建时区对象
# 根据上面得到的时区信息,就可以创建指定的时区对象。
# 比如创建上海时区对象:
tz=pytz.timezone('Asia/Shanghai')
# 3.得到某个时区的时间
# 然后在创建时间对象时进行指定上面时区,就可以得到指定时区的日期时间:
import datetime
# 有两种时间类型:naive和aware
# 第一种:naive,没有表明时区的时间
datetime.datetime.now()
# datetime.datetime(2021, 1, 28, 17, 18, 56, 324868)
# 第二种:aware,有时区的时间
datetime.datetime.now(tz)
# datetime.datetime(2021, 1, 28, 17, 19, 6, 804947, tzinfo=<DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>)
可以发现aware
类型时间多了tzinfo
标识时区
而因为我们获取当前的时候没有传入时区,为naive
类型
所以与有些aware
时间操作会发生异常
其实解决方法也很简单,将naive
转化为aware
类型就好了
怎样转化呢?我找到了这几种方式:
datetime.datetime.now()
# datetime.datetime(2021, 1, 28, 17, 29, 49, 620625)
# 方式一
datetime.datetime.now().replace(tzinfo=pytz.utc)
# datetime.datetime(2021, 1, 28, 17, 30, 0, 718485, tzinfo=<UTC>)
# 方式二
datetime.datetime.now(pytz.utc)
# datetime.datetime(2021, 1, 28, 9, 30, 12, 161834, tzinfo=<UTC>)
# 方式三
pytz.utc.localize(datetime.datetime.now())
# datetime.datetime(2021, 1, 28, 17, 30, 38, 100480, tzinfo=<UTC>)
2 本地化和转换
默认情况下,pandas中的时间序列是naive
时区。从naive
到本地化通过tz_localize
实现:
方式一
import pandas as pd
import numpy as np
# 方式一
rng=pd.date_range('3/9/2012 9:30',periods=6,freq='D')
DatetimeIndex(['2012-03-09 09:30:00', '2012-03-10 09:30:00',
'2012-03-11 09:30:00', '2012-03-12 09:30:00',
'2012-03-13 09:30:00', '2012-03-14 09:30:00'],
dtype='datetime64[ns]', freq='D')
ts=pd.Series(np.random.randn(len(rng)),index=rng)
2012-03-09 09:30:00 -1.206248
2012-03-10 09:30:00 -1.132678
2012-03-11 09:30:00 1.259751
2012-03-12 09:30:00 1.275133
2012-03-13 09:30:00 -1.588024
2012-03-14 09:30:00 -1.083190
Freq: D, dtype: float64
ts_utc=ts.tz_localize('UTC')
2012-03-09 09:30:00+00:00 -1.206248
2012-03-10 09:30:00+00:00 -1.132678
2012-03-11 09:30:00+00:00 1.259751
2012-03-12 09:30:00+00:00 1.275133
2012-03-13 09:30:00+00:00 -1.588024
2012-03-14 09:30:00+00:00 -1.083190
Freq: D, dtype: float64
ts_utc.index
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
一旦时间序列被本地化到某个特定时区,就可以用tz_convert
将其转换到别的时区了:
ts_utc.tz_convert('US/Eastern')
2012-03-09 04:30:00-05:00 -1.206248
2012-03-10 04:30:00-05:00 -1.132678
2012-03-11 05:30:00-04:00 1.259751
2012-03-12 05:30:00-04:00 1.275133
2012-03-13 05:30:00-04:00 -1.588024
2012-03-14 05:30:00-04:00 -1.083190
Freq: D, dtype: float64
对于上面这种序列,可以先本地化到US/Eastern
,然后转化成UTC
或柏林时间:
ts_Eastern=ts.tz_localize('US/Eastern')
ts_Eastern.tz_convert('UTC')
2012-03-09 14:30:00+00:00 -1.206248
2012-03-10 14:30:00+00:00 -1.132678
2012-03-11 13:30:00+00:00 1.259751
2012-03-12 13:30:00+00:00 1.275133
2012-03-13 13:30:00+00:00 -1.588024
2012-03-14 13:30:00+00:00 -1.083190
Freq: D, dtype: float64
ts_Eastern.tz_convert('Europe/Berlin')
2012-03-09 15:30:00+01:00 -1.206248
2012-03-10 15:30:00+01:00 -1.132678
2012-03-11 14:30:00+01:00 1.259751
2012-03-12 14:30:00+01:00 1.275133
2012-03-13 14:30:00+01:00 -1.588024
2012-03-14 14:30:00+01:00 -1.083190
Freq: D, dtype: float64
方式二
# 方式二
rng=pd.date_range('3/9/2012 9:30',periods=6,freq='D',tz='UTC')
DatetimeIndex(['2012-03-09 09:30:00+00:00', '2012-03-10 09:30:00+00:00',
'2012-03-11 09:30:00+00:00', '2012-03-12 09:30:00+00:00',
'2012-03-13 09:30:00+00:00', '2012-03-14 09:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='D')
3 操作时区意识型Timestamp对象
Timestamp对象也能从naive
本地化为aware
,并从一个时区转换到另一个时区:
stamp=pd.Timestamp('2011-03-12 04:00')
# Timestamp('2011-03-12 04:00:00')
stamp_utc=stamp.tz_localize('utc')
# Timestamp('2011-03-12 04:00:00+0000', tz='UTC')
stamp_utc.tz_convert('US/Eastern')
# Timestamp('2011-03-11 23:00:00-0500', tz='US/Eastern')
创建Timestamp对象时,还可以传入一个时区信息:
stamp_sh=pd.Timestamp('2011-03-12 04:00',tz='Asia/Shanghai')
# Timestamp('2011-03-12 04:00:00+0800', tz='Asia/Shanghai')
aware时间类型的Timestamp对象在内部保存了一个UTC时间戳。这个UTC值在时区转换过程中是不会发生变化的:
stamp_utc.value
# 1299902400000000000
stamp_utc.tz_convert('US/Eastern').value
# 1299902400000000000
4 不同时区之间的运算
如果两个时间序列的时区不同,将它们合并之后最后结果会是UTC。
由于时间戳其实是用UTC存储的,所以这是一个简单的运算,并不用发生任何转换:
rng=pd.date_range('3/7/2012 9:30',periods=10,freq='B')
ts=pd.Series(np.random.randn(len(rng)),index=rng)
2012-03-07 09:30:00 -0.529881
2012-03-08 09:30:00 -0.186080
2012-03-09 09:30:00 -1.697626
2012-03-12 09:30:00 -1.698966
2012-03-13 09:30:00 -0.953260
2012-03-14 09:30:00 -1.854349
2012-03-15 09:30:00 -0.326545
2012-03-16 09:30:00 2.185325
2012-03-19 09:30:00 -0.731005
2012-03-20 09:30:00 -1.104334
Freq: B, dtype: float64
ts1=ts[:7].tz_localize('Asia/Shanghai')
ts2=ts1[2:].tz_convert('US/Eastern')
res=ts1+ts2
res.index
DatetimeIndex(['2012-03-07 01:30:00+00:00', '2012-03-08 01:30:00+00:00',
'2012-03-09 01:30:00+00:00', '2012-03-12 01:30:00+00:00',
'2012-03-13 01:30:00+00:00', '2012-03-14 01:30:00+00:00',
'2012-03-15 01:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq='B')
等价于
ts1.tz_convert('utc')
2012-03-07 01:30:00+00:00 -0.529881
2012-03-08 01:30:00+00:00 -0.186080
2012-03-09 01:30:00+00:00 -1.697626
2012-03-12 01:30:00+00:00 -1.698966
2012-03-13 01:30:00+00:00 -0.953260
2012-03-14 01:30:00+00:00 -1.854349
2012-03-15 01:30:00+00:00 -0.326545
Freq: B, dtype: float64