IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Python知识库 -> 跟 “最烦用 Python 处理时间了” 说拜拜 -> 正文阅读

[Python知识库]跟 “最烦用 Python 处理时间了” 说拜拜

30734f0306bddc975e654d9eaa5641ae.png

文 |?李晓飞

来源:Python 技术「ID: pythonall」

eb6b5c529424d54fc212cee4c57a0931.png

人生苦短,我用 Python!,这句话是激励无数人,踏上了 Python 的伟大征程的座右铭。

但是,Python 中的时间处理,搞得我怀疑人生,总是弄不清该用 time 还是 datetime,什么时间戳、时间运算、各种格式的时间转化,概念多,操作复杂,bug 还得找半天,实在是太麻烦了,一遇到时间处理就焦虑~

今天给大家介绍一个处理时间的神器 —— Pendulum[1],跟过去说拜拜,让你用 Python 处理时间快步如飞,还等啥,来吧!

神器亮相

Python 中神器亮相的姿势都差不多,有种熟悉的味道:

pip?install?pendulum

顺利安装后,展示一下:

import?pendulum

d1?=?pendulum.yesterday()??#?昨天
#?2021-10-02T00:00:00+08:00

d2?=?pendulum.today()?#?今天
#?2021-10-03T00:00:00+08:00

d3?=?pendulum.tomorrow()?#?明天
#?2021-10-04T00:00:00+08:00

d2.diff(d1).in_days()?#?相差多少天
#?1

d2.diff(d1).in_hours()?#?相差多少小时
#?24

pendulum.now()?#?现在的时间

是不是感觉很有亲和力,各种操作都符合人性化。

而且将 datetime 和 time 两个库合并了,再也不用纠结应该用哪个了。

下面浏览一下 Pendulum 的更大威力吧。

搞定时区

时区处理是比较麻烦地事情,还好我们只使用一个时区,省去了很多麻烦。

不过时区的概念需要了解,再说,谁能说得准,不开发国际化程序呢。

一起困难,Pendulum 让我们优雅处之。

看例子:

import?pendulum

dt1?=?pendulum.datetime(2021,?10,?3)
print(dt2.timezone.name)?#?UTC

dt2?=?pendulum.datetime(2021,?10,?3,?tz="Asia/Shanghai")

print(dt2.timezone.name)?#?Asia/Shanghai
  • 不指定,就是默认的 UTC 0 时区

  • 创建时间对象时可以指定时区,例如我们的时区名称是 Asia/Shanghai

  • 通过 timezone.name 属性,可查看时间对象的具体时区,或者直接用 timezone_name 直接获取,另外,属性 timezone 可以简写成 tz

时区名称可在这里查:时区名称[2]
Pendulum 时区只支持用 时区名称 设置时区

时区运算

不同时区的时间可以用来比较、运算和转化,例如:

import?pendulum

first?=?pendulum.datetime(2012,?9,?5,?23,?26,?11,?0,?tz='America/Toronto')
second?=?pendulum.datetime(2012,?9,?5,?20,?26,?11,?0,?tz='America/Vancouver')

first.to_datetime_string()
#?2012-09-05?23:26:11

first.timezone_name
#?America/Toronto
second.to_datetime_string()
#?2012-09-05?20:26:11
second.timezone_name
#?America/Vancouver

first?==?second
#?True
first?!=?second
#?False
first?>?second
#?False
first?<?second
#?False

first?=?first.on(2012,?1,?1).at(0,?0,?0)
second?=?second.on(2012,?1,?1).at(0,?0,?0)
#?tz?is?still?America/Vancouver?for?second

first?==?second
#?False
first?!=?second
#?True
first?>?second
#?False
first?<?second
#?True

second.diff(first).in_hours()
#?3
  • 时区 America/TorontoAmerica/Vancouver 相差 3 小时

  • 设置相差 3 小时的时间,两者是相等的

  • 设置完全相同的时间,比较时是不相等的,计算它们之间的差异,可以看到相差 3 小时

  • diff 方法用于与另一个时间对象比较,in_hours 方法是时间区间的方法,可以将区间转化为小时,同理还有 in_daysin_years

时区切换

切换时区很方便,只要调用时间对象的 in_timezone 或者 缩写形式 in_tz 传入参数 时区名称 就可以了:

import?pendulum
in_perk?=?pendulum.now()
in_perk
#?DateTime(2021,?10,?4,?12,?10,?59,?986047,?tzinfo=Timezone('Asia/Shanghai'))

