python中时间处理标准库DateTime加强版库:pendulum

1|0DateTime 的时区问题


Python的datetime可以处理2种类型的时间,分别为offset-naiveoffset-aware。前者是指没有包含时区信息的时间,后者是指包含时区信息的时间,只有同类型的时间才能进行减法运算和比较。

datetime模块的函数在默认情况下都只生成offset-naive类型的datetime对象,例如now()、utcnow()、fromtimestamp()、utcfromtimestamp()和strftime()。

其中now()和fromtimestamp()可以接受一个tzinfo对象来生成offset-aware类型的datetime对象,但是标准库并不提供任何已实现的tzinfo类,只能自己实现。

一旦生成了一个offset-aware类型的datetime对象,我们就能调用它的astimezone()方法,生成其他时区的时间(会根据时差来计算)。

而如果拿到的是offset-naive类型的datetime对象,也是可以调用它的replace()方法来替换tzinfo的,只不过这种替换不会根据时差来调整其他时间属性。

因此,如果拿到一个格林威治时间的offset-naive类型的datetime对象,直接调用replace(tzinfo=UTC())即可转换成offset-aware类型,然后再调用astimezone()生成其他时区的datetime对象。

不带时区datetime实例
普通的datetime都是不带时区信息

>>> from datetime import datetime >>> datetime_now = datetime.now() >>> >>> datetime_now datetime.datetime(2021, 9, 15, 9, 34, 18, 600690)

带时区datetime实例

>>> import pytz >>> datetime_now = datetime.now(tz=pytz.utc) >>> >>> datetime_now datetime.datetime(2021, 9, 14, 3, 28, 31, 421979, tzinfo=<UTC>)

2|0pendulum


pendulum是对datetime的高级封装,主要是用的是带时区的datetime

>>> import pendulum >>> from datetime import datetime >>> >>> now = pendulum.now() >>> now DateTime(2021, 9, 14, 11, 36, 52, 473028, tzinfo=Timezone('Asia/Shanghai')) >>> >>> isinstance(now, datetime) True

3|0创建DateTime实例


pendulum是简化时间操作的模块。
特别注意确保正确处理时区,并基于底层tzinfo实现。例如,所有比较均以UTC或所用日期时间的时区进行。pendulum默认创建带时区的datetime,但时区并不是当地时区,而是标准时区UTC时区。

3|1创建


dt = pendulum.datetime(2015, 2, 5) >>> dt DateTime(2015, 2, 5, 0, 0, 0, tzinfo=Timezone('UTC'))

如果没有指明时分秒,那么就是00:00:00,并且时区是UTC。此外它也可以是Timezone实例或一个简单的时区字值

pendulum.datetime(2015, 2, 5, tz='Europe/Paris') tz = pendulum.timezone('Europe/Paris') pendulum.datetime(2015, 2, 5, tz=tz)

local
local 和 datetime()很类似,但是会自动设置时区为本地时区

