最近发现个 Python 时间库 arrow,相比 time、datetime 等标准库,arrow 提供了更合理和人性化的方法来创建、操作、格式化和转换日期、时间和时间戳。
话说之前有个需求:把一组非标准格式的日期加时间字符串,如 2020年12月20日 22点7分5秒,转换为 YYYY-MM-DD HH:mm:ss 即 2020-12-20 22:07:05 这样的标准格式。
通常会想到用 time 或 datetime 库来格式化,比如:
# 用 time 模块
import time
# 先转为 struct_time
a = time.strptime("2020年12月20日 22点7分5秒", "%Y年%m月%d日 %H点%M分%S秒")
fmt = "%Y年%m月%d日 %H点%M分%S秒"
# 转为所需格式,输出 '2020-12-20 22:07:05'
time.strftime(fmt, a)
# 或者用 datetime 模块,看似简洁一点
from datetime import datetime
fmt = "%Y年%m月%d日 %H点%M分%S秒"
# 同样输出 '2020-12-20 22:07:05'
str(datetime.strptime("2020年12月20日 22点7分5秒", fmt))
问题解决了,可事情往往没这么简单:又来了几批数据,时间格式是这样的:2020/12/20 22:07、12/22 2020 22:07:05、二零二零年十二月二十二日 等等,总之它们的样子各不相同,可能没有秒钟精度,或者年月日顺序不同。
当然,可根据来源添加 if...else,分别设置不同的 fmt 后转换,但这肯定不是 Pythonic:不优雅。
现在祭出 arrow,这里用到它的一个特性:可使用正则表达式来格式化日期,避免碰到包含各种不规则符号分割的日期时间字符串,而且,fmt 还可以是一个正则表达式的列表,代码:
import arrow
# 列表里是可能碰到的各种日期时间格式
fmt = [
r'YYYY[\S*]MM[\S*]DD[\S*] HH[\S*]mm[\S*]ss[\S*]',
r'MM[\S*]DD[\S*] YYYY HH[\S*]mm[\S*]ss[\S*]',
r'YYYY[\S*]MM[\S*]DD[\S*] HH[\S*]m[\S*]s[\S*]',
]
my_date = [
'2020年12月20日 22点7分5秒',
'20201220 220705',
'2020/12-20 22:07:05',
'12/20 2020 22:07:05',
]
# 以下输出的结果均为 2020-12-20 22:07:05
for i in my_date:
# get()方法用于解析时间,format()来格式化
arrow.get(i, fmt).format('YYYY-MM-DD HH:mm:ss')
不过要注意,这里的正则表达式支持并不完整,但已经够用了。
上面仅仅是 arrow 模块一个很小的功能,它的强大远不止如此。
根据官方文档描述:
Arrow 是一个提供了更加合理和人性化的方法来创建、操作、格式化和转换日期、时间和时间戳的 Python 库。它实现了并更新 datetime 类型,弥补了其缺少的功能,另外提供一个API,用来支持许多常见的创建场景智能模块。简单地说,它能帮助你用更少的导入模块和代码来使用日期和时间。
Arrow 的命名来自物理学中的“时间箭头Arrow of time”,一定程度上受到 moment.js 和 requests 两个库的启发。
为啥要用 Arrow 来代替 Python 内置的时间模块?
Python 标准库和其他一些低层次的模块已经几乎完成了日期、时间和时区相关的所有功能,但它们的可用性不太好:
- 模块太多:datetime, time, calendar, dateutil, pytz 等
- 类型太多: date, time, datetime, tzinfo, timedelta, relativedelta 等
- 涉及时区和时间戳的转换太过繁琐,令人不爽。
- 时区问题太弱智
- ISO 8601 解析、时间间隔、人性化等相关函数功能不完善。
Arrow 的特性:
- 可以完全代替 datetime
- 支持 Python 2.7 到 3.9,持续更新中
- 默认使用 UTC 时区
- 在很多场景下使用起来超级简单
- 转换格式时支持相对偏移,包括周
- 自动格式和解析字符串
- 对 ISO 8601 的广泛支持
- 时区转换
- 时间戳可以作为属性
- .......
安装:
pip install -U arrow
用法示例:
import arrow
# 获取当前UTC格式时间
>>> utc = arrow.utcnow()
>>> utc
<Arrow [2013-05-11T21:23:58.970460+00:00]>
# 时间偏移
>>> utc = utc.shift(hours=-1)
>>> utc
<Arrow [2013-05-11T20:23:58.970460+00:00]>
# 根据时区获取当前时间
>>> local = utc.to('US/Pacific')
>>> local
<Arrow [2013-05-11T13:23:58.970460-07:00]>
# 转换为时间戳
>>> local.timestamp
1368303838
# 格式化,默认为 YYYY-MM-DD HH:mm:ss ZZ
>>> local.format()
'2013-05-11 13:23:58 -07:00'
# 按指定格式来格式化
>>> local.format('YYYY-MM-DD HH:mm:ss ZZ')
'2013-05-11 13:23:58 -07:00'
# 适用于人类阅读的时间格式,默认为英文
>>> local.humanize()
'an hour ago'
# 可指定语言,支持中文
>>> local.humanize(locale='zh_cn')
'4分钟前'
更多用法可参看 arrow 库的文档。
参考资料:
谢谢分享
学习到了,模块确实不错