in_perk.in_timezone("America/New_York")
#?DateTime(2021,?10,?4,?0,?7,?50,?106336,?tzinfo=Timezone('America/New_York'))

时间运算

时间运算包括比较计算差异增减。上面例子中已经计算了不同时区的时间差异,下面我们详细的说一下。

比较

比较很简单,对两个时间对象做比较就可以了,支持 ==!=>>=<<=,比较的结果是 TrueFalse

计算差异

前面时区的例子里已经看到了,使用 diff 方法来计算差异,会返回一个时间区间(Period)对象

使用 diff 时,如果不提供比较参加,就会默认和当前时间比较。

import?pendulum

first?=?pendulum.datetime(2012,?1,?31,?0)
second?=?pendulum.datetime(2012,?2,?1,?0)
first.diff(second)
#?<Period?[2012-01-31T00:00:00+00:00?->?2012-02-01T00:00:00+00:00]>

first.diff()
#?<Period?[2012-01-31T00:00:00+00:00?->?2021-10-04T04:44:56.337989+00:00]>

对于时间区间(period)来说,处理前面提到的 in_days 等方法,将区间转化为一个单位的数量,还可以直接使用对应的属性,例如 daysyearsweeks 等,效果是一样的。

增减

如果要的时间增加或者减少某些时间,可以使用 addsubtract 方法:

import?pendulum

dt?=?pendulum.datetime(2012,?1,?31)

dt?=?dt.add(years=5)
#?'2017-01-31?00:00:00'
dt?=?dt.add(years=1)
#?'2018-01-31?00:00:00'
dt?=?dt.subtract(years=1)
#?'2017-01-31?00:00:00'
dt?=?dt.subtract(years=5)
#?'2012-01-31?00:00:00'

dt?=?dt.add(months=60)
#?'2017-01-31?00:00:00'
dt?=?dt.add(months=1)
#?'2017-02-28?00:00:00'
dt?=?dt.subtract(months=1)
#?'2017-01-28?00:00:00'
dt?=?dt.subtract(months=60)
#?'2012-01-28?00:00:00'

dt?=?dt.add(days=29)
#?'2012-02-26?00:00:00'
dt?=?dt.add(days=1)
#?'2012-02-27?00:00:00'
dt?=?dt.subtract(days=1)
#?'2012-02-26?00:00:00'
dt?=?dt.subtract(days=29)
#?'2012-01-28?00:00:00'

dt?=?dt.add(weeks=3)
#?'2012-02-18?00:00:00'
dt?=?dt.add(weeks=1)
#?'2012-02-25?00:00:00'
dt?=?dt.subtract(weeks=1)
#?'2012-02-18?00:00:00'
dt?=?dt.subtract(weeks=3)
#?'2012-01-28?00:00:00'

dt?=?dt.add(hours=24)
#?'2012-01-29?00:00:00'
dt?=?dt.add(hours=1)
#?'2012-02-25?01:00:00'
dt?=?dt.subtract(hours=1)
#?'2012-02-29?00:00:00'
dt?=?dt.subtract(hours=24)
#?'2012-01-28?00:00:00'

dt?=?dt.add(minutes=61)
#?'2012-01-28?01:01:00'
dt?=?dt.add(minutes=1)
#?'2012-01-28?01:02:00'
dt?=?dt.subtract(minutes=1)
#?'2012-01-28?01:01:00'
dt?=?dt.subtract(minutes=24)
#?'2012-01-28?00:00:00'

dt?=?dt.add(seconds=61)
#?'2012-01-28?00:01:01'
dt?=?dt.add(seconds=1)
#?'2012-01-28?00:01:02'
dt?=?dt.subtract(seconds=1)
#?'2012-01-28?00:01:01'
dt?=?dt.subtract(seconds=61)
#?'2012-01-28?00:00:00'

dt?=?dt.add(years=3,?months=2,?days=6,?hours=12,?minutes=31,?seconds=43)
#?'2015-04-03?12:31:43'
dt?=?dt.subtract(years=3,?months=2,?days=6,?hours=12,?minutes=31,?seconds=43)
#?'2012-01-28?00:00:00'
  • addsubtract 方法参数一致,支持 yearsmonthsweeks 等多种时间单位,而且可以一起设置

  • 时间单位参数可以支持负数,相当于 addsubtract 可以相互替换

  • 时间单位参数还支持小数,比如加上一天半可以写成 dt.add(days=1.5)

时间调整

时间调整很有用,之前我在约马程序 中,需要计算下一个周一,当时只能通过日期 API 摸,当时要是知道 Pendulum 就省事多了:

