2 理论准备
3 time 模块
4 timedate 模块
4.1 date 类
4.2 time 类
4.3 datetime 类
4.4 datedelta 类
在实际开发过程中, 我们经常会用到日期或者时间, 那么在 Python 中我们怎么获取时间, 以及如何将时间转换为我们需要的格式呢? 在之前的开发中, 也曾遇到 time,datetime 等模块下的不同函数, 这些函数名又很是相似, 几次下来头都昏了, 今天来彻底总结梳理一下 Python 中日期时间获取与格式化.
2 理论准备
首先必须做一点理论准备, 不然待会都不知道为什么会有这些函数. 介绍 3 个概念:
UTC time Coordinated Universal Time, 世界协调时, 又称格林尼治天文时间, 世界标准时间. 与 UTC time 对应的是各个时区的 local time, 也就是本地时间, 例如我们的北京时间.
epoch time 表示时间开始的起点; 它是一个特定的时间, 不同平台上这个时间点的值不太相同, 对于 Unix 而言, epoch time 为 1970-01-01 00:00:00 UTC.
timestamp(时间戳) 也称为 Unix 时间 或 POSIX 时间; 它是一种时间表示方式, 表示从格林尼治时间 1970 年 1 月 1 日 0 时 0 分 0 秒开始到现在所经过的毫秒数, 其值为 float 类型. 但是有些编程语言的相关方法返回的是秒数, 例如我们的天下第一编程语言 - Python 大法就是这样(请不要反驳我). 所谓的时间戳 timestamp 就是当前时间与格林尼治时间 1970 年 1 月 1 日 0 时 0 分 0 秒之间过了多少秒.
相应的, 日期时间就有三种表示方法:
1)stamptime 时间戳, 时间戳表示的是从 1970 年 1 月 1 日 00:00:00 开始按秒计算的偏移量. stamptime 表现为一个 float 类型数据.
2)struct_time 时间元组, 共有九个元素组. stamptime 时间戳和格式化时间字符串之间的转化必须通过 struct_time 才行, 所以 struct_time 时间元组时 3 中时间表示的中心.
3)format time 格式化时间, 已格式化的结构字符串使时间更具可读性. 包括自定义格式和固定格式.
那么, 下面要说的就是怎么获取这三个时间, 并进行这三个时间之间的转化. 先总结一下 time 模块.
3 time 模块
先放两个图:
time 模块中, 几乎所有时间获取与格式转化的函数都在上图中了, 只要理清了这幅图的关系, 那么 time 模块就不再是问题. 图中, 蓝色方块表示那三种时间格式, 箭头表示时间的转化. 下面, 重点来了:
1)获取当前时间的方法只有一个, 那就是通过上图中的函数 1--time.time(). 也就是说, 要想获取当前时间, 只能通过这个方法, 而且获取的是时间戳格式的时间. 想直接获取当前时间的时间元组格式或格式化字符串? 没门, 只能老老实实转化.
2)当传入默认参数时, 指的是使用当前时间作为参数值. 图中带黄色底纹的都是设有默认值的参数(虽然默认值为 None), 函数 2,3 不传入该参数时, 系统会自动获取当前时间的时间戳作为该参数值. 而函数 5 则是系统会自动获取当前时间的时间元组作为该参数值, 不是不能直接获取当前时间的时间元组吗? 是的, 但系统会先获取当前时间的时间戳, 然后转化为时间元组. 上图中只有向左的箭头所代表的函数才有默认值, 就是因为向右才能由时间戳转化得到需要的时间格式.
3) localtime(函数 2)和 gmtime(函数 3)都可以实现将时间戳转化为时间元组, 但是, localtime 转化的是本地时间, gmtime 转为的是世界标准时间.
4)asctime(函数 7)和 ctime(函数 8)只能转为为 %a %b %d %H:%M:%S %Y 格式的字符串时间. 不传入参数时, 用的也是当前时间.
5)struct_time 元组元素结构:
下标 / 索引 | 属性名称 | 描述 |
0 | tm_year | 年份,如 2018 |
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 | 是否为夏令时,可取值为:0 , 1 或 -1,默认值为 - 1 |
struct_time 属性值的获取方式有两种:
可以把它当做一种特殊的有序不可变序列通过 下标 / 索引 获取各个元素的值, 如 t[0]
也可以通过对象名 "t. 属性名" 的方式来获取各个元素的值, 如 t.tm_year.
6)format time 结构化表示:
格式 | 含义 |
%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)time.time()
- >>> import time
- >>> time.time()
- 1544278402.1804464
- 2)time.localtime()
- >>> time.localtime() # 不传入参数
- time.struct_time(tm_year=2018, tm_mon=12, tm_mday=8, tm_hour=22, tm_min=14, tm_sec=58, tm_wday=5, tm_yday=342, tm_isdst=0)
- >>> time.localtime(time.time()) # 传入当前时间
- time.struct_time(tm_year=2018, tm_mon=12, tm_mday=8, tm_hour=22, tm_min=15, tm_sec=33, tm_wday=5, tm_yday=342, tm_isdst=0)
- >>> time.localtime(1544200000.1232) # 传入其他时间戳
- time.struct_time(tm_year=2018, tm_mon=12, tm_mday=8, tm_hour=0, tm_min=26, tm_sec=40, tm_wday=5, tm_yday=342, tm_isdst=0)
- 3)time.gctime()
- >>> time.gmtime()
- time.struct_time(tm_year=2018, tm_mon=12, tm_mday=8, tm_hour=14, tm_min=18, tm_sec=38, tm_wday=5, tm_yday=342, tm_isdst=0)
- 4)time.mktime()
- >>> time.mktime(time.localtime())
- 1544279024.0
- 5)strftime(format, p_tuple=None)
- >>> time.strftime('%y-%m-%d' , time.localtime())
- '18-12-08'
- >>> time.strftime('%Y-%m-%d' , time.localtime())
- '2018-12-08'
- >>> time.strftime('%Y 年 %m 月 %d 日 %M 时 %I 分 %S 秒' , time.localtime())
- '2018 年 12 月 08 日 34 时 10 分 04 秒'
- 6)strptime(string, format)
- >>> time.strptime('2018 年 12 月 08 日 34 时 10 分 04 秒' , '%Y 年 %m 月 %d 日 %M 时 %I 分 %S 秒')
- time.struct_time(tm_year=2018, tm_mon=12, tm_mday=8, tm_hour=10, tm_min=34, tm_sec=4, tm_wday=5, tm_yday=342, tm_isdst=-1)
- 7)asctime(p_tuple=None)
- >>> time.asctime() # 不传入参数, 默认是当前时间
- 'Sat Dec 8 22:42:46 2018'
- >>> time.asctime(time.localtime(1544278402.1804464))
- 'Sat Dec 8 22:13:22 2018'
- 8)ctime(seconds=None)
- >>> time.ctime() # 不传入参数
- 'Sat Dec 8 22:45:58 2018'
- >>> time.ctime(1544278402.1804464)
- 'Sat Dec 8 22:13:22 2018'
4 datetime 模块
datetime 模块是 time 模块的进一步封装, 对用户更加友好, 在时间各属性的获取上回更加方便一些, 当然, 在效率上会略微低一些. datetime 模块的功能主要都几种在 datetime,date,time,timedelta,tzinfo 五个类中. 这五个类功能如下表所示:
类名 | 功能 |
date | 提供日期(年、月、日)的处理 |
time | 提供时间(时、分、秒)的处理 |
datetime | 同时提供对日期和时间的处理 |
timedelta | 两个 date、time、datetime 实例之间的时间间隔(时间加减运算) |
tzinfo | 时区信息 |
4.1 date 类
先来说说 date 类, 其定义如下:
class datetime.date(year, month, day)
year, month 和 day 都是是必须参数, 各参数的取值范围为:
参数名称 | 取值范围 |
year | [MINYEAR, MAXYEAR] |
month | [1, 12] |
day | [1, 指定年份的月份中的天数] |
类方法和属性
类方法 / 属性名称 | 描述 |
date.max | date 对象所能表示的最大日期:9999-12-31 |
date.min | date 对象所能表示的最小日志:00001-01-01 |
date.resoluation | date 对象表示的日期的最小单位:天 |
date.today() | 返回一个表示当前本地日期的 date 对象 |
date.fromtimestamp(timestamp) | 根据跟定的时间戳,返回一个 date 对象 |
对象方法和属性
对象方法 / 属性名称 | 描述 |
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) 功能相同 |
4.2 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 类的实例 |
类方法和属性
类方法 / 属性名称 | 描述 |
time.max | time 类所能表示的最大时间:time(23, 59, 59, 999999) |
time.min | time 类所能表示的最小时间:time(0, 0, 0, 0) |
time.resolution | 时间的最小单位,即两个不同时间的最小差值:1 微秒 |
对象方法和属性
对象方法 / 属性名称 | 描述 |
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) 功能相同 |
4.3 datetime 类
datetime 类的定义如下:
class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None)
year, month 和 day 是必须要传递的参数, tzinfo 可以是 None 或 tzinfo 子类的实例.
各参数的取值范围为:
参数名称 | 取值范围 |
year | [MINYEAR, MAXYEAR] |
month | [1, 12] |
day | [1, 指定年份的月份中的天数] |
hour | [0, 23] |
minute | [0, 59] |
second | [0, 59] |
microsecond | [0, 1000000] |
tzinfo | tzinfo 的子类对象,如 timezone 类的实例 |
如果一个参数超出了这些范围, 会引起 ValueError 异常.
类方法和属性:
类方法 / 属性名称 | 描述 |
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 对象 |
对象方法和属性:
对象方法 / 属性名称 | 描述 |
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) | 返回指定格式的时间字符串 |
上面是 date,time,datetime 三个类的方法和属性, 关于这三个类, 使用方法上基本与 time 模块差不多, 看方法名基本就一目了然, 实在忘记, 直接查表就好, 本文不在过多介绍.
4.4 timedelta 类
timedelta 可以方便实现日期 (date 实例, time 实例, datetime 实例) 之间的加减运算.
datetime.timedelta 类的定义
class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, hours=0, weeks=0)
所有参数都是默认参数, 因此都是可选参数. 参数的值可以是整数或浮点数, 也可以是正数或负数. 内部值存储 days,seconds 和 microseconds, 其他所有参数都将被转换成这 3 个单位:
1 毫秒转换为 1000 微秒
1 分钟转换为 60 秒
1 小时转换为 3600 秒
1 周转换为 7 天
然后对这 3 个值进行标准化, 使得它们的表示是唯一的:
- microseconds : [0, 999999]
- seconds : [0, 86399]
- days : [-999999999, 999999999]
类属性:
类属性名称 | 描述 |
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) |
5 总结
对于 Python 中时间, 日期模块的应用主要集中在 time 模块和 datetime 模块中, 其中涉及到的方法和属性有些多容易混淆, 可以以 time 模块为出发点, 只要理清 time 模块中 3 种时间格式之间的关系, 就容易记忆了.
参考资料:
https://blog.csdn.net/p9bl5bxp/article/details/54945920
来源: https://www.cnblogs.com/chenhuabin/p/10099766.html