Python的时间模块

时间术语解释

epoch

假设我们要将时间表示成毫秒数,比方说1000000毫秒,那有一个问题必须解决,这个1000000毫秒的起点是什么时间,也就是我们的时间基准点是什么时间?好比身高1.8米,是指相对于站立的地面来说的。这个时间基准点就是 epoch,在 Unix 系统中,这个基准点就是1970年1月1日0点整那个时间点。

格林威治标准时间 GMT

十七世纪,格林威治皇家天文台为了海上霸权的扩张计划而进行天体观测。1675年旧皇家观测所(Old Royal Observatory) 正式成立,到了1884年决定以通过格林威治的子午线作为划分地球东西两半球的经度零度。观测所门口墙上有一个标志 24 小时的时钟,显示当下的时间。

对全球而言,这里所设定的时间是世界时间的参考点,全球都以格林威治的时间作为标准来设定时间,这就是我们耳熟能详的「格林威治标准时间」(Greenwich Mean Time,简称G.M.T.)的由来。如果标示在手表上,则代表此表具有两地时间功能,也就是同时可以显示原居地和另一个国度的时间。

世界协调时间 UTC

多数的两地时间表都以GMT来表示,但也有些两地时间表上看不到GMT字样,出现的反而是UTC这3个英文字母,究竟何谓UTC?事实上,UTC指的是 Coordinated Universal Time- 世界协调时间(又称世界标准时间、世界统一时间),是经过平均太阳时(以格林威治时间GMT为准)、地轴运动修正后的新时标以及以「秒」为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密,因此若以「世界标准时间」的角度来说,UTC比GMT来得更加精准。其误差值必须保持在0.9秒以内,若大于0.9秒则由位于巴黎的国际地球自转事务中央局发布闰秒,使UTC与地球自转周期一致。所以基本上UTC的本质强调的是比GMT更为精确的世界时间标准,不过对于现行表款来说,GMT与UTC的功能与精确度是没有差别的。

夏日节约时间 DST

所谓「夏日节约时间」Daylight Saving Time(简称D.S.T.),是指在夏天太阳升起的比较早时,将时钟拨快一小时,以提早日光的使用,在英国则称为夏令时间(Summer Time)。这个构想于1784年由美国班杰明·富兰克林提出来,1915年德国成为第一个正式实施夏令日光节约时间的国家,以削减灯光照明和耗电开支。 自此以后,全球以欧洲和北美为主的约70个国家都引用这个做法。

系统时间

一般说来就是我们在 Linux 系统上执行 date 命令看到的时间,系统下所有的时间调用(除了直接访问硬件时间的命令)都是使用的这个时间。

硬件时间

主板上BIOS中的时间,由主板电池供电来维持运行,系统开机时要读取这个时间,并根据它来设定系统时间(注意:系统启动时根据硬件时间设定系统时间的过程可能存在时区换算,这要视具体的系统及相关设置而定)。

世界时间

(Universal Time)世界标准时间即UTC。

地方时间

(本地时间,Local Time)由于处在不同的时区,本地时间一般与UTC是不同的,换算方法就是:
本地时间 = UTC + 时区 或 UTC = 本地时间 – 时区。

time 模块

time 模块中时间表现的格式主要有三种:timestamp、struct_time、format time。

timestamp

time 模块中获取时间的基本方法是:

1
2
3
4
>>> import time
>>> time.time()
1562824183.531237
>>>

它返回的是从 epoch 到现在的秒数(即:表示的是从1970年1月1日 00:00:00 开始到现在经历了多少秒),也就是时间戳,用的是 UTC 时间。

struct_time 元组元素结构

time 模块给我们提供了两个方法:

1
2
time.gmtime(t)
time.localtime(t)

两种方法都返回一个 struct_time 的时间元组,该元组包含九个元素:

属性
tm_year(年) 比如 2011
tm_mon(月) 1 - 12
tm_mday(日) 1 - 31
tm_hour(时) 0 - 23
tm_min(分) 0 - 59
tm_sec(秒) 0 - 61
tm_wday(weekday) 0 - 6(0表示周一)
tm_yday(一年中的第几天) 1 - 366
tm_isdst(是否是夏令时) 默认为-1