import?pendulum

dt?=?pendulum.datetime(2012,?1,?31,?12,?0,?0)

dt.start_of('day')
#?'2012-01-31?00:00:00'

dt.end_of('day')
#?'2012-01-31?23:59:59'

dt.start_of('month')
#?'2012-01-01?00:00:00'

dt.end_of('month')
#?'2012-01-31?23:59:59'

dt.start_of('year')
#?'2012-01-01?00:00:00'

dt.end_of('year')
#?'2012-12-31?23:59:59'

dt.start_of('decade')
#?'2010-01-01?00:00:00'

dt.end_of('decade')
#?'2019-12-31?23:59:59'

dt.start_of('century')
#?'2000-01-01?00:00:00'

dt.end_of('century')
#?'2099-12-31?23:59:59'

dt.start_of('week')
#?'2012-01-30?00:00:00'
dt.day_of_week?==?pendulum.MONDAY
#?True?#?ISO8601?week?starts?on?Monday

dt.end_of('week')
#?'2012-02-05?23:59:59'
dt.day_of_week?==?pendulum.SUNDAY
#?True?#?ISO8601?week?ends?on?SUNDAY

dt.next(pendulum.WEDNESDAY)
#?'2012-02-01?00:00:00'
dt.day_of_week?==?pendulum.WEDNESDAY
#?True

dt?=?pendulum.datetime(2012,?1,?1,?12,?0,?0)
dt.next()
#?'2012-01-08?00:00:00'
dt.next(keep_time=True)
#?'2012-01-08T12:00:00+00:00'

dt?=?pendulum.datetime(2012,?1,?31,?12,?0,?0)
dt.previous(pendulum.WEDNESDAY)
#?'2012-01-25?00:00:00'
dt.day_of_week?==?pendulum.WEDNESDAY
#?True

dt?=?pendulum.datetime(2012,?1,?1,?12,?0,?0)
dt.previous()
#?'2011-12-25?00:00:00'
dt.previous(keep_time=True)
#?'2011-12-25?12:00:00'

start?=?pendulum.datetime(2014,?1,?1)
end?=?pendulum.datetime(2014,?1,?30)
start.average(end)
#?'2014-01-15?12:00:00'

#?others?that?are?defined?that?are?similar
#?and?tha?accept?month,?quarter?and?year?units
#?first_of(),?last_of(),?nth_of()

是否看眼花了,我看到这里,兴奋地都要跳起来了,简直是只有没想到的,没有它没实现的呀!

  • start_of 方法用于计算某个起始时间,可以是 天、年、月、周,甚至可以是世纪。end_of 是类似的,用于计算结束

  • next 方法用于计算以一个星期,不加参数就是计算下个星期的今天,也可以指定计算下一个哪天,比如下个星期一:dt.next(pendulum.MONDAY)previous 是类似的,用于计算向前的天

  • average 方法用于计算两个时间的中间时间,简直太方便了

时间转字符串

时间对象是一个复杂的对象,对于我们来说不方便看和读,就需要将起转化为字符串,或者将字符串表示的时间转化为时间对象。

Pendulum 提供和很多方便的方式:

import?pendulum

dt?=?pendulum.datetime(1975,?12,?25,?14,?15,?16)
print(dt)
#?'1975-12-25T14:15:16+00:00'

dt.to_date_string()
#?'1975-12-25'

dt.to_formatted_date_string()
#?'Dec?25,?1975'

dt.to_time_string()
#?'14:15:16'

dt.to_datetime_string()
#?'1975-12-25?14:15:16'

dt.to_day_datetime_string()
'Thu,?Dec?25,?1975?2:15?PM'

#?You?can?also?use?the?format()?method
dt.format('dddd?Do?[of]?MMMM?YYYY?HH:mm:ss?A')
'Thursday?25th?of?December?1975?02:15:16?PM'

#?Of?course,?the?strftime?method?is?still?available
dt.strftime('%A?%-d%t?of?%B?%Y?%I:%M:%S?%p')
'Thursday?25th?of?December?1975?02:15:16?PM'
  • to_date_string 转化日期

  • to_datetime_string 转化日期和时间

  • to_time_string 转化时间

  • to_formatted_date_string 转化为英文书写形式

  • format 安装指定格式转化

  • strftimedatetime 的格式化方法

时间转化字符串,如何将字符串转化为时间类型呢?

使用 parse 方法就好了,看下例子:

import?pendulum

dt?=?pendulum.parse('1975-05-21T22:00:00')
print(dt)
#?'1975-05-21T22:00:00+00:00

