time标准库的使用
time是python处理时间的标准库,调用方法和其他python各种库的使用是一样的。
import time
time标准库的函数主要分为三大类函数:时间获取,时间格式化,程序计时
1.时间获取
时间格式介绍
在获取时间之前我们要了解这几点:
- 在Python中,通常有这几种方式来表示时间: 1)时间戳 2)格式化的时间字符串 3)元组(struct_time)共九个元素。
- UTC(Coordinated Universal Time,世界协调时)亦即格林威治天文时间,世界标准时间。在中国为UTC+8。DST(Daylight Saving Time)即夏令时。
时间戳(timestamp)的方式:通常来说,时间戳表示的是从1970年1月1日00:00:00开始按秒计算的偏移量。我们运行“type(time.time())”,返回的是float类型。返回时间戳方式的函数主要有time(),clock()等。 - 元组(struct_time)方式:struct_time元组共有9个元素,返回struct_time的函数主要有gmtime(),localtime(),strptime()。
函数讲解
- 获取时间戳格式
time() 获得当前时间戳,即计算机内部时间值,浮点数输出。时间戳一般不常用,但在一些特殊情况下作用是很大,比如网页上的新闻网站新闻时间的源码有很多用的就是时间戳格式,所以我们处理的时候也会用对应的方法处理。
- 获取时间元组形式
常用time.localtime()和time.gmtime() 两个函数来获取时间元组形式,但前者以本地时区作为标准,后者以格林威治时间时区为标准也就是0时区。
time.localtime() #返回给定时间戳对应的本地时间下的时间元祖,默认为当前时间
Out[5]: time.struct_time(tm_year=2019, tm_mon=4, tm_mday=7, tm_hour=12, tm_min=27, tm_sec=19, tm_wday=6, tm_yday=97, tm_isdst=0)
time.gmtime() # 返回给定时间戳对应的UTC时间下的时间元祖,默认为当前时间
Out[6]: time.struct_time(tm_year=2019, tm_mon=4, tm_mday=7, tm_hour=4, tm_min=28, tm_sec=18, tm_wday=6, tm_yday=97, tm_isdst=0)
- 获取时间字符串
简单来说,就是一种人类易读的时间方式,但对于计算机不是一种易读的时间。这两个参数默认参数都是当前时间。
time.asctime() # 返回给定时间的字符串,默认为当前时间
Out[7]: 'Sun Apr 7 12:33:05 2019'
time.ctime() # 同asctime,接受参数为时间戳
Out[8]: 'Sun Apr 7 12:34:44 2019'
2.时间格式化
将时间以合理的方式展示出来 类似字符串格式化,需要有展示模板。
strftime(tpl,ts) tpl是格式化模板字符串,用来定义输出效果 ts是计算机内部时间类型变量。
- 格式化符号
符号 含义
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
备注:
- “%p”只有与“%I”配合使用才有效果。
- 文档中强调确实是0 - 61,而不是59,闰年秒占两秒(汗一个)。
当使用strptime()函数时,只有当在这年中的周数和天数被确定的时候%U和%W才会被计算。
这些是时间格式化的模板,具体使用大家可以看看我例子。
time.strftime(format[, t]):把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)转化为格式化的时间字符串。如果t未指定,将传入time.localtime()。如果元组中任何一个元素越界,ValueError的错误将会被抛出。
time.strftime("%Y-%m-%d %H:%M:%S",time.gmtime())#时间格式化之前处理的时间是元组形式
Out[13]: '2019-04-07 04:49:29'
与之对应的还有一个strptime()函数,time.strptime(string[, format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。在这个函数中,format默认为:"%a %b %d %H:%M:%S %Y"。time.strptime(string[, format]):把一个格式化时间字符串转化为struct_time。实际上它和strftime()是逆操作。
s ='2019-04-07 04:49:29'
time.strptime(s, "%Y-%m-%d %H:%M:%S")
Out[14]: time.struct_time(tm_year=2019, tm_mon=4, tm_mday=7, tm_hour=4, tm_min=49, tm_sec=29, tm_wday=6, tm_yday=97, tm_isdst=-1)
3.计时
测量起止动作所经历时间的过程,这个在检验代码效率和算法都是常用的,常用来设计进度条,测试代码运行时间。
time.sleep(s) 产生时间 ,拟休眠时间,单位是秒,可以是浮点数,程序运行这一行会在这行休眠一定的时间。
time.sleep(3.3)
time.clock():这个需要注意,在不同的系统上含义不同。在UNIX系统上,它返回的是“进程时间”,它是用秒表示的浮点数(时间戳)。而在WINDOWS中,第一次调用,返回的是进程运行的实际时间。而第二次之后的调用是自第一次调用以后到现在的运行时间。(实际上是以WIN32上QueryPerformanceCounter()为基础,它比毫秒表示更为精确)
a =time.clock()
time.sleep(3.3)
b =time.clock()
b-a
Out[21]: 3.3005928388868497
perf_counter() 测量时间 ,返回一个CPU级别的精确时间计数值,单位为秒 由于这个计数值起点不确定,连续调用差值才有意义,和time.clock()类似。
start=time.perf_counter() #起始时间
end=time.perf_counter() #基于起始时间之后的时间
end-start
Out[22]: 2.718578429039553e-05
最后参考别人的博客,觉得这个图对time库总结的很到位。
datime标准库的使用
python中的datetime模块提供了操作日期和时间功能, 该模块提供了五种核心对象:datetime(时间日期类型), date(日期类型), time(时间类型), tzinfo(时区类型), timedelta(时间差类型)。与time模块相比,datetime模块提供的接口更直观、易用,功能也更加强大。
datetime模块提供了处理日期和时间的类,既有简单的方式,又有复杂的方式。它虽然支持日期和时间算法,但其实现的重点是为输出格式化和操作提供高效的属性提取功能。
1.datatime中的类
类名 功能说明
date 日期对象,常用的属性有year, month, day
time 时间对象
datetime 日期时间对象,常用的属性有hour, minute, second, microsecond
datetime_CAPI 日期时间对象C语言接口
timedelta 时间间隔,即两个时间点之间的长度
tzinfo 时区信息对象
这些类的对象都是不可变的。
2.datetime模块中包含的常量
常量 功能说明 用法 返回值
MAXYEAR 返回能表示的最大年份 datetime.MAXYEAR 9999
MINYEAR 返回能表示的最小年份 datetime.MINYEAR 1
3.相关类的介绍
1.data类
- data对象的构成
date对象由year年份、month月份及day日期三部分构成:
date(year,month,day)
使用data对象前,还是得调用datatime这个包
import datetime
通过year, month, day三个数据描述符可以进行访问:
import datetime
a = datetime.date.today()
a
Out[26]: datetime.date(2019, 4, 7)
a.year
Out[31]: 2019
a.month
Out[32]: 4
a.day
Out[33]: 7
也可以通过__getattribute__(…)来获取上述值
a.__getattribute__('year')
Out[34]: 2019
date对象中包含的方法与属性
- 用于日期比较大小的方法
方法名 方法说明 用法
__eq__(…) 等于(x==y) x.__eq__(y)
__ge__(…) 大于等于(x>=y) x.__ge__(y)
__gt__(…) 大于(x>y) x.__gt__(y)
__le__(…) 小于等于(x<=y) x.__le__(y)
__lt__(…) 小于(x x.__lt__(y)
__ne__(…) 不等于(x!=y) x.__ne__(y)
以上方法的返回值为True\False
例子
a=datetime.date(2019,4,7)
b=datetime.date(2019,4,15)
a.__eq__(b)
False
a.__ge__(b)
False
a.__gt__(b)
False
a.__le__(b)
True
a.__lt__(b)
True
a.__ne__(b)
True
- 计算日期的间隔
使用__sub__(…)和__rsub__(…)方法,其实二个方法差不太多,一个是正向操作,一个是反向操作:
方法名 方法说明 用法
__sub__(…) x - y x.__sub__(y)
__rsub__(…) y - x x.__rsub__(y)
a=datetime.date(2019,4,7)
b=datetime.date(2019,4,15)
a.__sub__(b)
Out[38]: datetime.timedelta(-8)
a.__rsub__(b)
Out[39]: datetime.timedelta(8)
计算结果的返回值类型为datetime.timedelta, 如果获得整数类型的结果则按下面的方法操作:
a.__sub__(b).days
Out[40]: -8
a.__rsub__(b).days
Out[41]: 8
- 标准化日期
如果想要让所使用的日期符合ISO标准,那么使用如下三个方法:
1).* isocalendar(…)*:返回一个包含三个值的元组,三个值依次为:year年份,week number周数,weekday星期数(周一为1…周日为7):
a.isocalendar()
Out[42]: (2019, 14, 7)
a.isocalendar()[0]
2019#返回年份
a.isocalendar()[1]
14#返回第几周
a.isocalendar()[2]
7#返回星期几
2). isoformat(…): 返回符合ISO 8601标准 (YYYY-MM-DD) 的日期字符串;
a.isoformat()
Out[44]: '2019-04-07'
3). isoweekday(…): 返回符合ISO标准的指定日期所在的星期数(周一为1…周日为7)
a.isoweekday()
Out[45]: 7
a.weekday()#类似isoweekday(),只不过是weekday(...)方法返回的周一为 0, 周日为 6
Out[46]: 6
其他
对象方法/属性名称 描述
d.year 年
d.month 月
d.day 日
d.replace(year[, month[, day]]) 生成并返回一个新的日期对象,原日期对象不变
d.timetuple() 返回日期对应的time.struct_time对象
d.toordinal() 返回日期是是自 0001-01-01 开始的第多少天
d.weekday() 返回日期是星期几,[0, 6],0表示星期一
d.isoweekday() 返回日期是星期几,[1, 7], 1表示星期一
d.isocalendar() 返回一个元组,格式为:(year, weekday, isoweekday)
d.isoformat() 返回‘YYYY-MM-DD'格式的日期字符串
d.strftime(format) 返回指定格式的日期字符串,与time模块的strftime(format, struct_time)功能相同
d是上面的date时间,具体这些详细讲解可以参考这篇博客python之时间、日期处理模块(datetime)
- 日期的字符串输出
如果你想将日期对象转化为字符串对象的话,可以用到__format__(…)方法以指定格式进行日期输出:
a.__format__('%Y-%m-%d')
Out[47]: '2019-04-07'
a.__format__('%Y/%m/%d')
Out[48]: '2019/04/07'
与此方法等价的方法为strftime()
a.strftime("%Y-%m-%d")
Out[50]: '2019-04-07'
a.__str__()#只是相简单的获得日期的字符串
Out[51]: '2019-04-07'
a.ctime() #获得ctime样式的格式
Out[52]: 'Sun Apr 7 00:00:00 2019'
2.time类
datetime.time的定义
class datetime.time(hour, [minute[, second, [microsecond[, tzinfo]]]])
hour为必须参数,其他为可选参数。各参数的取值范围为
参数名称 取值范围
hour [0, 23]
minute [0, 59]
second [0, 59]
microsecond [0, 1000000]
tzinfo tzinfo的子类对象,如timezone类的实例
1.比较时间大小
相关方法包括:eq(…), ge(…), gt(…), le(…), lt(…), ne(…)
这里的方法与date类中定义的方法大同小异,使用方法与一样
2. 类方法和属性
类方法/属性名称 描述
time.max time类所能表示的最大时间:time(23, 59, 59, 999999)
time.min time类所能表示的最小时间:time(0, 0, 0, 0)
time.resolution 时间的最小单位,即两个不同时间的最小差值:1微秒
3.对象方法和属性
对象方法/属性名称 描述
t.hour 时
t.minute 分
t.second 秒
t.microsecond 微秒
t.tzinfo 返回传递给time构造方法的tzinfo对象,如果该参数未给出,则返回None
t.replace(hour[, minute[, second[, microsecond[, tzinfo]]]]) 生成并返回一个新的时间对象,原时间对象不变
t.isoformat() 返回一个‘HH:MM:SS.%f'格式的时间字符串
t.strftime() 返回指定格式的时间字符串,与time模块的strftime(format, struct_time)功能相同
基本使用
>>> from datetime import time
>>>
>>> time.max
datetime.time(23, 59, 59, 999999)
>>> time.min
datetime.time(0, 0)
>>> time.resolution
datetime.timedelta(0, 0, 1)
>>>
>>> t = time(20, 5, 40, 8888)
>>> t.hour
20
>>> t.minute
5
>>> t.second
40
>>> t.microsecond
8888
>>> t.tzinfo
>>>
>>> t.replace(21)
datetime.time(21, 5, 40, 8888)
>>> t.isoformat()
'20:05:40.008888'
>>> t.strftime('%H%M%S')
'200540'
>>> t.strftime('%H%M%S.%f')
'200540.008888'
4.datetime类
定义
class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
year, month 和 day是必须要传递的参数, tzinfo可以是None或tzinfo子类的实例。
1.各参数的取值范围为:
参数名称 取值范围
year [MINYEAR, MAXYEAR]
month [1, 12]
day [1, 指定年份的月份中的天数]
hour [0, 23]
minute [0, 59]
second [0, 59]
microsecond [0, 1000000]
tzinfo tzinfo的子类对象,如timezone类的实例
如果一个参数超出了这些范围,会引起ValueError异常。
2.类方法和属性
类方法/属性名称 描述
datetime.today() 返回一个表示当前本期日期时间的datetime对象
datetime.now([tz]) 返回指定时区日期时间的datetime对象,如果不指定tz参数则结果同上
datetime.utcnow() 返回当前utc日期时间的datetime对象
datetime.fromtimestamp(timestamp[, tz]) 根据指定的时间戳创建一个datetime对象
datetime.utcfromtimestamp(timestamp) 根据指定的时间戳创建一个datetime对象
datetime.combine(date, time) 把指定的date和time对象整合成一个datetime对象
datetime.strptime(date_str, format) 将时间字符串转换为datetime对象
3.对象方法
对象方法/属性名称 描述
dt.year, dt.month, dt.day 年、月、日
dt.hour, dt.minute, dt.second 时、分、秒
dt.microsecond, dt.tzinfo 微秒、时区信息
dt.date() 获取datetime对象对应的date对象
dt.time() 获取datetime对象对应的time对象, tzinfo 为None
dt.timetz() 获取datetime对象对应的time对象,tzinfo与datetime对象的tzinfo相同
dt.replace([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]]) 生成并返回一个新的datetime对象,如果所有参数都没有指定,则返回一个与原datetime对象相同的对象
dt.timetuple() 返回datetime对象对应的tuple(不包括tzinfo)
dt.utctimetuple() 返回datetime对象对应的utc时间的tuple(不包括tzinfo)
dt.toordinal() 同date对象
dt.weekday() 同date对象
dt.isocalendar() 同date独享
dt.isoformat([sep]) 返回一个‘%Y-%m-%d
dt.ctime() 等价于time模块的time.ctime(time.mktime(d.timetuple()))
dt.strftime(format) 返回指定格式的时间字符串
4.基本用法
>>> from datetime import datetime, timezone
>>>
>>> datetime.today()
datetime.datetime(2017, 2, 4, 20, 44, 40, 556318)
>>> datetime.now()
datetime.datetime(2017, 2, 4, 20, 44, 56, 572615)
>>> datetime.now(timezone.utc)
datetime.datetime(2017, 2, 4, 12, 45, 22, 881694, tzinfo=datetime.timezone.utc)
>>> datetime.utcnow()
datetime.datetime(2017, 2, 4, 12, 45, 52, 812508)
>>> import time
>>> datetime.fromtimestamp(time.time())
datetime.datetime(2017, 2, 4, 20, 46, 41, 97578)
>>> datetime.utcfromtimestamp(time.time())
datetime.datetime(2017, 2, 4, 12, 46, 56, 989413)
>>> datetime.combine(date(2017, 2, 4), t)
datetime.datetime(2017, 2, 4, 20, 5, 40, 8888)
>>> datetime.strptime('2017/02/04 20:49', '%Y/%m/%d %H:%M')
datetime.datetime(2017, 2, 4, 20, 49)
>>> dt = datetime.now()
>>> dt
datetime.datetime(2017, 2, 4, 20, 57, 0, 621378)
>>> dt.year
2017
>>> dt.month
2
>>> dt.day
4
>>> dt.hour
20
>>> dt.minute
57
>>> dt.second
0
>>> dt.microsecond
621378
>>> dt.tzinfo
>>> dt.timestamp()
1486213020.621378
>>> dt.date()
datetime.date(2017, 2, 4)
>>> dt.time()
datetime.time(20, 57, 0, 621378)
>>> dt.timetz()
datetime.time(20, 57, 0, 621378)
>>> dt.replace()
datetime.datetime(2017, 2, 4, 20, 57, 0, 621378)
>>> dt.replace(2016)
datetime.datetime(2016, 2, 4, 20, 57, 0, 621378)
>>> dt.timetuple()
time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=20, tm_min=57, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=-1)
>>> dt.utctimetuple()
time.struct_time(tm_year=2017, tm_mon=2, tm_mday=4, tm_hour=20, tm_min=57, tm_sec=0, tm_wday=5, tm_yday=35, tm_isdst=0)
>>> dt.toordinal()
736364
>>> dt.weekday()
5
>>> dt.isocalendar()
(2017, 5, 6)
>>> dt.isoformat()
'2017-02-04T20:57:00.621378'
>>> dt.isoformat(sep='/')
'2017-02-04/20:57:00.621378'
>>> dt.isoformat(sep=' ')
'2017-02-04 20:57:00.621378'
>>> dt.ctime()
'Sat Feb 4 20:57:00 2017'
>>> dt.strftime('%Y%m%d %H:%M:%S.%f')
'20170204 20:57:00.621378'
5.使用datetime.datetime类对时间戳与时间字符串进行转换
5.datetime.timedelta类
timedelta对象表示连个不同时间之间的差值。如果使用time模块对时间进行算术运行,只能将字符串格式的时间 和 struct_time格式的时间对象 先转换为时间戳格式,然后对该时间戳加上或减去n秒,最后再转换回struct_time格式或字符串格式,这显然很不方便。而datetime模块提供的timedelta类可以让我们很方面的对datetime.date, datetime.time和datetime.datetime对象做算术运算,且两个时间之间的差值单位也更加容易控制。
这个差值的单位可以是:天、秒、微秒、毫秒、分钟、小时、周。
1.datetime.timedelta类的定义
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, hours=0, weeks=0)
2.基本参数
-
所有参数都是默认参数,因此都是可选参数。参数的值可以是整数或浮点数,也可以是正数或负数。内部值存储days、seconds 和 microseconds,其他所有参数都将被转换成这3个单位:
-
1毫秒转换为1000微秒
-
1分钟转换为60秒
-
1小时转换为3600秒
-
1周转换为7天
然后对这3个值进行标准化,使得它们的表示是唯一的:
microseconds : [0, 999999]
seconds : [0, 86399]
days : [-999999999, 999999999]
3.类属性
类属性名称 描述
timedelta.min timedelta(-999999999)
timedelta.max timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)
timedelta.resolution timedelta(microseconds=1)
实例方法和属性
实例方法/属性名称 描述
td.days 天 [-999999999, 999999999]
td.seconds 秒 [0, 86399]
td.microseconds 微秒 [0, 999999]
td.total_seconds() 时间差中包含的总秒数,等价于: td / timedelta(seconds=1)
方法/属性 描述
datetime.datetime.now() 返回当前本地时间(datetime.datetime对象实例)
datetime.datetime.fromtimestamp(timestamp) 返回指定时间戳对应的时间(datetime.datetime对象实例)
datetime.timedelta() 返回一个时间间隔对象,可以直接与datetime.datetime对象做加减操作
例子
>>> import datetime
>>>
>>> datetime.timedelta(365).total_seconds() # 一年包含的总秒数
31536000.0
>>> dt = datetime.datetime.now()
>>> dt + datetime.timedelta(3) # 3天后
datetime.datetime(2017, 2, 8, 9, 39, 40, 102821)
>>> dt + datetime.timedelta(-3) # 3天前
datetime.datetime(2017, 2, 2, 9, 39, 40, 102821)
>>> dt + datetime.timedelta(hours=3) # 3小时后
datetime.datetime(2017, 2, 5, 12, 39, 40, 102821)
>>> dt + datetime.timedelta(hours=-3) # 3小时前
datetime.datetime(2017, 2, 5, 6, 39, 40, 102821)
>>> dt + datetime.timedelta(hours=3, seconds=30) # 3小时30秒后
datetime.datetime(2017, 2, 5, 12, 40, 10, 102821)
6.tzinfo对象
讲解tzinfo(时区)对象前,先了解两个概念:
-
UTC时间: 协调世界时。和GMT(格林尼治平均时间)是一个东西,只不过UTC是通过原子钟测量出来,GMT是通过天文观测出来的,所以UTC比GMT精度更高,因此现在世界上不同时区的时间都是以UTC时间为基准,如:北京时间=UTC时间+8小时
-
DST:夏时令(daylight saving time),因为夏天天亮的早,所以有的国家就在一年的某些时段把时间人为的调快一小时,使人们早睡,减少照明亮,充分利用光照资源,从而节约能源。我国也实行过,不过后来废止了。
tzinfo对象是用来表示该时区相对UTC时间差值,和该地区是否执行夏时令的对象。datetime模块所提供的的tzinfo对象是一个抽象基类,也就是说我们不应该直接实例化此对象, 而应该以此类为基类,定义出子类,然后再实例化以供使用。在子类化的时候,需要自定义很多方法,非常繁琐。还好python提供了一个pytz的库,里面自带了适合各个国家和时区的tzinfo对象,我们可以直接使用。
>>> from datetime import datetime
>>> import pytz
>>> utc_tz = pytz.timezone('UTC')
>>> china_tz = pytz.timezone('China/Shanghai')
>>> local_naive = datetime.now()
>>> local_naive
datetime.datetime(2016, 12, 18, 8, 8, 14000)
>>> local_aware = localmoment_aware.replace(china_tz)
datetime.datetime(2016, 12, 18, 8, 8, 14000, tzinfo=<DstTzInfo 'Asia/Shanghai' LMT+8>)
>>> utc_aware = local_aware.astimezone(utc_tz)
>>> utc_aware
datetime.datetime(2016, 12, 18, 0, 8, 14000, tzinfo=<UTC>
>>> utc_aware - local_aware #虽然时区不同但是表示的同一个时间点
datetime.timedelta(0)
注意,aware类型的datetime对象,只能和aware类型的datetime对象进行运算(相减,大小比较等)。navie类型的datetime对象,只能和naive类型的datetime对象进行运算(相减,大小比较等)。aware类型和naive类型之间运算会报错
7.个人总结
datetime 这个包类似一堆书分为很多类,每一类用它专门的用法和作用,是一个多个类形成一个整体的包。Python中处理时间时,使用time模块好,还是用datetime模块好呢?就我个人而言,datetime模块基本上可以满足需要,且用起来确实比较方便。对于time模块,我只是在取当前时间的时间戳时会用到time.time()方法,当然也可以通过datetime.datetime.now().timestamp()来获取,只是显得复杂一点。
8.参考文献
1.Python datetime模块详解、示例
2.Python中的datetime模块的使用
3.python之时间、日期处理模块(datetime)
4.python——时间与时间戳之间的转换