time和datatime
time
时间戳,struct_time和时间格式之间是能互相转换的.
例如时间戳通过time.localtime函数就可以比那位struct_time对象,之后在使用srtftime方法就可以把该时间戳变换为需要格式的时间格式对象.
例如
# 显示当前格式化后的时间 print(time.strftime('%Y-%m-%d %X')) # 显示指定struct_time格式化后的时间 print(time.strftime('%Y-%m-%d %X',time.localtime()))
同时也可以将时间格式对象转换为时间戳对象
my_time = '2021-02-03 02:14:10' str_time = time.strptime(my_time,'%Y-%m-%d %X') print(str_time) # 此时str_time是一个struct_time对象 after_3 = time.mktime(str_time)+24*60*60*3 # 设置新时间为3天后的时间 print(after_3) # 此时是一个时间戳对象 time.strftime('%Y-%m-%d %X',time.localtime(after_3)) # 再把这个时间戳对象以时间格式输出
因此struct_time通常作为时间戳和时间格式之间转换的桥梁,我们可以使用struct_time的属性进行访问其对应的时间值
my_time = '2021-02-03 02:14:10' str_time = time.strptime(my_time,'%Y-%m-%d %X') print(str_time.tm_year) print(str_time.tm_mon) print(str_time.tm_mday) print(str_time.tm_hour) print(str_time.tm_min)
了解了基本的时间戳和struct_time,就需要了解一下时间格式这个对象他的格式定义了
%Y-年[0001,…, 2018,2019,…9999]
%m -月[01,02,…,11,12]
%d -天[01,02,…, 30,31]
%H-小时[00,01,…,22,23
%M -分钟[00,01,…,58,59]
%S -秒[00,01,…,58,61]
%X本地相应时间
%y去掉世纪的年份(00 - 99)
datetime
datatime模块重新封装了time模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo
date
datetime. date(year,month,day)
静态方法和字段
- date.today():返回一个表示当前本地日期的date对象;
- date.fromtimestamp(timestamp):根据给定的时间戮,返回一个date对象
d1 = date(2022,2,2)
- d1.year、date.month、date.day:年、月、日;
- d1.replace(year, month, day):生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性。(原有对象仍保持不变)
- d1.timetuple():返回日期对应的time.struct_time对象;
- d1.weekday():返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
- d1.isoweekday();返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
- d1.isoformat():返回格式如’YYYY-MM-DD’的字符串;
- d1.strftime(fmt):和time模块format相同。
now = date.today() print(now.year,now.month,now.day) first = now.replace(day=1) print('now:',now,',当月第一天:',first) print('timetuple():',now.timetuple()) print('weekday():',now.weekday()) # weekday是从0开始计算星期 print('isoweekday():',now.isoweekday()) # 因此我们都使用isoweekday 他从1开始 print('isoformat():',now.isoformat()) print('strftime():',now.strftime('%Y.%m.%d'))
datetime
datetime相当于date和time结合起来
datetime.datetime(year,month,day[,hour[,minute,second[,microsecond[,tzinfo]]]]])
静态方法
- datetime.today():返回一个表示当前本地时间的datetime对象;
- datetime.now([z]):返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取t参数所指时区的本地时间;
- datetime.fromtimestamp(timestamp[, tz]):根据时间戮创建一个datetime对象,参数tz指定时区信息;
- datetime.strptime(date_string, format):将格式字符串转换为datetime对象
from datetime import datetime now = datetime.now() print(type(now)) print(datetime.today()) # 将datetime转换为指定格式的字符串 print(now.strftime('%Y-%m-%d %X')) print(now.strftime('%Y-%m-%d %H:%M')) # 将字符串转换为datetime my_str = '2022-02-02 12:32' print(datetime.strptime(my_str,'%Y-%m-%d %H:%M')) my_str = '10/11/2021 10:23' print(datetime.strptime(my_str,'%d/%m/%Y %H:%M')) print(type(datetime.strptime(my_str,'%d/%m/%Y %H:%M'))) print('fromtimestamp:',datetime.fromtimestamp(time.time()))
timedelta
该类可以很方便的再日期上做天days,小时hour,分钟,秒,毫秒,微秒的时间计算,如果要计算月份则需要另外的方法
from datetime import datetime from datetime import timedelta dt = datetime.now() dt_1 = dt+timedelta(days=-1)# 昨天 dt_11 = dt-timedelta(days=1) # 昨天 dt_111 = dt+timedelta(days=1)# 明天 print(dt_1) print(dt_11) print(dt_111) dis = dt_111 - dt_1 print(type(dis),dis) print(dis.days,dis.total_seconds()) # 计算天数和时间
时间处理基础
Pandas提供了四种类型的生成日期时间的对象:日期时间、时间增量、时间跨度、臼期偏移量
(1)日期时间(Date Times):具有时区支持的特定日期和时间。与Python标准库中的datetime.datetime类似。如2020年12月6日13点37分50秒;l
(2)时间增量(Time Deltas):绝对持续时间,用于在指定时间点基础上增加指定的增量,如在某年月日的基础上增加2天、增加2个月、减少4小时等,最后产生一个新的时间点;
(3)时间跨度(Time Span):由时间点及其相关周期定义的时间跨度,如连续产生一年四个季度的时间序列;
(4)日期偏移(Date Offsets):以日历计算的相对持续时间,表示时间间隔,两个时间点之间的长度,如日、周、月、季度、年。
时间序列类型
时间戳Timestamp
python datetime的替代品
时间戳相当于python的Datetime,在大多数情况下可以与之互换。
该类型用于组成Datetimelndex的条目,以及pandas中其他面向时间序列的数据结构。
pandas.Timestamp(ts_input=<object object>,freq=None,tz=None,unit=None,year=None,month=None,day=None,hour=None,minute=None,second=None,
microsecond=None,nanosecond=None,tzinfo=None,*, fold=None)
- ts_input:要转换为时间戳的值
- freq:时间戳将具有的偏移量
- unit:用于转换的单位
pd.Timestamp用于将字符串或者unix时间转换为pandas对应的时间戳
print(pd.Timestamp('2022-02-02')) print(pd.Timestamp('2022-12-13 12')) print(pd.Timestamp('02-02-2022 12')) print(pd.Timestamp('2022-01')) # 如果输入的时间是错误的 那么会报错 # print(pd.Timestamp('2022-01-32')) # unit参数为s表示将转换以秒为单位表示Unix历元的浮点值 # 1970-1-1这个时间正是Unix系统的起始时间 # 使用的是格林威治时间 因此有时区偏移八小时 print(pd.Timestamp(time.time(),unit='s')) print(pd.Timestamp(int(time.time()),unit='s')) print(pd.Timestamp(time.time())) # 也可以通过year,month,day,hour,minute,second,microsecond单独设置时间 print(pd.Timestamp(2022,1,2,12)) print(pd.Timestamp(year=2022,month=12,day=1)) print(pd.Timestamp(year=2022,month=12,day=1,hour=12)) # 注意必须至少设置到日 否则报错 # print(pd.Timestamp(year=2022,month=1))
时间间隔–时间datetime加减
表示持续时间,即两个日期或者时间之间的差异
相当于python的datetime.timedelta,在大多数情况下可以与之转换
pd.Timedelta(
value=<object object at 0x000001BE55DCFE80>,
unit=None,
**kwargs,
)
- value:数值或者Timedelta
- unit:如果输入是整数,则表示输入的单位M’,“W” ,‘D’,‘‘T’,‘S’,
ts = pd.Timestamp('2021-02-02 12') print(ts) ts = ts + pd.Timedelta(-1,'D') # day减一 print(ts) td = pd.Timedelta(days=5,minutes=50,seconds=20) print(td) print(ts+td) print('总秒数:',td.total_seconds()) print('今天:',datetime.datetime.now()) print('今天加上时间间隔后的总秒数:',time.time()+td.total_seconds()) # 设置时区 否则会有时间偏移 pd.Timestamp(int(time.time()+td.total_seconds()),unit='s',tz='Asia/Shanghai')
时间转换
to_datetime转换时间戳
你可能会想到,我们经常要和文本数据(字符串)打交道,能否快速将文本数据转为时间戳呢?
答案是可以的,通过 to_datetime 能快速将字符串转换为时间戳。当传递一个Series时,它会返回一个Series(具有相同的索引),而类似列表的则转换为DatetimeIndex。
to_datetime(arg,errors='raise', dayfirst=False,yearfirst=False, utc=None,format=None,unit=None,infer_datetime_format=False,origin='unix')
函数用户将数组、序列或dict的对象转换为datetime对象
- arg要转换为日期时间的对象
- errors :错误处理
If ‘raise’,将引发异常.
If ‘coerce’,无效的转换,使用NaT.
If ‘ignore’,无效的转换,将使用输入的数据. - dayfirst:转换时指定日期分析顺序yearfirst
- utc:控制与时区相关的解析,本地化和转换(忽略)
- format :用于分析时间的strftime,例如“%d/%m/%Y",自定义格式
- unit : D,s,ms将时间戳转datetime
- origin:定义参考日期。数值将被解析为自该参考日期起的单位数
1).处理各种输入格式
从一个数据帧的多个列中组装日期时间。
这些键可以是常见的缩写,
如[‘year’、 ‘month’、 ‘day’、 ‘minute’、 ‘second’、 ‘ms’、 ‘us’、 ‘ns’])
也可以是相同的复数形式
df = pd.DataFrame({'year':[2014,2015],'month':[2,3],'day':[4,5]}) print(df) pd.to_datetime(df)
2).将字符串转datatime
print(pd.to_datetime(['11-12-2021'])) print(pd.to_datetime(['2021/2/3 12:31:22','2022/2/3 12:32:21']))
3).除了可以将文本数据转为时间戳外,还可以将unix时间转为时间戳
print(pd.to_datetime([1347123456,1234567890,1098765432],unit='s')) print(pd.to_datetime([1234567890,1234561231,1234567891],unit='ms'))
4).自动识别异常
print(pd.to_datetime('210605')) # 日月年 print(pd.to_datetime('210605',yearfirst=True))
5).配合unit参数,使用非unix时间
# origin为参考起始时间 print(pd.to_datetime([1,2,3],unit='D',origin=pd.Timestamp('2020-01-11'))) # 距离2020-1-11加1天/2天/3天 print(pd.to_datetime([1,2,3],unit='D')) # 距离1970-1-1加1天/2天/3天 print(pd.to_datetime([1,2,3],unit='h',origin=pd.Timestamp('2020-01'))) print(pd.to_datetime([1,2,3],unit='m',origin=pd.Timestamp('2020-01'))) print(pd.to_datetime([1,2,3],unit='s',origin=pd.Timestamp('2020-01')))
生成时间戳范围
有时候,我们可能想要生成某个范围内的时间戳。例如,我想要生成"2018-6-26"这一天之后的8天时间戳,我们可以使用date_range和bdate_range来完成时间戳范围的生成。
date_range()返回固定频率的Datetimelndex
date_range(start=None,end=None,periods=None,freq=None,tz=None,normalize=False,name=None,closed=None,**kwargs)
返回等距时间点的范围(其中任意两个相邻点之间的差值由给定频率指定),以便它们都满足
开始<[=]x<[=]end,其中第一个和最后一个分别为该范围内的第一个和最后一个时间点位于freq的边界(如果以频率字符串的形式给出)或对freq有效
- start :生成日期的左边界
- end :生成日期的左边界
- periods:要生成的周期数
- freq:频率, default ‘"D’,频率字符串可以有倍数, ‘5H’
- tz:时区用于返回本地化日期时间索引的时区名称,例如“Asia/Hong_Kong”。默认情况下,生成的DatetimeIndex是时区初始索引。
- normalize:默认False,在生成日期范围之前,将开始/结束日期标准化
- name:默认 None设置返回Datetimelndex name
前三个参数介绍
print(pd.date_range(start='2021-8-26',end='2021-9-20')) print(pd.date_range(start='2021',end='2022')) print(pd.date_range(start='1/1/2018',periods=8)) # 指定开始日期,设置期间数 print(pd.date_range(start='2018-04-24',end='2018-04-27',periods=3)) # 指定开始,结束和期间,频率自动生成 print(pd.date_range(start='2018-04-24',periods=4))
freq参数
月缩写:JAN/FEB/MAR/APR/MAYIJUN/JUL/AUGI/SEPIOCT/NOV/DEC星期几缩写:MON/TUE/WED/THU/FRISAT/SUN
所以Q-月只有三种情况:1-4-7-10,2-5-8-11,3-6-9-12
print(pd.date_range('2022/1/1','2022/2/2',freq='W-MON'))# 表示获取时间区间内的Monday周一 print(pd.date_range('2022/1/1','2022/5/1',freq='WOM-2MON')) # 表示week of month 也就是从每个月的第二个周一开始算 print(pd.date_range('2021/1/1','2021/1/4')) # 默认freq=D 也就是每天 print(pd.date_range('2021/1/1','2021/1/5',freq='B')) # B 表示每个工作日 print(pd.date_range('2021/1/1 00:10:00','2021/1/1 00:20:00',freq='T')) # 每分钟 T=MIN print(pd.date_range('2021/1/1 00:10:00','2021/1/1 00:20:10',freq='S')) # 每秒钟 T=MIN print(pd.date_range('2021/1/1 00:10:00','2021/1/1 00:10:01',freq='U')) # 每微妙 十的负六 print(pd.date_range('2021/1/1 00:10:00','2022/1/1 00:20:00',freq='M')) # M 表示获取每月的最后一天的日期 print(pd.date_range('2017','2020',freq='Q-DEC')) # Q-月 指定月为季度末,每个季度末最后一月的最后一个日历日 print(pd.date_range('2017','2020',freq='A-DEC')) # A-月 每年指定月发的最后一个日历日 print(pd.date_range('2017','2018',freq='BM')) # B(M,Q,A),S -->分别表示工作日,以月为频率,以季度为频率,以年为频率
closed
print(pd.date_range('1/1/2021','1/4/2021',closed='right')) # 意思为左开右闭类型 print(pd.date_range('1/1/2021','1/4/2021',closed='left')) # 意思为左闭右开
bdate_range(start=None, end=None, periods=None, freq="B')
返回固定频率的Datetimelndex,默认频率为工作日
print(pd.bdate_range('1/1/2022','2/1/2022'))
日期频率转换
asfreq(freq,method=None,how=None,normalize=False,fill_value=None)
将时间序列转换为指定的频率
- 如果此数据帧的索引是Periodlndex,则新索引是使用PeriodIndex转换原始索引的结果
- 否则,新指数将相当于pd。date_range (start,end,freq=freq),其中start和end分别是原始索引中的第一个和最后一个条目
- 与新索引中未出现在原始索引中的任何时间步对应的值将为空(NaN),除非提供了填充此类未知值的方法
时间频率进行位移
shift(periods=1,freq=None,axis=0,fill_value=None)
按所需的时段数和可选的时间频率进行移位索引。
如果未传递freq,则在不重新调整数据的情况下移动索引。如果传递了freq(在这种情况下,
索引必须是date或datetime,否则将引发NotlmplementedError),只要在索引中设置了freq或推断的_freq属性,就可以推断freq
- periods:要转换的时段数。可以是正面的,也可以是负面的
- freq:如果指定了freq,则索引值会移位,但数据不会重新对齐。也就是说,如果要在移动时扩展索引并保留原始数据
- axis:{0 or ‘index’, 1 or ‘columns’, None}转换方向
- fill_value:填充值
df = pd.DataFrame(np.random.rand(16).reshape((4,4)), index=pd.date_range('20210101','20210104'), columns=list('ABCD')) print(df) df.shift(periods=2) # 正数:数值后移,模式为行 行上数据后移两行 df.shift(periods=1,axis='columns') # 正数:数值后移(滞后),设置为列 也就是列上的数据后移一列 # df.shift(periods=3,fill_value=0) # 正数,数值后移,NaN填充为0 df.shift(periods=3,freq='D') # 当设置freq时,对时间索引移动 也就是对所有的时间加上3天 df.shift(1) per = df/df.shift(1)-1 # 计算变化百分比,这里计算:该时间戳与上一个时间戳的变化 print(per) # 如果<0说明降了 反之增了