当前位置: 首页 > backend >正文

Pendulum:优雅处理 Python 中的日期与时间

在日常开发中,日期和时间的处理一直是让人头疼的事情。虽然 Python 内置的 datetime 模块功能强大,但使用起来冗长、容易出错,对时区支持也不够友好。而 pendulum 正是为了解决这些痛点而生的现代化日期时间库。

本文将全面介绍 pendulum 的特点、用法以及典型应用场景,并与 datetime 模块进行对比,帮助你在实际项目中优雅地处理时间逻辑。


一、为什么选择 Pendulum?

在你接触 pendulum 之前,可能已经习惯于这样写代码:

from datetime import datetime, timedelta, timezonenow = datetime.now()
later = now + timedelta(days=3)

然而,如果你需要处理时区转换、自然语言式时间表达、日期范围、持续时间等需求时,datetime 的语法就显得冗长而繁琐。

而使用 pendulum,代码变成这样:

import pendulumnow = pendulum.now("Asia/Shanghai")
later = now.add(days=3)

是不是清晰不少?


二、安装 Pendulum

Pendulum 可以通过 pip 快速安装:

pip install pendulum

安装完成后,导入方式非常简单:

import pendulum

三、核心功能与语法解析

3.1 获取当前时间

pendulum.now()                         # 使用本地时区
pendulum.now("UTC")                   # 使用指定时区
pendulum.today("Asia/Shanghai")       # 获取今天0点
pendulum.yesterday("Asia/Shanghai")   # 获取昨天
pendulum.tomorrow("Asia/Shanghai")    # 获取明天

3.2 创建时间对象

dt = pendulum.datetime(2025, 6, 4, 15, 30, tz="Asia/Shanghai")

相比原生 datetime.datetimependulum.datetime 支持直接指定时区字符串,无需手动构造 timezone 对象。

还可以通过 from_format 快速解析:

dt = pendulum.from_format("2025-06-04 15:30", "YYYY-MM-DD HH:mm", tz="Asia/Shanghai")

3.3 自然语言解析时间

pendulum.parse("2025-06-04T15:30:00+08:00")
pendulum.parse("2025-06-04 15:30:00", tz="Asia/Shanghai")

3.4 时间加减(Duration)

now = pendulum.now()
three_days_later = now.add(days=3)
one_week_ago = now.subtract(weeks=1)

甚至可以链式调用:

now.add(days=1).subtract(hours=2)

3.5 时间比较

dt1 = pendulum.datetime(2025, 6, 1)
dt2 = pendulum.datetime(2025, 6, 4)print(dt1 < dt2)               # True
print(dt1.diff(dt2).in_days())  # 3

支持 .is_before().is_after().is_same_day() 等方法。

3.6 时区处理

dt = pendulum.datetime(2025, 6, 4, 15, 30, tz="UTC")
local_dt = dt.in_timezone("Asia/Shanghai")

还可以轻松获取所有时区:

pendulum.timezones  # 返回所有支持的时区列表

3.7 格式化与字符串转换

now = pendulum.now()
print(now.to_datetime_string())       # "2025-06-04 15:30:00"
print(now.format("YYYY-MM-DD HH:mm"))  # "2025-06-04 15:30"

支持使用 moment.js 的格式化语法,非常自然。

3.8 持续时间(Durations)

duration = pendulum.duration(days=2, hours=5, minutes=30)
print(duration.total_minutes())  # 2*24*60 + 5*60 + 30 = 3090

你也可以对时间进行差值计算:

start = pendulum.datetime(2025, 6, 1)
end = pendulum.datetime(2025, 6, 4)
diff = end - start
print(diff.in_days())  # 3

四、日期区间与范围处理

处理时间段是数据分析、报表等任务的常见需求。pendulum 提供 periodintervals 工具:

start = pendulum.datetime(2025, 6, 1)
end = pendulum.datetime(2025, 6, 10)
period = pendulum.period(start, end)for dt in period.range("days"):print(dt.to_date_string())

还可以使用:

period.days         # 获取所有日期组成的列表
period.includes(pendulum.datetime(2025, 6, 4))  # 判断某个时间是否在范围内