dt = pendulum.local(2015, 2, 5) >>> dt DateTime(2015, 2, 5, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai'))

local 类似于
pendulum.datetime(2015, 2, 5, tz='local')

now
now 和 local一样,也会自动设置时区为本地时区

now = pendulum.now() >>> >>> now DateTime(2021, 9, 13, 22, 39, 53, 257567, tzinfo=Timezone('Asia/Shanghai'))

today
获取当天的起始时间,零时零点。带时区

>>> to =pendulum.today() >>> to DateTime(2021, 9, 13, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> >>> print(to) 2021-09-13T00:00:00+08:00

tommorrow
获取明天的起始时间,零时零点。带时区

>>> tomm = pendulum.tomorrow() >>> >>> tomm DateTime(2021, 9, 14, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> print(tomm) 2021-09-14T00:00:00+08:00

yesterday
获取昨天的起始时间,零时零点,带时区

>>> yes = pendulum.yesterday() >>> >>> yes DateTime(2021, 9, 12, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> print(yes) 2021-09-12T00:00:00+08:00

naive 不带时区实例
pendulum是强制使用时区的,使用它们是使用库的首选和推荐方式。但是如果你真的需要一个简单的DateTime对象,可以使用naive()

>>> naive = pendulum.naive(2015, 2, 5) >>> naive DateTime(2015, 2, 5, 0, 0, 0) >>> print(naive) 2015-02-05T00:00:00

3|2从字符串创建


form_format
form_format和原生的datetime.strptime()很类似,但使用自定义标记创建DateTime实例。

>>> dt = pendulum.from_format('1975-05-21 22', 'YYYY-MM-DD HH') >>> >>> dt DateTime(1975, 5, 21, 22, 0, 0, tzinfo=Timezone('UTC')) >>>

同样可以接受一个时区

>>> dt = pendulum.from_format('1975-05-21 22', 'YYYY-MM-DD HH', tz='Asia/Shanghai') >>> >>> dt DateTime(1975, 5, 21, 22, 0, 0, tzinfo=Timezone('Asia/Shanghai'))

form_timestamp
最后一个助手用于处理unix时间戳。from_timestamp()将创建一个与给定时间戳相等的DateTime实例,并设置时区或将其默认为UTC。

>>> dt = pendulum.from_timestamp(-1) >>> >>> dt DateTime(1969, 12, 31, 23, 59, 59, tzinfo=Timezone('UTC'))

instance:从DateTime创建
如果你发现你继承了一个datetime.datetime的实例,你可以创建一个DateTime实例通过instance方法

>>> dt = datetime(2008, 1, 1) >>> p = pendulum.instance(dt) >>> print(p) DateTime(2008, 1, 1, 0, 0, 0, tzinfo=Timezone('UTC'))

parse
pendulum.parse() 可以将字符串转peewee对象,默认不设置本地时区,可通过tz手动添加时区。字符串格式支持:

  • RFC 3339 format
  • ISO 8601 formats
>>> dt = pendulum.parse('1975-05-21T22:00:00') >>> print(dt) '1975-05-21T22:00:00+00:00

4|0pendulum 对象的属性和方法


pendulum 对象有十分庞大的属性和方法

4|1输出当前时刻的年月日,时分秒


>>> dt.year 2021 >>> dt.month 9 >>> dt.day 14 >>> dt.hour 15 >>> dt.minute 24 >>> dt.second 15 >>> dt.microsecond 928205 >>>

4|2输出当前时刻是一年中的第几周,第几天,第几个月


>>> dt.day_of_week 2 >>> dt.day_of_year 257 >>> dt.week_of_month 3 >>> dt.week_of_year 37 >>> >>> dt.days_in_month 30 >>>

4|3输出对象的时区相关,时区名字,时区类型本地时区或标准时区


>>> dt.timezone Timezone('Asia/Shanghai') >>> >>> dt.is_local() True >>> dt.is_utc() False

4|4date和time属性


date通常是指年月日的时间
time通常是指时分秒的时间
pendulum属性中可以输出date和time

date

>>> date_obj = now.date() >>> date_obj Date(2021, 9, 14) >>> >>> print(date_obj) 2021-09-14 >>> >>> type(date_obj) <class 'pendulum.date.Date'>

time

>>> time_ojb = now.time() >>> time_obj Time(19, 27, 53, 49291) >>> >>> print(time_obj) 19:27:53.049291 >>> >>> type(time_obj) <class 'pendulum.time.Time'>

date,time都不是datetime类型的。所以在一些时间加减运算,比较等操作是date和time都不可以和pendulum直接运算。

>>> now DateTime(2021, 9, 14, 19, 27, 53, 49291, tzinfo=Timezone('Asia/Shanghai')) >>> >>> isinstance(now, datetime) True >>> isinstance(date_obj, datetime) False >>> >>> isinstance(time_obj, datetime) False >>>

date,time,datetime之间无法比较计算

>>> date_obj - time_obj Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for -: 'Date' and 'Time' >>> >>> now - date_obj Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for -: 'DateTime' and 'Date' >>> >>> now - time_obj Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for -: 'DateTime' and 'Time' >>>

5|0字符串输出格式


pendulum实例的输出格式,字符串的输出格式相关函数。

5|1date,time,datetime 相关字符串格式的输出


>>> dt = pendulum.now() >>> >>> dt.to_date_string() '2021-09-14' >>> >>> dt.to_time_string() '15:57:47' >>> >>> dt.to_datetime_string() '2021-09-14 15:57:47' >>>

5|2自定义输出格式


>>> dt.format('dddd Do [of] MMMM YYYY HH:mm:ss A') 'Tuesday 14th of September 2021 15:57:47 PM' >>> >>> dt.strftime('%A %-d%t of %B %Y %I:%M:%S %p') 'Tuesday 14\t of September 2021 03:57:47 PM' >>>

format 比 strftime 使用更加直观,而且支持更多参数

>>> dt.format('YYYY-MM-DD HH:mm:ss') '2021-09-14 15:57:47'

可以使用的参数:

- TOKEN OUTPUT
YEAR YYYY 2000, 2001, 2002 ... 2012, 2013
YY 00, 01, 02 ... 12, 13
Y 2000, 2001, 2002 ... 2012, 2013
QUARTER Q 1 2 3 4
Qo 1st 2nd 3rd 4th
MONTH MMMM January, February, March ...
MMM Jan, Feb, Mar ...
MM 01, 02, 03 ... 11, 12
M 1, 2, 3 ... 11, 12
Mo 1st 2nd ... 11th 12th
DAY OF YEAR DDDD 001, 002, 003 ... 364, 365
DDD 1, 2, 3 ... 4, 5
DAY OF MONTH DD 01, 02, 03 ... 30, 31
D 1, 2, 3 ... 30, 31
Do 1st, 2nd, 3rd ... 30th, 31st
DAY OF WEEK dddd Monday, Tuesday, Wednesday ...
ddd Mon, Tue, Wed ...
dd Mo, Tu, We ...
d 0, 1, 2 ... 6
DAYS OF ISO WEEK E 1, 2, 3 ... 7
HOUR HH 00, 01, 02 ... 23, 24
H 0, 1, 2 ... 23, 24
hh 01, 02, 03 ... 11, 12
h 1, 2, 3 ... 11, 12
MINUTE mm 00, 01, 02 ... 58, 59
m 0, 1, 2 ... 58, 59
SECOND ss 00, 01, 02 ... 58, 59
s 0, 1, 2 ... 58, 59

转义字符

要转义格式字符串中的字符,可以将字符括在方括号中。

>>> import pendulum >>> dt = pendulum.now() >>> dt.format('[today] dddd') 'today Sunday'

6|0时间比较


pendulum的时间可以直接比较。但是只能限制在相同对象之间。如datetime和datetime之间可以比较,datetime和date无法比较,带时区对象和不带时区对象无法比较。

6|1pendulum对象之间比较


>>> one = pendulum.now() >>> >>> two = pendulum.now() >>> >>> >>> one > two False >>> >>> three = pendulum.datetime(2021,9,10) >>> >>> one > three

6|2datetime 和 date之间无法比较


>>> three = pendulum.datetime(2021,9,10).date() >>> >>> >>> three Date(2021, 9, 10) >>> >>> one > three Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can't compare DateTime to Date

6|3带时区和不带时区不可以比较


>>> now = pendulum.now() >>> datetime_demo = datetime(2021,9,12) >>> >>> now - datetime_demo Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/root/.virtualenvs/python3.8/lib/python3.8/site-packages/pendulum/datetime.py", line 1417, in __sub__ return other.diff(self, False) File "/root/.virtualenvs/python3.8/lib/python3.8/site-packages/pendulum/datetime.py", line 794, in diff return Period(self, dt, absolute=abs) File "/root/.virtualenvs/python3.8/lib/python3.8/site-packages/pendulum/period.py", line 33, in __new__ raise TypeError("can't compare offset-naive and offset-aware datetimes") TypeError: can't compare offset-naive and offset-aware datetimes

7|0时间加减运算


有一些需要对时间操作的场景,比如定时4个小时执行一段代码,这是需要对时间加减运算。时间加减返回DateTime实例,不会造成时区变化。加减运算仅限于同一种类型的时间。

方法:

  1. add 加法
  2. subtract 减法

pendulum支持的加减的时间颗粒度:

  1. years
  2. months
  3. days
  4. hours
  5. minutes
  6. seconds

同时也支持多个参数

>>> dt = pendulum.now() >>> >>> >>> dt.add(years=1) DateTime(2022, 9, 14, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.subtract(years=1) DateTime(2020, 9, 14, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> >>> dt.add(months=2) DateTime(2021, 11, 14, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> dt.subtract(months=2) DateTime(2021, 7, 14, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> >>> dt.add(days=3) DateTime(2021, 9, 17, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> dt.subtract(days=3) DateTime(2021, 9, 11, 16, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> >>> dt.add(hours=4) DateTime(2021, 9, 14, 20, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>> dt.subtract(hours=4) DateTime(2021, 9, 14, 12, 16, 42, 375986, tzinfo=Timezone('Asia/Shanghai')) >>>

8|0时间间距计算


8|1diff


diff 方法来计算两个时间之间的间距。但是时间间距计算只限于同一种类型,带时区和不带时区时间无法计算。

diff()方法返回一个Period实例,它表示两个DateTime实例之间的时间,这个间隔可以用不同的单位表示。

diff方法有两个参数,第一个参数是DateTime,第二个是可选参数,表示时间差距是否以相对值返回。默认情况下差距是绝对差距,即没有正负。默认是True,相对为False

绝对值

>>> one = pendulum.now() >>> two = pendulum.datetime(2021,9,12) >>> >>> one.diff(two) <Period [2021-09-12T00:00:00+00:00 -> 2021-09-14T17:10:53.346499+08:00]> >>> >>> one.diff(two).in_hours() 57 >>> two.diff(one).in_hours() 57

相对值

>>> one.diff(two, False).in_hours() -57 >>> >>> two.diff(one, False).in_hours() 57

差值可以转换的时间颗粒度

  1. 天 in_days()
  2. 小时 in_hours()
  3. 分钟 in_minutes()

8|2时间间隔对象 period 属性和方法


当您从另一个DateTime实例中减去一个DateTime实例,或者使用diff()方法时,它将返回一个Period实例,可以叫做:时间间隔对象。
Period 继承了Duration类,还增加了一个好处,即它知道生成它的实例,因此它可以访问更多的方法和属性。Duration类继承自本机timedelta类。它对基类有很多改进。

>>> now = pendulum.now() >>> >>> past = pendulum.datetime(2021,9,10) >>> >>> (now - past).days 4 >>> >>> (past-now).days -4 >>>

period实例拥有的属性和方法:

as_interval as_timedelta days end hours in_days in_hours in_minutes in_months in_seconds in_weeks in_words in_years invert max microseconds min minutes months range remaining_days remaining_seconds resolution seconds start total_days total_hours total_minutes total_seconds total_weeks weeks years

从period中输出时间间隔的方法:

  1. 年:years
  2. 星期:weeks
  3. 月:months
  4. 天:days
  5. 小时:hours
  6. 分钟:minutes

8|3时间间隔 period 实例


可以创建一个持续周期实例,来完成一些转换。

>>> it = pendulum.duration(years=2, months=3) >>> it.days 820 >>> it.total_seconds() 70848000.0 >>>

如果你想获得每个支持单元的持续时间,你可以使用适当的方法。将所有的时间以周,天,小时的时间来计算。

>>> one DateTime(2021, 9, 12, 0, 0, 0, tzinfo=Timezone('UTC')) >>> two DateTime(2021, 9, 23, 0, 0, 0, tzinfo=Timezone('UTC')) >>> t = two - one >>> >>> t.total_weeks() 1.5714285714285714 >>> >>> t.total_days() 11.0 >>> t.total_hours() 264.0 >>> t.total_minutes() 15840.0

9|0pendulum常用方法


9|1获取时区的方法


>>> now =pendulum.now() >>> pendulum.now() DateTime(2021, 9, 13, 22, 47, 28, 47882, tzinfo=Timezone('Asia/Shanghai')) >>> now DateTime(2021, 9, 13, 22, 47, 27, 873328, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> now.timezone.name 'Asia/Shanghai'

9|2转换时区


可以使用in_timezone()方法轻松更改DateTime实例的时区。

v>>> now = pendulum.datetime(2021,9,15) >>> >>> now DateTime(2021, 9, 15, 0, 0, 0, tzinfo=Timezone('UTC')) >>> >>> now.in_timezone('Asia/Shanghai') DateTime(2021, 9, 15, 8, 0, 0, tzinfo=Timezone('Asia/Shanghai'))

注意:需要避免在python3.6之前使用时区库

9|3period实例的创建


可以通过period()来创建一个实例。

>>> one DateTime(2021, 9, 14, 17, 10, 53, 346499, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> past DateTime(2021, 9, 10, 0, 0, 0, tzinfo=Timezone('UTC')) >>> >>> period = pendulum.period(one, past) >>> v>>> period <Period [2021-09-14T17:10:53.346499+08:00 -> 2021-09-10T00:00:00+00:00]>

9|4起始日期


pendulum提供了起始日期的获取方法

开始时间
获取一个时间的开始时间,可以为:year,month,day,week

>>> dt = pendulum.now() >>> >>> dt.start_of('year') DateTime(2021, 1, 1, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.start_of('month') DateTime(2021, 9, 1, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.start_of('day') DateTime(2021, 9, 14, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.start_of('week') DateTime(2021, 9, 13, 0, 0, 0, tzinfo=Timezone('Asia/Shanghai'))

截止日期
获取一个时间的截止日期,可以为year,month,day,week

>>> dt.end_of('year') DateTime(2021, 12, 31, 23, 59, 59, 999999, tzinfo=Timezone('Asia/Shanghai')) >>> dt.end_of('month') DateTime(2021, 9, 30, 23, 59, 59, 999999, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.end_of('day') DateTime(2021, 9, 14, 23, 59, 59, 999999, tzinfo=Timezone('Asia/Shanghai')) >>> >>> dt.end_of('week') DateTime(2021, 9, 19, 23, 59, 59, 999999, tzinfo=Timezone('Asia/Shanghai'))

9|5迭代时间范围


如果希望在一个周期内进行迭代,可以使用range()方法。使用period对象的range方法,可以产生一个以参数为粒度的可迭代时间对象。

>>> one DateTime(2021, 9, 14, 17, 10, 53, 346499, tzinfo=Timezone('Asia/Shanghai')) >>> >>> >>> past DateTime(2021, 9, 10, 0, 0, 0, tzinfo=Timezone('UTC')) >>> >>> period = pendulum.period(one, past) >>> >>> for i in period.range('months'): ... print(i) ... 2021-09-14T17:10:53.346499+08:00 >>> >>> for i in period.range('days'): ... print(i) ... 2021-09-14T17:10:53.346499+08:00 2021-09-13T17:10:53.346499+08:00 2021-09-12T17:10:53.346499+08:00 2021-09-11T17:10:53.346499+08:00 2021-09-10T17:10:53.346499+08:00 >>> for i in period.range('hours'): ... print(i) ... 2021-09-14T17:10:53.346499+08:00 2021-09-14T16:10:53.346499+08:00 2021-09-14T15:10:53.346499+08:00 2021-09-14T14:10:53.346499+08:00 2021-09-14T13:10:53.346499+08:00 .....

9|6修改时间


pendulum提供一些帮助,通过对旧实例修改,返回一个新的实例。
但是,除了显式设置时区外,这些帮助程序都不会更改实例的时区。具体而言,设置时间戳不会将相应的时区设置为UTC。

>>> dt = pendulum.now() >>> dt.set(year=1975, month=5, day=21).to_datetime_string() '1975-05-21 15:24:15'

in_timezone() in_tz()可以将时间转化到设置的时区。

>>> dt = pendulum.now() >>> >>> dt DateTime(2021, 9, 14, 15, 50, 9, 590527, tzinfo=Timezone('Asia/Shanghai')) >>> dt.in_timezone('Europe/London') DateTime(2021, 9, 14, 8, 50, 9, 590527, tzinfo=Timezone('Europe/London')) >>>

__EOF__

本文作者goldsunshine
本文链接https://www.cnblogs.com/goldsunshine/p/15292216.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   金色旭光  阅读(2385)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示