相比用秒数表示的时间,这样的表示更适合我们理解。这两个函数如果调用时不传参数,它们内部会调用 time.time(),并用返回的秒数做转换。

1
2
3
4
5
6
>>> import time
>>> time.gmtime()
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=11, tm_hour=5, tm_min=56, tm_sec=19, tm_wday=3, tm_yday=192, tm_isdst=0)
>>> time.localtime()
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=11, tm_hour=13, tm_min=56, tm_sec=26, tm_wday=3, tm_yday=192, tm_isdst=0)
>>>

python 同样也提供了将这种 struct_time 转为秒数的方法。time.mktime() 用来把时间元组 struct_time 转为时间戳 timestamp。也就是说 mktime 方法会先找到系统中的时区和 DST 信息,并利用这个信息对 struct_time 进行调整后再换算成秒数。

format time 格式化时间

格式化时间指的是已格式化的结构,使时间更具可读性,包括自定义格式和固定格式。time 模块中提供了两个方法专门处理时间元组与格式化时间的互相转换:

  • strftime 即 string format time,用来将时间格式化成字符串。
  • strptime 即 Parse a string to a time tuple ,用来将字符串解析成时间元组。

对于格式化的时间有如下表示格式:

格式 含义
%a 本地(locale)简化星期名称
%A 本地完整星期名称
%b 本地简化月份名称
%B 本地完整月份名称
%c 本地相应的日期和时间表示
%d 一个月中的第几天(01 - 31)
%H 一天中的第几个小时(24小时制,00 - 23)
%I 第几个小时(12小时制,01 - 12)
%j 一年中的第几天(001 - 366)
%m 月份(01 - 12)
%M 分钟数(00 - 59)
%p 本地am或者pm的相应符
%S 秒(01 - 61)
%U 一年中的星期数。(00 - 53星期天是一个星期的开始。)第一个星期天之前的所有天数都放在第0周
%w 一个星期中的第几天(0 - 6,0是星期天)
%W 和%U基本相同,不同的是%W以星期一为一个星期的开始
%x 本地相应日期
%X 本地相应时间
%y 去掉世纪的年份(00 - 99)
%Y 完整的年份
%Z 时区的名字(如果不存在为空字符)
%% % 字符本身

时间格式转换

为了便于记忆,这里画了一张图来说明三种时间格式的转换关系:

下面列出了时间格式之间的转换示例以及一些其他的方法:

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
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import time

# 生成 timestamp
print(time.time())
# 1521117670.6779785

# 生成 struct_time 本地时间
print(time.localtime())
# time.struct_time(tm_year=2018, tm_mon=3, tm_mday=15, tm_hour=20, tm_min=41, tm_sec=10, tm_wday=3, tm_yday=74, tm_isdst=0)

# 生成 struct_time 格林威治时间
print(time.gmtime())
# time.struct_time(tm_year=2018, tm_mon=3, tm_mday=15, tm_hour=12, tm_min=41, tm_sec=10, tm_wday=3, tm_yday=74, tm_isdst=0)

# timestamp to struct_time 本地时间
print(time.localtime(time.time()))
# time.struct_time(tm_year=2018, tm_mon=3, tm_mday=15, tm_hour=20, tm_min=41, tm_sec=10, tm_wday=3, tm_yday=74, tm_isdst=0)

# timestamp to struct_time 格林威治时间
print(time.gmtime(time.time()))
# time.struct_time(tm_year=2018, tm_mon=3, tm_mday=15, tm_hour=12, tm_min=41, tm_sec=10, tm_wday=3, tm_yday=74, tm_isdst=0)

# struct_time to timestamp
print(time.mktime(time.localtime()))
# 1521117670.0

# format_time to struct_time
print(time.strptime('2011-05-05 16:37:06', '%Y-%m-%d %X'))
# time.struct_time(tm_year=2011, tm_mon=5, tm_mday=5, tm_hour=16, tm_min=37, tm_sec=6, tm_wday=3, tm_yday=125, tm_isdst=-1)

# 生成format_time
print(time.strftime("%Y-%m-%d %X"))
print(time.strftime('%F %T'))
# 2018-03-15 20:46:24

# struct_time to format_time
print(time.strftime("%Y-%m-%d %X", time.localtime()))
# 2018-03-15 20:46:24

