Python 的 datetime 模块

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 字符串参数来解析。

发表评论