五、与 datetime 的兼容性

pendulumdatetime 的完全替代品,它继承了 datetime.datetime,并向下兼容所有用法。

from datetime import datetime
import pendulumdt = pendulum.now()
isinstance(dt, datetime)  # True

这意味着你可以在现有项目中逐步替换 datetimependulum,无需大改动。


六、典型应用场景

6.1 多时区日程应用

event_time = pendulum.parse("2025-06-04 18:00", tz="America/New_York")
user_time = event_time.in_timezone("Asia/Shanghai")
print(user_time.format("YYYY-MM-DD HH:mm"))

6.2 自动任务触发器

now = pendulum.now()
if now.is_weekday() and now.hour == 9:print("开始执行每日工作任务")

6.3 数据报表日期范围

start = pendulum.today().subtract(days=6)
end = pendulum.today()for day in pendulum.period(start, end).range("days"):print(f"处理报表:{day.to_date_string()}")

6.4 人类可读的时间间隔(humanize)

dt = pendulum.now().subtract(days=2, hours=3)
print(dt.diff_for_humans())  # “2 days ago”

支持中英文,适合用于日志、用户提示信息等。


七、与其他时间库对比

特性datetimearrowpendulum
原生支持时区✅(强)
人性化输出✅(更好)
日期范围处理
国际化支持✅(多语言)
与原生兼容性
安装包体积

pendulum 结合了 arrow 的易用性和 datetime 的兼容性,是目前处理时间的最佳选择之一。


八、总结

pendulum 是一个现代化、直观且功能丰富的 Python 时间处理库。无论你是开发金融系统、定时任务调度、日志系统,还是需要处理复杂的时间逻辑,pendulum 都能大大简化你的代码。

推荐理由总结:

  • ✅ API 更加直观
  • ✅ 对时区支持优秀
  • ✅ 支持日期范围
  • ✅ 高度兼容 datetime
  • ✅ 支持人类可读输出
  • ✅ 性能优于 arrow

如果你还在用 datetime 并苦于写一堆格式转换、手动处理时区和计算间隔,不妨从下一个项目开始试试 pendulum,相信你会爱上它。


参考链接

  • 官方文档:https://pendulum.eustace.io/
  • GitHub 项目:https://github.com/sdispater/pendulum

http://www.xdnf.cn/news/12058.html

相关文章:

  • vue3动态插入iframe,内容被取消的原因
  • pack 布局管理器
  • 第十三节:第三部分:集合框架:Map集合的遍历方式
  • 数码相片冲印规格参考表
  • Docker load 后镜像名称为空问题的解决方案
  • 国芯思辰ADE芯片成功替代ADS1296R,除颤仪核心部件实现自主可控
  • git删除本地分支和远程分支
  • 非对称加密
  • MuLogin浏览器如何使用Loongproxy?
  • 【AI系列】DPO 与 PPO 的比较与分析
  • 民锋视角下的资金流效率与账户行为建模
  • 解决fastadmin、uniapp打包上线H5项目路由冲突问题
  • Netty内存池之内存分配算法
  • 字符串接龙
  • Java 大视界 — Java 大数据在智能安防视频监控中的异常事件快速响应与处理机制
  • 未来的AI 终端
  • 系统性学习C语言-第十四讲-深入理解指针(4)
  • 《仿盒马》app开发技术分享-- 商品搜索页(顶部搜索bar热门搜索)(端云一体)
  • 中级统计师-经济学基础知识-第一章 经济学基础
  • android与Qt类比
  • 重要通知:6月申报纳税期限延至6月16日(附2025年办税日历 图文版)
  • 树莓派超全系列教程文档--(53)如何使用 SCP 共享文件
  • 嵌入式开发之STM32学习笔记day18
  • 手写Promise实例方法finally
  • 肺癌靶向治疗耐药困境下的新探索
  • LLM应用开发(九)- 幻觉及如何缓解
  • Authentication failed(切换了新的远程仓库tld)
  • 区块链技术发展现状与应用前景分析
  • Rocket客户端消息确认机制
  • JAVA:String类详解