#?You?can?pass?a?tz?keyword?to?specify?the?timezone
dt?=?pendulum.parse('1975-05-21T22:00:00',?tz='Europe/Paris')
print(dt)
#?'1975-05-21T22:00:00+01:00'

#?Not?ISO?8601?compliant?but?common
dt?=?pendulum.parse('1975-05-21?22:00:00')

dt?=?pendulum.parse('31-01-01',?strict=False)

dt?=?pendulum.parse('31/01/01',?strict=False)

dt?=?pendulum.parse('31/1/1',?strict=False)
  • 可以直接转化,也可以在转化时指定时区

  • 支持多种时间格式,如果不是标准的时间格式,需要添加参数 strict=False,这样 Pendulum 就会尽最大可能去猜

  • 更多的时间格式请参考 Pendulum Parsing 文档[3]

人性化

现在看到 Pendulum 的强大了吧,不过还有个令人叫绝的功能,就是人性化时间。

如果你注意搜索引擎的结果的话,就能看到,很多时间被表示为:1天前,2周后等等,如果让我们来实现,可得好好想想,如果需求说,搞个英文版的,我们可能有拿起键盘去砸的冲动。

现在好了,直接看例子:

import?pendulum

pendulum.now().subtract(days=1).diff_for_humans()
#?'1?day?ago'

pendulum.now().diff_for_humans(pendulum.now().subtract(years=1))
#?'1?year?after'

dt?=?pendulum.datetime(2011,?8,?1)
dt.diff_for_humans(dt.add(months=1))
#?'1?month?before'
dt.diff_for_humans(dt.subtract(months=1))
#?'1?month?after'

pendulum.now().add(seconds=5).diff_for_humans()
#?'5?seconds?from?now'

pendulum.now().subtract(days=24).diff_for_humans()
#?'3?weeks?ago'

pendulum.now().subtract(days=24).diff_for_humans(absolute=True)
#?'3?weeks'

pendulum.set_locale('zh')
pendulum.now().subtract(days=24).diff_for_humans()
#?'3周前'

pendulum.now().add(seconds=5).diff_for_humans()
#?'5秒钟后'

oneday?=?pendulum.now().diff(pendulum.now().add(days=1))
oneday.in_words()
#?'1天'
  • diff_for_humans 可以将时间区间直接输出成人性化时间

  • 参数 absolute 的作用是给出一个人性化的时间间隔,而不是相对于现在的说法

  • 默认情况下输出的是英语写法,如果要让说中文,通过 pendulum.set_locale('zh') 就可以了,厉害吧

  • 对于一个时间区域来说,可以用 in_words 来输出人性化时间

这里注意,对于 dt.diff_for_humans(dt.subtract(months=1)) 这样的,相对一个日期的时间差异人性化输出,不支持中文,会报错,所以建议先计算出两个日期的差异,再用 in_words 做人性化输出,如果有必要,在其后加上
希望这个 bug 能早日修复

总结

今天简单介绍了一下 Pendulum 库在时间上的优秀能力,除了这些它还有更多的功能可供发掘。只要多研究,多用,一定能解决你遇到时间处理的问题。

最好的学就是用,所以要不断地通过练习或者实践去用,期望通过这篇介绍,能让你在时间处理上更高效,比心!

参考资料

[1]

Pendulum 工具: https://pendulum.eustace.io/

[2]

时区名称: https://docs.aws.amazon.com/zh_cn/redshift/latest/dg/time-zone-names.html

[3]

Pendulum Parsing 文档: https://pendulum.eustace.io/docs/#parsing

PS:公号内回复「Python」即可进入Python 新手学习交流群,一起 100 天计划!

老规矩,兄弟们还记得么,右下角的 “在看” 点一下,如果感觉文章内容不错的话,记得分享朋友圈让更多的人知道!

a2a4c557d064085ea3860a20ec10ac99.gif

代码获取方式

识别文末二维码,回复:太阳雪

cf431017e0addd6ab16b4e71f36bd02c.png

  Python知识库 最新文章
Python中String模块
【Python】 14-CVS文件操作
python的panda库读写文件
使用Nordic的nrf52840实现蓝牙DFU过程
【Python学习记录】numpy数组用法整理
Python学习笔记
python字符串和列表
python如何从txt文件中解析出有效的数据
Python编程从入门到实践自学/3.1-3.2
python变量
上一篇文章      下一篇文章      查看所有文章
加:2021-10-12 23:23:18  更:2021-10-12 23:23:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 18:20:24-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码