time.sleep(t)
# t 推迟执行的秒数,表示进程挂起的时间

# 生成固定格式的时间表示格式
time.asctime(time.localtime())
time.ctime(time.time())
# Thu Mar 15 20:46:24 2018

# 返回处理器时间,3.3开始已废弃 , 改成了time.process_time()测量处理器运算时间,不包括sleep时间,不稳定
print(time.clock())

# 返回与utc时间的时间差,以秒计算
print(time.altzone)

datetime

datatime 模块重新封装了 time 模块,提供更多接口,提供的类有:date,time,datetime,timedelta,tzinfo 。

date 类

语法格式

1
datetime.date(year, month, day)

静态方法和字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import datetime

print('datetime.date.max: ', datetime.date.max)
# date 对象所能表示的最大日期

print('datetime.date.min: ', datetime.date.min)
# date对象所能表示的最小日期

print('datetime.date.today(): ', datetime.date.today())
# 返回一个表示当前本地日期的date对象

import time
print('datetime.date.fromtimestamp(): ', datetime.date.fromtimestamp(time.time()))
# 根据给定的时间戮,返回一个date对象

'''
输出:
datetime.date.max: 9999-12-31
datetime.date.min: 0001-01-01
datetime.date.today(): 2018-03-18
datetime.date.fromtimestamp(): 2018-03-18
'''

方法和属性

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
import datetime

now = datetime.date(2018, 3, 18) # date 对象
tomorrow = now.replace(day=19)
# 生成一个新的日期对象,用参数指定的年,月,日代替原有对象中的属性,原有对象仍保持不变

print(now.year, now.month, now.day) # 年 月 日
print('now: ', now)
print('tomorrow: ', tomorrow)
'''
2018 3 18
now: 2018-03-18
tomorrow: 2018-03-19
'''

print('timetuple():', now.timetuple())
# 返回日期对应的time.struct_time对象
'''
timetuple(): time.struct_time(tm_year=2018, tm_mon=3, tm_mday=18, tm_hour=0, tm_min=0, tm_sec=0, # tm_wday=6, tm_yday=77, tm_isdst=-1)
'''

print('weekday():', now.weekday())
# 返回weekday,如果是星期一,返回0;如果是星期2,返回1,以此类推;
'''
weekday(): 6
'''

print('isoweekday():', now.isoweekday())
# 返回weekday,如果是星期一,返回1;如果是星期2,返回2,以此类推;
'''
isoweekday(): 7
'''

print('isocalendar():', now.isocalendar())
# 返回格式如(year,month,day)的元组;
'''
isocalendar(): (2018, 11, 7)
'''

print('isoformat():', now.isoformat())
# 返回格式如'YYYY-MM-DD’的字符串;
'''
isoformat(): 2018-03-18
'''

print('strftime():', now.strftime("%Y-%m-%d"))
# 和time模块的format相同
'''
strftime(): 2018-03-18
'''

time 类

语法格式

1
datetime.time(hour[ , minute[ , second[ , microsecond[ , tzinfo] ] ] ] )

静态方法和字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import datetime

print('datetime.time.max: ', datetime.time.max)
# time 对象所能表示的最大时间

print('datetime.time.min: ', datetime.time.min)
# time 对象所能表示的最小时间

print('datetime.time.resolution: ', datetime.time.resolution)
# time 对象的最小单位,这里是1微秒

'''
输出
datetime.time.max: 23:59:59.999999
datetime.time.min: 00:00:00
datetime.time.resolution: 0:00:00.000001
'''

方法和属性

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
import datetime

tm = datetime.time(23, 46, 10) # time 对象
print('tm:', tm)
print('time zone: ', tm.tzinfo)
# 时区信息

print('hour: %d, minute: %d, second: %d, microsecond: %d' % (tm.hour, tm.minute, tm.second, tm.microsecond))
# 时 分 秒 微秒

tm1 = tm.replace(hour=20)
# 创建一个新的时间对象,用参数指定的时、分、秒、微秒代替原有对象中的属性,原有对象仍保持不变

print('tm1:', tm1)

print('isoformat(): ', tm.isoformat())
# 返回型如"HH:MM:SS"格式的字符串表示

print('strftime(): ', tm.strftime("%X"))
# 和time模块的format相同

