1
2
3
4
5
6
7
8
9
|
'''
不同于int,str,float,Python没有包含对应日期和时间的原生类型,不过提供了3个相应的模块,可以采用多种表示来管理日期和时间值
time模块由底层C库提供与时间相关的函数。它包含一些函数,可以用于获取时钟时间和处理器运行时间,还提供了基本的解析和字符串格式化工具
datetime模块为日期、时间以及日期时间值提供了一个更高层接口。datetime中的类支持算术、比较和时区配置
calendar模块可以创建周、月、年的格式化表示。它还可以用来计算重复事件,给定日期的话是星期几,以及其他基于日历的值
'''
|
(一)time:时钟时间
1
2
3
4
5
|
'''
time模块允许访问多种类型的时钟,分别用于不同的用途。
标准系统调用(如time())会报告系统"墙上时钟"时间。monotonic()时钟可以用于测量一个长时间运行的进程的耗用时间,因为即使系统时间有改变,也能保证这个时间不会逆转。
以及其他的功能我们慢慢介绍
'''
|
1.比较时钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
import
time
import
textwrap
'''
时钟的实现细节因平台而异。可以使用get_clock_info()获得当前实现的基本信息,包括时钟的分辨率
'''
available_clocks
=
[
(
"clock"
, time.clock),
(
"monotonic"
, time.monotonic),
(
"perf_counter"
, time.perf_counter),
(
"process_time"
, time.process_time),
(
"time"
, time.time)
]
for
clock_name, func
in
available_clocks:
info
=
time.get_clock_info(clock_name)
print
(textwrap.dedent(f
'''
{clock_name}:
adjustable: {info.adjustable}
implementation: {info.implementation}
monotonic: {info.monotonic}
resolution: {info.resolution}
current: {func()}
'''
))
'''
clock:
adjustable: False
implementation: QueryPerformanceCounter()
monotonic: True
resolution: 4.109233282817159e-07
current: 0.239568711
monotonic:
adjustable: False
implementation: GetTickCount64()
monotonic: True
resolution: 0.015600099999999999
current: 20896.24
perf_counter:
adjustable: False
implementation: QueryPerformanceCounter()
monotonic: True
resolution: 4.109233282817159e-07
current: 0.239739244
process_time:
adjustable: False
implementation: GetProcessTimes()
monotonic: True
resolution: 1e-07
current: 0.2808018
time:
adjustable: True
implementation: GetSystemTimeAsFileTime()
monotonic: False
resolution: 0.015600099999999999
current: 1552032134.9916494
'''
|
2.墙上时钟时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import
time
'''
time模块的核心函数之一是time(),它会把从"纪元"开始以来的秒数作为一个浮点值返回
'''
print
(
"the time is:"
, time.time())
# the time is: 1552033201.089945
'''
纪元是时间测量的起点,对于Unix平台系统这个起点时间就是1970年1月1日0点0分0秒。
time.time()得到结果就是当前时间相对于起点过了多少秒。这个值是一个浮点数,具体的精度依赖于具体的平台
'''
# 浮点数表示对于存储或比较日期很有用,但是对于生成人类可读的表示就有些差强人意了。要记录或打印时间,ctime()或许是更好的选择。
print
(
"the time is:"
, time.ctime())
# the time is: Fri Mar 8 17:22:59 2019
later
=
time.time()
+
15
# time.ctime可以接收一个时间戳,不传参数的话,默认是当前的时间戳
print
(
"15 secs from now:"
, time.ctime(later))
# 15 secs from now: Fri Mar 8 17:23:14 2019
|
3.单调时钟
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import
time
'''
由于time()查看系统时钟,并且用户或系统服务可能改变系统时钟来同步多个计算机上的时钟,所以反复调用time()所产生的的值可能向前或向后。
试图测量持续时间或者使用这些时间来完成计算时,这可能会导致意想不到的行为。为了避免这些情况,可以使用monotonic,它总是返回向前的值。
'''
start
=
time.monotonic()
time.sleep(
0.1
)
end
=
time.monotonic()
print
(f
"start: {start:>9.2f}"
)
# start: 27083.08
print
(f
"end : {end:>9.2f}"
)
# end : 27083.18
print
(f
"span : {end-start:>9.2f}"
)
# span : 0.1
'''
单调时钟的起始点没有被定义,所以返回值只是在与其他时钟值完成计算时完成计算时有用。
在这个例子中,使用monotonic来测量睡眠持续时间
'''
|
4.处理器时钟时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
import
time
import
hashlib
'''
time()返回的是一个墙上的时钟时间,而clock()返回处理器时钟时间。
clock()返回的值反映了程序运行时使用的实际时间
'''
# 但是不推荐这个方法为什么呢?
'''
DeprecationWarning: time.clock has been deprecated in Python 3.3
and will be removed from Python 3.8: use time.perf_counter or time.process_time instead
'''
# 所以这个就跳过了
|
5.性能计数器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
import
time
import
hashlib
'''
在测量性能时,高分辨率时钟是必不可少的。
要确定最好的时钟数据源,需要有平台特定的知识,Python通过perf_counter()来提供所需的这些知识
'''
data
=
open
(__file__,
"rb"
).read()
loop_start
=
time.perf_counter()
for
i
in
range
(
5
):
iter_start
=
time.perf_counter()
h
=
hashlib.sha1()
for
i
in
range
(
100000
):
h.update(data)
cksum
=
h.hexdigest()
now
=
time.perf_counter()
# 叠加计算循环时间
loop_elapsed
=
now
-
loop_start
# 计算每一次的循环时间
iter_elapsed
=
now
-
iter_start
print
(f
"{time.time(): .3f} : {iter_elapsed: .3f} : {loop_elapsed: .3f}"
)
'''
1552040433.357 : 0.269 : 0.269
1552040433.632 : 0.275 : 0.543
1552040433.901 : 0.269 : 0.812
1552040434.172 : 0.271 : 1.083
1552040434.495 : 0.323 : 1.407
'''
# 类似于monotonic,perf_counter的纪元未定义,所以返回值只用于比较和计算值,而不作为绝对时间
|
6.时间组成
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
|
import
time
'''
有些情况下需要把时间存储为过去了多少秒(秒数),但是另外一些情况下,程序需要访问一个时期的各个字段(例如,年月日)。
time模块定义了struct_time来保存日期和时间值,其中分解了各个组成部分以便于访问。
很多函数都要处理struct_time值而不是浮点值
'''
print
(time.gmtime())
# time.struct_time(tm_year=2019, tm_mon=3, tm_mday=8, tm_hour=10, tm_min=27, tm_sec=29, tm_wday=4, tm_yday=67, tm_isdst=0)
print
(time.localtime())
# time.struct_time(tm_year=2019, tm_mon=3, tm_mday=8, tm_hour=18, tm_min=27, tm_sec=53, tm_wday=4, tm_yday=67, tm_isdst=0)
print
(time.mktime(time.gmtime()))
# 1552012197.0
'''
gmtime函数以UTC格式返回当前时间。localtime会返回应用了当前的时区的系统时间,mktime取一个time_struct实例,返回时间戳
'''
def
show_struct(s: time.struct_time):
print
(f
"年:"
, s.tm_year)
print
(f
"月:"
, s.tm_mon)
print
(f
"日:"
, s.tm_mday)
print
(f
"时:"
, s.tm_hour)
print
(f
"分:"
, s.tm_min)
print
(f
"秒:"
, s.tm_sec)
print
(f
"这一周的第几天,从0开始,0是周一:"
, s.tm_wday)
print
(f
"这一年的第几天:"
, s.tm_yday)
print
(f
"是否时夏令时的旗帜:"
, s.tm_isdst)
show_struct(time.localtime())
'''
年: 2019
月: 3
日: 8
时: 18
分: 36
秒: 4
这一周的第几天,从0开始,0是周一: 4
这一年的第几天: 67
是否时夏令时的旗帜: 0
'''
# 此外我再补充一下gmtime和localtime,这个和ctime一样。可以接收一个时间戳,如果不传参,那么默认是当前系统的时间戳
print
(time.localtime(
1
))
# time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=8, tm_min=0, tm_sec=1, tm_wday=3, tm_yday=1, tm_isdst=0)
'''
相当于从纪元过了1秒钟
'''
|
7.处理时区
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import
time
import
os
'''
用于确定当前时间的函数有一个前提,即已经设置了时区,其可以由程序设置,也可以使用系统的默认时区。
修改时区不会改变具体的时间,只会改变时间的方式。
要改变时区,需要设置环境变量tz,然后调用tzset()。设置时区时可以指定很多细节,甚至细致到夏令时的开始和结束时间。
不过通常更容易的做法是使用时区名,由底层库推导出其他信息。
'''
def
show_zone_info():
print
(
"TZ:"
, os.environ.get(
"TZ"
,
"not set"
))
print
(
"tzname:"
, time.tzname)
print
(
"Zone:"
, time.timezone, time.timezone
/
3600
)
print
(
"DST:"
, time.daylight)
print
(
"Time:"
, time.ctime())
print
(
"-"
*
20
)
print
(
"Default"
)
show_zone_info()
ZONES
=
[
"GMT"
,
"Europe/Amsterdam"
]
for
zone
in
ZONES:
# 这两行代码是为了让我们改变时区的,先设置环境变量TZ,然后调用time.tzset()
os.environ[
"TZ"
]
=
zone
time.tzset()
# 此方法不适用于Windows
print
(
"zone:"
)
show_zone_info()
|
8.解析和格式化时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
import
time
'''
函数strptime和strftime可以在时间值的struct_time表示和字符串表示之间进行转换。
这两个函数支持大量格式化指令,允许不同方式的输入和输出
'''
# 接收一个字符串格式的日期,和以及格式化的参数,得到struct_time
parsed
=
time.strptime(
"2018-5-12 16:14:25"
,
"%Y-%m-%d %H:%M:%S"
)
# %H-%M-%S也可以写成%X
print
(parsed)
# time.struct_time(tm_year=2018, tm_mon=5, tm_mday=12, tm_hour=16, tm_min=14, tm_sec=25, tm_wday=5, tm_yday=132, tm_isdst=-1)
# 传入一个格式化的参数,和一个struct_time,得到一个字符串格式的日期
print
(time.strftime(
"%m-%d-%Y %X"
, parsed))
# 05-12-2018 16:14:25
# strptime:将字符串格式的日期转为struct_time
# strftime:将struct_time转为字符串格式的日期
|
(二)datetime:日期和时间值管理
1
2
3
|
'''
datetime包含一些函数和类,用于完成日期和时间的解析、格式化和算术运算
'''
|
1.时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import
datetime
'''
时间值可以用time表示。time实例包含hour,minute,second和microsecond属性,还可以包含时区信息。
'''
t
=
datetime.time(
1
,
2
,
3
)
print
(f
"hour: {t.hour}"
)
# hour: 1
print
(f
"minute: {t.minute}"
)
# minute: 2
print
(f
"second: {t.second}"
)
# second: 3
print
(f
"microsecond: {t.microsecond}"
)
# microsecond: 0
print
(f
"tzinfo: {t.tzinfo}"
)
# tzinfo: None
# time实例只包含时间值,而不包含和时间值关联的日期值
print
(f
"earliest: {datetime.time.min}"
)
# earliest: 00:00:00
print
(f
"latest: {datetime.time.max}"
)
# latest: 23:59:59.999999
print
(f
"resolution: {datetime.time.resolution}"
)
# resolution: 0:00:00.000001
|
2.日期
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
import
datetime
'''
日期日历值用date类表示。date实例包含year,month,day等属性。使用date()类方法很容易创建一个表示当前日期的日期实例
'''
today
=
datetime.datetime.today()
print
(today)
# 2019-03-18 17:07:53.787871
print
(f
"ctime: {today.ctime()}"
)
# ctime: Mon Mar 18 17:07:53 2019
# 得到的是一个时间元组
print
(today.timetuple())
# time.struct_time(tm_year=2019, tm_mon=3, tm_mday=18, tm_hour=17, tm_min=7, tm_sec=53, tm_wday=0, tm_yday=77, tm_isdst=-1)
print
(f
"original: {today.toordinal()}"
)
# original: 737136
print
(f
"year: {today.year}"
)
# year: 2019
print
(f
"month: {today.month}"
)
# month: 3
print
(f
"day: {today.day}"
)
# day: 18
# 创建指定年月的日期,如果不包含时分秒,那么可以使用date函数。
# 包含时分秒使用datetime函数
print
(datetime.date(
2018
,
11
,
12
))
# 2018-11-12
print
(datetime.datetime(
2018
,
11
,
12
))
# 2018-11-12 00:00:00
print
(datetime.datetime(
2018
,
11
,
12
,
23
,
12
))
# 2018-11-12 23:12:00
# 还可以对date进行替换
d
=
datetime.date(
2018
,
11
,
15
)
print
(d.replace(year
=
1999
))
# 1999-11-15
print
(d.replace(year
=
1999
, month
=
5
))
# 1999-05-15
|
3.日期的运算和比较
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
import
datetime
'''
先来介绍一下时间间隔,timedelta,顾名思义就是隔了多长时间
可以对两个timedelta进行算术运算,也可以结合datetime和timedelta得到一个新的datetime
'''
d
=
datetime.date(
2018
,
12
,
11
)
delta1
=
datetime.timedelta(days
=
1
)
print
(f
"next_day: {d+delta1}"
)
# next_day: 2018-12-12
delta2
=
datetime.timedelta(weeks
=
1
)
print
(f
"next_week: {d+delta2}"
)
# next_week: 2018-12-18
delta3
=
datetime.timedelta(days
=
-
1
)
print
(f
"last_day: {d+delta3}"
)
# last_day: 2018-12-10
'''
timedelta支持的参数如下:
days, seconds, microseconds, milliseconds, minutes, hours, weeks
'''
# 日期也可以进行比较
d1
=
datetime.date(
2018
,
12
,
1
)
d2
=
datetime.date(
2018
,
8
,
19
)
print
(d1 > d2)
# True
# 日期也可以进行运算
print
(d1
-
d2)
# 104 days, 0:00:00
print
((d1
-
d2).days)
# 104
|
4.结合日期和时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import
datetime
'''
使用datetime类可以存储由日期和时间分量构成的值。
date只是包含年月日
datetime则是年月日时分秒
'''
print
(f
"Now: {datetime.datetime.now()}"
)
# Now: 2019-03-18 17:33:57.287297
print
(f
"Today: {datetime.datetime.today()}"
)
# Today: 2019-03-18 17:33:57.287297
# 由于咱们在东八区,所以差了八个小时
print
(f
"UTC Now: {datetime.datetime.utcnow()}"
)
# UTC Now: 2019-03-18 09:33:57.287297
d
=
datetime.datetime.now()
print
(d.month)
# 3
print
(d.year)
# 2019
print
(d.day)
# 18
print
(d.hour)
# 17
print
(d.minute)
# 33
print
(d.second)
# 57
# 此外还可以通过combine方法创建datetime实例
t
=
datetime.time(
1
,
2
,
3
)
d
=
datetime.date(
2011
,
12
,
11
)
print
(datetime.datetime.combine(d, t))
# 2011-12-11 01:02:03
# 或者通过时间戳来创建
import
time
t
=
time.time()
+
1000000
print
(datetime.datetime.fromtimestamp(t))
# 2019-03-30 07:23:53.256506
# 当然通过时间戳的话,date也是可以的
print
(datetime.date.fromtimestamp(t))
# 2019-03-30
|
5.格式化和解析
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
import
datetime
'''
datetime模块和time模块一样也提供了strptime和strftime函数来对字符串和datetime对象进行解析
'''
now
=
datetime.datetime.now()
print
(now)
# 2019-03-18 17:44:06.537144
# 可以使用datetime实例对象调用,当然也可以使用datetime.datetime.strftime(now, format)方法
s
=
now.strftime(
"%Y-%m-%d ---- %X"
)
print
(
type
(s))
# <class 'str'>
print
(s)
# 2019-03-18 ---- 17:44:06
# 此外还可以将字符串格式的日期转换成datetime对象
s
=
"2018-12-11 14:25:25"
d
=
datetime.datetime.strptime(s,
"%Y-%m-%d %H:%M:%S"
)
print
(
type
(d))
# <class 'datetime.datetime'>
print
(d)
# 2018-12-11 14:25:25
'''
time.strftime: 传入format和struct_time,得到format格式的字符串
datetime.datetime.strftime:传入datetime对象和format,得到format格式的字符串。此外这个方法也可以使用实例去调用
time.strptime:传入日期格式的字符串和format,得到struct_time
datetime.datetime.strptime:传入日期格式的字符串和format,得到datetime对象
'''
|
6.时区
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import
datetime
'''
关于设置时区,不推荐datetime模块。可以使用一个第三方模块叫pytz
'''
import
pytz
# 可以看到全部的时区有591个
print
(
len
(pytz.all_timezones))
# 591
# 可以看到中国的时区有两个,分别是上海和乌鲁木齐
print
(pytz.country_timezones(
"cn"
))
# ['Asia/Shanghai', 'Asia/Urumqi']
print
(datetime.datetime.now())
# 2019-03-18 18:10:45.735613
# 设置时区
tz
=
pytz.timezone(
"Asia/Shanghai"
)
print
(datetime.datetime.now(tz
=
tz))
# 2019-03-18 18:10:45.736613+08:00
tz
=
pytz.timezone(
"Asia/Urumqi"
)
print
(datetime.datetime.now(tz
=
tz))
# 2019-03-18 16:09:35.343587+06:00
'''
可以看到我所处的时区时Asia/Shanghai,所以设置不设置是一样的,
然而当我设置为乌鲁木齐的时候,会发现早了两个小时。说明当我们这里十二点的时候,乌鲁木齐那里是十点
'''
|
(三)calendar:处理日期
1
2
3
4
5
|
import
calendar
'''
calendar模块定义了Calendar类,其中封装了一些值的计算,如给定的一个月或一年中的周日期。
另外,TextCalendar和HTMLCalendar类可以生成经过预格式化的输出
'''
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
import
calendar
'''
prmonth方法是一个简单的函数,可以生成月的格式化文本输出
'''
c
=
calendar.TextCalendar()
c.prmonth(
2017
,
7
)
'''
July 2017
Mo Tu We Th Fr Sa Su
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
'''
# 如果想按照美国的方式,将TextCalendar配置为一周从星期日开始的话,怎么做呢?
# 只需要加上一个参数即可,当然也可以指定其它,比如星期五,星期六什么的
calendar.TextCalendar(calendar.SUNDAY).prmonth(
2017
,
7
)
'''
July 2017
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
'''
# 此外还有更简单的方法,直接调用模块下的month方法,输入年和月,但需要加上print
print
(calendar.month(
2017
,
7
))
'''
July 2017
Mo Tu We Th Fr Sa Su
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31
'''
|