Python 的 datetime 模块可以自定义日期的显示格式,而且还可以很方便地对日期进行算术运算,比如增减天数等操作。
datetime 模块定义了 datetime 数据类型,用于表示一个特定的时刻。
import datetime import logging import time logging.basicConfig(level=logging.DEBUG, format='%(levelname)s - %(message)s') ''' datetime 模块 @author Deniro Lee ''' dt = datetime.datetime(2020, 10, 21, 17, 32, 34) logging.info('%s-%s-%s %s:%s:%s', dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
运行结果:
INFO - 2020-10-21 17:32:34
1 转换 Unix 纪元时间戳
Unix 纪元时间戳可以通过 datetime.datetime.fromtimestamp() ,转换为 datetime 对象。 datetime 对象的日期和时间会根据本地时区自动转换。
dt = datetime.datetime.fromtimestamp(10000000) logging.info('from 10000000 -> %s', dt) dt = datetime.datetime.fromtimestamp(time.time()) logging.info('from now -> %s', dt)
运行结果:
INFO - from 10000000 -> 1970-04-27 01:46:40 INFO - from now -> 2020-01-19 10:23:14.695018
2 比较时间
datetime 对象可以用比较操作符进行时间比较。
new_year_2019 = datetime.datetime(2019, 1, 1, 0, 0, 0) new_year_2020 = datetime.datetime(2020, 1, 1, 0, 0, 0) logging.info('2019 > 2020 -> %s', new_year_2019 > new_year_2020) logging.info('2019 < 2020 -> %s', new_year_2019 < new_year_2020) logging.info('2019 != 2020 -> %s', new_year_2019 != new_year_2020)
运行结果:
INFO - 2019 > 2020 -> False INFO - 2019 < 2020 -> True INFO - 2019 != 2020 -> True
利用比较时间方法,我们可以实现一个计划任务,比如程序到某一时刻时,才开始执行业务逻辑。
dt = datetime.datetime(2020, 10, 21, 17, 32, 34) while datetime.datetime.now() < dt: time.sleep(1) logging.info('sleep ...')
运行结果:
INFO - sleep ... INFO - sleep ... INFO - sleep ...
这里利用了一个 while 循环,让程序直到某一个特定的时间到来之前,一直处于休眠状态。
3 timedelta 数据类型
datetime 模块还定义了 timedelta 数据类型,它表示的是一段时间。
delta = datetime.timedelta(days=12, hours=8, minutes=36, seconds=58) logging.info('delta.days -> %s,delta.seconds -> %s,delta.microseconds -> %s', delta.days, delta.seconds, delta.microseconds) logging.info('total_seconds -> %s', delta.total_seconds()) logging.info('delta -> %s', delta)
运行结果:
INFO - delta.days -> 12,delta.seconds -> 31018,delta.microseconds -> 0 INFO - total_seconds -> 1067818.0 INFO - delta -> 12 days, 8:36:58
使用 datetime.timedelta()函数来创建 timedelta 对象,它接受关键字参数 weeks、 days、 hours、 minutes、 seconds、 milliseconds 和 microseconds。注意: 这里没有 month 和 year 关键字参数,因为“月”和“年”可以通过其它关键字参数推算出来。
timedelta 对象拥有的总时间以天 、 秒 、 微秒来表示。这些值分别保存在 days 、 seconds和 microseconds 属性中 。total_seconds() 方法会返回以秒表示的时长。把一个 timedelta 对象传入 str() ,就会返回格式良好的 、 可供人阅读的字符串表示形式。
4 时间运算
可以使用算术运算符对 datetime 值进行运算。
dt = datetime.datetime(2020, 10, 21, 17, 32, 34) logging.info('current time -> %s', dt) days_30 = datetime.timedelta(days=30) logging.info('after 30 days -> %s', dt + days_30)
运行结果:
INFO - delta.days -> 12,delta.seconds -> 31018,delta.microseconds -> 0 INFO - total_seconds -> 1067818.0 INFO - delta -> 12 days, 8:36:58
利用+和-运算符,我们可以把 timedelta 对象与 datetime 对象或其他 timedelta 对象进行相加或相减。timedelta 对象还支持乘、除运算。
dt = datetime.datetime(2020, 10, 21, 17, 32, 34) days_150 = datetime.timedelta(days=30 * 5) logging.info('after 150 days -> %s', days_150) logging.info('dt-days_150 -> %s', dt - days_150) logging.info('dt-days_150 * 2 -> %s', dt - days_150 * 2)
运行结果:
INFO - after 150 days -> 150 days, 0:00:00 INFO - dt-days_150 -> 2020-05-24 17:32:34 INFO - dt-days_150 * 2 -> 2019-12-26 17:32:34
5 datetime 对象与字符串之间相互转换
利用 strftime() 方法,我们可以将 datetime 对象转换为更可读的字符串。 str ftime() 函数名中的 f 表示 format。
strftime() 方法支持以下格式化指令:
格式化指令 | 含义 |
---|---|
%Y | 带世纪的年份,例如’2020′ |
%y | 不带世纪的年份, ’00’至’99’(1970 至 2069) |
%m | 数字表示的月份, ’01’至’12’ |
%B | 完整的月份,例如’November’ |
%b | 简写的月份,例如’Nov’ |
%d | 一月中的第几天, ’01’至’31’ |
%j | 一年中的第几天, ‘001’至’366′ |
%w | 一周中的第几天, ‘0’(周日)至’6’(周六) |
%A | 完整的周几,例如’Monday’ |
%a | 简写的周几,例如’Mon’ |
%H | 小时(24 小时时钟), ’00’至’23’ |
%I | 小时(12 小时时钟), ’01’至’12’ |
%M | 分, ’00’至’59’ |
%S | 秒, ’00’至’59’ |
%p | ‘AM’或’PM’ |
%% | 转义出’%’字符 |
向 strftime() 方法传入一个自定义的格式字符串,其中包含格式化指令, strftime() 就会返回相应格式的字符串。
如果要将字符串转换成 datetime 对象,就是用反向操作方法 strptime(),它所支持的格式化指令与 strftime() 方法相同。
注意: strptime() 的第一个入参是带有日期信息的字符串,它必须准确匹配定制的格式字符串,否则 Python 会抛出 ValueError 异常。
# datetime 对象转换为字符串 dt = datetime.datetime(2020, 10, 21, 17, 32, 34) logging.info('format -> %s', dt.strftime('%Y-%m-%d %H:%M:%S')) logging.info('format -> %s', dt.strftime('%I:%M %p')) logging.info('format -> %s', dt.strftime('%B of %y, %A')) # 字符串转换为 datetime 对象 dt = datetime.datetime.strptime('2020-10-21 17:32:34', '%Y-%m-%d %H:%M:%S') logging.info('str to datetime -> %s(%s)', dt, type(dt))
运行结果:
INFO - format -> 2020-10-21 17:32:34 INFO - format -> 05:32 PM INFO - format -> October of 20, Wednesday INFO - str to datetime -> 2020-10-21 17:32:34(<class 'datetime.datetime'>)
总结如下:
(1)表示时间的 3 种不同类型对象
- Unix 纪元时间戳(time 模块)是一个浮点值或整型值,它表示自 1970 年1月1日午夜 0 点( UTC )以来的秒数。
- datetime 对象(datetime 模块)包含一些整型值,保存在 year、 month 、 day 、 hour 、 minute 和 second 等属性中。
- timedelta 对象(datetime 模块)表示的是一段时间,而不是一个特定的时刻。
(2)时间函数、参数及其返回值
- time.time() 函数返回一个浮点值,表示当前时刻的 Unix 纪元时间戳。
- time.sleep(second s)函数会让程序暂停指定的秒数 s。
- datetime.datetime (year, month , day , hour , minute , second ) 函数返回参数指定的时刻的 datetime 对象。如果没有提供 hour 、 minute 或 second 参数,则使用默认值 0 。
- datetime.datetime.now() 函数返回当前时刻的 datetime 对象。
- datetime.datetime.fromtimestamp( epoch ) 函数返回 epoch 时间戳参数表示的时刻,即Unix 纪元时间戳的 datetime 对象。
- datetime.timedelta(weeks, days, hours, minutes, seconds,milliseconds,microseconds)函数返回一个表示一段时间的 timedelta对象。该函数的关键字参数都是可选的,不包括 month 或year。
- total_ seconds()方法用于 timedelta对象,返回 timedelta对象表示的秒数。
- datetime.datetime.strftime ( format )方法返回一个字符串,用 format 字符串中的定制格式来表示datetime 对象表示的时间字符串。
- datetime.datetime.strptime ( time_string, format )函数返回一个datetime 对象,它的时刻由 time_string指定,利用 format 字符串参数来解析。