'''
输出
tm: 23:46:10
time zone: None
hour: 23, minute: 46, second: 10, microsecond: 0
tm1: 20:46:10
isoformat(): 23:46:10
strftime(): 23:46:10
'''

datetime 类

datetime 相当于 date 和 time 结合起来。语法格式:

1
datetime.datetime(year, month, day[ , hour[ , minute[ , second[ , microsecond[, tzinfo]]]]])

静态方法和字段

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 time
import datetime

print('datetime.max: ', datetime.datetime.max)
print('datetime.min: ', datetime.datetime.min)
print('datetime.resolution: ', datetime.datetime.resolution)

print('today(): ', datetime.datetime.today())
# 返回一个表示当前本地时间的datetime对象

print('now(): ', datetime.datetime.now())
# 返回一个表示当前本地时间的datetime对象,如果提供了参数tz,则获取tz参数所指时区的本地时间

print('utcnow(): ', datetime.datetime.utcnow())
# 返回一个当前utc时间的datetime对象;格林威治时间

print('fromtimestamp(tmstmp): ', datetime.datetime.fromtimestamp(time.time()))
# 根据时间戮创建一个datetime对象,参数tz指定时区信息

print('utcfromtimestamp(tmstmp): ', datetime.datetime.utcfromtimestamp(time.time()))
# 根据时间戮创建一个datetime对象

'''
输出
datetime.max: 9999-12-31 23:59:59.999999
datetime.min: 0001-01-01 00:00:00
datetime.resolution: 0:00:00.000001
today(): 2018-10-24 11:42:26.772787
now(): 2018-10-24 11:42:26.772817
utcnow(): 2018-10-24 03:42:26.772829
fromtimestamp(tmstmp): 2018-03-18 08:24:10
utcfromtimestamp(tmstmp): 2018-03-18 00:24:10
'''

方法和属性

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
>>> import time
>>> import datetime
>>> dt = datetime.datetime.now() # datetime对象
>>> dt.year
2019
>>> dt.month
7
>>> dt.day
7
>>> dt.hour
21
>>> dt.minute
13
>>> dt.second
35
>>> dt.microsecond
348424
>>> dt.date() # 获取date对象;
datetime.date(2019, 7, 7)
>>> dt.time() # 获取time对象;
datetime.time(21, 13, 35, 348424)
>>>
>>> dt.timetuple()
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=7, tm_hour=21, tm_min=13, tm_sec=35, tm_wday=6, tm_yday=188, tm_isdst=-1)
>>>
>>> dt. utctimetuple ()
time.struct_time(tm_year=2019, tm_mon=7, tm_mday=7, tm_hour=21, tm_min=13, tm_sec=35, tm_wday=6, tm_yday=188, tm_isdst=0)
>>>
>>> dt. weekday ()
6
>>> dt. isocalendar ()
(2019, 27, 7)
>>> dt. isoformat () # 返回格式如'YYYY-MM-DD’的字符串;
'2019-07-07T21:13:35.348424'
>>> dt. ctime () # 返回一个日期时间的C格式字符串,等效于time.ctime(time.mktime(dt.timetuple()));
'Sun Jul 7 21:13:35 2019'
>>>
>>> dt.strftime('%F %T')
'2019-07-07 21:13:35'

timedelta 类 时间加减

使用 timedelta 可以很方便的在日期上做天 day,小时,分钟,秒,毫秒,微秒的时间计算,如果要计算月份则需要另外的办法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import datetime

print(datetime.datetime.now())
# 返回 2018-03-20 23:33:04.677979

print(datetime.date.fromtimestamp(time.time()) )
# 时间戳直接转成日期格式 2018-03-20 23:33:04.677979

# 时间加减
print(datetime.datetime.now() + datetime.timedelta(3)) # 当前时间+3天
print(datetime.datetime.now() + datetime.timedelta(-3)) # 当前时间-3天
print(datetime.datetime.now() + datetime.timedelta(hours=3)) # 当前时间+3小时
print(datetime.datetime.now() + datetime.timedelta(minutes=30)) # 当前时间+30分

# 时间替换
c_time = datetime.datetime.now()
print(c_time.replace(minute=3,hour=2))
有钱任性,请我吃包辣条
0%