8.4 时间处理
8.4.1 datetime模块
datetime 模块提供了可以通过多种方式操作日期和时间的类。在支持日期时间数学运算的同时,实现的关注点更着重于如何能够更有效地解析其属性用于格式化输出和数据操作。
datetime模块定义了下面这几个类:
- datetime.date:表示日期的类。常用的属性有year, month, day。
- datetime.time:表示时间的类。常用的属性有hour, minute, second, microsecond。
- datetime.datetime:表示日期时间。
- datetime.timedelta:表示时间间隔,即两个时间点之间的长度。
- datetime.tzinfo:与时区有关的相关信息。
- datetime.timezone:表示相对于世界标准时间(UTC)的偏移量。
date 对象
date对象表示一个标准日期,包含年,月,日三个整数属性。
>>> import datetime
# date构造函数,三个参数值分别代表年月日
# datetime.date(year, month, day)
>>> date1 = datetime.date(year=2021, month=1, day=1)
>>> date1
datetime.date(2021, 1, 1)
# 返回当地的当前日期
>>> date2 = datetime.date.today()
>>> date2
datetime.date(2020, 1, 10)
>>> type(date2)
<class 'datetime.date'>
time 对象
time对象表示一个时间,独立于日期,包括时,分,秒,微秒等整数属性。
>>> import datetime
# time构造函数,指定对应的属性
# datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
>>> time1 = datetime.time(12, 0, 0, 0)
>>> time1
datetime.time(12, 0)
>>> type(time1)
<class 'datetime.time'>
datetime 对象
datetime对象包含了date对象和time对象。
>>> import datetime
# datetime构造函数
# datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)
>>> datetime1 = datetime.datetime(2020, 10, 1, 0, 0, 0, 0)
>>> datetime1
datetime.datetime(2020, 10, 1, 0, 0)
>>> type(datetime1)
<class 'datetime.datetime'>
# now方法获取当前日期和时间
>>> datetime2 = datetime.datetime.now()
>>> datetime2
datetime.datetime(2020, 1, 10, 14, 48, 13, 255836)
# utcnow方法获取当前UTC日期和时间
>>> datetime3 = datetime.datetime.utcnow()
>>> datetime3
datetime.datetime(2020, 1, 10, 6, 49, 11, 868705)
# today方法等同于now方法
>>> datetime4 = datetime.datetime.today()
>>> datetime4
datetime.datetime(2020, 1, 10, 14, 49, 29, 894566)
timedelta 对象
timedelta对象表示两个date或者time的时间间隔。
>>> import datetime
# timedelta构造函数
# datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)
>>> timedelta1 = datetime.timedelta(7, 0, 0)
>>> timedelta1
datetime.timedelta(days=7)
>>> type(timedelta1)
<class 'datetime.timedelta'>
# 两个时间对象相减,得到timedelta对象
>>> datetime1
datetime.datetime(2020, 10, 1, 0, 0)
>>> datetime2
datetime.datetime(2020, 1, 10, 14, 48, 13, 255836)
>>> timedelta2 = datetime1 - datetime2
>>> timedelta2
datetime.timedelta(days=264, seconds=33106, microseconds=744164)
# 时间对象与timedelta对象运算,得到另一个时间对象
>>> datetime2 - timedelta1
datetime.datetime(2020, 1, 3, 14, 48, 13, 255836)
>>> datetime2 + timedelta1
datetime.datetime(2020, 1, 17, 14, 48, 13, 255836)
8.4.2 time模块
time 模块提供了各种时间相关的函数。侧重于时间的应用。
>>> import time
# time模块的time方法返回浮点数,单位是秒。
>>> t1 = time.time()
>>> t1
1578644638.6917596
>>> type(t1)
<class 'float'>
# sleep方法,参数为秒
>>> time.sleep(2)
time模块提供struct_time结构体,共有九个元素,同一个时间戳的struct_time会因为时区不同而不同。
| 索引 | 属性 | 值 |
|---|---|---|
| 0 | tm_year | 年份数字 |
| 1 | tm_mon | [1, 12] |
| 2 | tm_mday | [1, 31] |
| 3 | tm_hour | [0, 23] |
| 4 | tm_min | [0, 59] |
| 5 | tm_sec | [0, 61] |
| 6 | tm_wday | [0, 6] ,周一为 0 |
| 7 | tm_yday | [1, 366] |
| 8 | tm_isdst | 夏令时相关 |
>>> import time
>>> st1 = time.localtime()
>>> st1
time.struct_time(tm_year=2020, tm_mon=1, tm_mday=10, tm_hour=17, tm_min=3, tm_sec=26, tm_wday=4, tm_yday=10, tm_isdst=0)
>>> type(st1)
<class 'time.struct_time'>
使用time模块的perf_counter和process_time方法,可以计算一段代码的耗时。两个方法的区别在于process_time不包括睡眠期间经过的时间。如果需要更小精度的时间,可以使用这两个方法的纳秒版:perf_counter_ns和process_time_ns。
例如:8.2-time模块计时.py
# time模块计时
# perf_counter / perf_counter_ns : 包括睡眠时间
# process_time / process_time_ns : 不包括睡眠时间
import time
def test():
_sum = 0
for i in range(1000000):
_sum += i
pc1 = time.perf_counter()
pt1 = time.process_time()
test()
time.sleep(2)
pc2 = time.perf_counter()
pt2 = time.process_time()
print('perf_counter :', pc2 - pc1)
print('process_time :', pt2 - pt1)
结果为:
perf_counter : 2.0562915999999998
process_time : 0.046875
8.4.3 时间格式转换
Python 中常见的时间表示格式有下列几种:
时间戳形式:相对于1970.1.1 00:00:00以秒计算的偏移量,时间戳是唯一的,如:1530580203.513723
时间模块类的实例,即datetime模块中的date,time,datetime对象,time模块的struct_time结构体等。
字符串形式,如:2013-10-25 13:29:39.543000
时间格式转换
其中格式化字符串采用下列占位符:
%a星期的简写。如:星期三为Web
%A星期的全写。如:星期三为Wednesday
%b月份的简写。如4月份为Apr
%B月份的全写。如4月份为April
%c: 日期时间的字符串表示。(如: 04/07/10 10:43:39)
%d: 日在这个月中的天数(是这个月的第几天)
%f: 微秒(范围[0,999999])
%H: 小时(24小时制,[0, 23])
%I: 小时(12小时制,[0, 11])
%j: 日在年中的天数 [001,366](是当年的第几天)
%m: 月份([01,12])
%M: 分钟([00,59])
%p: AM或者PM
%S: 秒(范围为[00,61])
%U: 周在当年的周数(是当年的第几周),星期日作为周的第一天
%w: 今天在这周的天数,范围为[0, 6],6表示星期天
%W: 周在当年的周数(是当年的第几周),星期一作为周的第一天
%x: 日期字符串(如:04/07/10)
%X: 时间字符串(如:10:43:39)
%y: 2个数字表示的年份
%Y: 4个数字表示的年份
%z: 与utc时间的间隔 (如果是本地时间,返回空字符串)
%Z: 时区名称(如果是本地时间,返回空字符串)
%%: 字面的 '%' 字符。
8.4.4 timeit模块
timeit 模块提供了一种简单的方法来计算一小段 Python 代码的耗时。
该模块定义了以下函数用于实现计时:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None)
timeit.repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=5, number=1000000, globals=None)
stmt:接受一个将计时的语句或函数。
setup:用于设置的附加语句。
timer:定时器函数,与平台有关,time.perf_counter() 是默认计时器。
number:重复执行的次数,默认为100万次。
repeat:重复调用timeit的次数,默认为5次。
globals:命名空间。
timeit函数返回执行number次stmt代码的总耗时,以秒为单位。
repeat函数执行repeat次timeit函数,返回一个列表,包含repeat个元素,每个元素为执行number次stmt代码的总耗时。
例如:8.3-timeit.py
# timeit模块计时
import timeit
def test():
_sum = 0
for i in range(1000000):
_sum += i
number = 100
repeat = 5
res = timeit.timeit("test()", number=number, setup="from __main__ import test")
print(res / number)
res_list = timeit.repeat("test()", repeat=repeat, number=number, setup="from __main__ import test")
print([i / number for i in res_list])
结果为:
0.068962116
[0.067404231, 0.066871028, 0.06286055299999997, 0.06126845499999998, 0.068811374]