Skip to content

ariebovenberg / **whenever ** Public

⏰ 现代 Python 日期时间库 whenever.rtfd.io

License

MIT license 1.4k stars 17 forks Branches Tags Activity Star Notifications You must be signed in to change notification settings

Additional navigation options

ariebovenberg/whenever

main BranchesTags Go to file Code

Folders and files

Name| Name| Last commit message| Last commit date ---|---|---|---

Latest commit

History

260 Commits .cargo| .cargo .github| .github benchmarks| benchmarks docs| docs pysrc/whenever| pysrc/whenever requirements| requirements src| src tests| tests typesafety| typesafety .coveragerc| .coveragerc .flake8| .flake8 .gitignore| .gitignore .readthedocs.yml| .readthedocs.yml CHANGELOG.rst| CHANGELOG.rst CONTRIBUTING.md| CONTRIBUTING.md Cargo.lock| Cargo.lock Cargo.toml| Cargo.toml LICENSE| LICENSE MANIFEST.in| MANIFEST.in Makefile| Makefile README.md| README.md build.rs| build.rs generate_docstrings.py| generate_docstrings.py pyproject.toml| pyproject.toml pytest.ini| pytest.ini setup.py| setup.py View all files

Repository files navigation

⏰ Whenever

为 Python 提供类型安全和 DST 安全的日期时间,可以使用 Rust 实现或者纯 Python 实现。

你是否每次使用 Python 的 datetime 库时都祈祷自己没有混淆 naive 和 aware 的日期时间?或者希望自己避开了它的其他陷阱? 没有什么办法能确定...

✨ 现在不一样了! ✨

Whenever 帮助你编写正确类型检查的日期时间代码,它使用了其他语言现代库成熟的概念。它也比其他第三方库快得多 —— 通常也比标准库快。如果性能不是你的首要任务,还可以使用纯 Python 版本。

显示基准测试结果的条形图。

RFC3339 解析、标准化、与当前时间比较、偏移和更改时区 (100 万次)

📖 文档 | 🐍 PyPI | 🐙 GitHub | 🚀 Changelog | ❓ FAQ | 🗺️ Roadmap | 💬 Issues & feedback

⚠️ 注意:1.0 版本即将发布。在此之前,API 可能会随着我们收集反馈和改进库而发生变化。如果你想了解这个项目的发展,请在 GitHub 上留下一个 ⭐️!

为什么不使用标准库?

经过 20 多年,Python 的 datetime 库已经与你对现代日期时间库的期望不一致了。 有两点比较突出:

  1. 它并不总是考虑夏令时 (DST)。 这是一个简单的例子:
bedtime = datetime(2023, 3, 25, 22, tzinfo=ZoneInfo("Europe/Paris"))
full_rest = bedtime + timedelta(hours=8)
# 它返回 6am,但应该是 7am——因为由于 DST 我们跳过了一个小时!

请注意,这不是一个错误,而是一个设计上的决定,即只有当计算涉及_两个_时区时,才会考虑 DST。 如果你觉得这很奇怪,你不是 孤单的

  1. 类型系统无法区分 naive 和 aware 的日期时间。 你的代码可能只使用其中一种,但没有办法在类型系统中强制执行这一点!
# 这期望的是 naive 还是 aware? 无法分辨!
def schedule_meeting(at: datetime) -> None: ...

为什么不使用其他库?

还有两个流行的第三方库,但它们并没有(完全)解决这些问题。 以下是它们与 Whenever 和标准库的比较:

Whenever | datetime | Arrow | Pendulum ---|---|---|--- DST-safe | ✅ | ❌ | ❌ | ⚠️ Typed aware/naive | ✅ | ❌ | ❌ | ❌ Fast | ✅ | ✅ | ❌ | ❌

Arrow 可能是历史上最流行的第三方日期时间库。 它试图提供比标准库更“友好”的 API,但没有解决核心问题:它保留了相同的陷阱,并且它决定将类型数量减少到只有一个 (arrow.Arrow) 意味着类型检查器更难发现错误。

Pendulum 于 2016 年出现,承诺更好的 DST 处理以及更高的性能。 然而,它只修复了_一些_与 DST 相关的陷阱,并且它的性能随着时间的推移显着下降。 此外,它处于维护停滞状态,过去四年仅发布了一个版本,并且许多问题仍未解决。

为什么要使用 Whenever?

快速开始

>>> from whenever import (
...  # Explicit types for different use cases
...  Instant,
...  ZonedDateTime,
...  LocalDateTime,
... )
# Identify moments in time, without timezone/calendar complexity
>>> now = Instant.now()
Instant(2024-07-04 10:36:56Z)
# Simple, explicit conversions
>>> now.to_tz("Europe/Paris")
ZonedDateTime(2024-07-04 12:36:56+02:00[Europe/Paris])
# A 'naive' local time can't accidentally mix with other types.
# You need to explicitly convert it and handle ambiguity.
>>> party_invite = LocalDateTime(2023, 10, 28, hour=22)
>>> party_invite.add(hours=6)
Traceback (most recent call last):
 ImplicitlyIgnoringDST: Adjusting a local datetime implicitly ignores DST [...]
>>> party_starts = party_invite.assume_tz("Europe/Amsterdam")
ZonedDateTime(2023-10-28 22:00:00+02:00[Europe/Amsterdam])
# DST-safe arithmetic
>>> party_starts.add(hours=6)
ZonedDateTime(2023-10-29 03:00:00+01:00[Europe/Amsterdam])
# Comparison and equality
>>> now > party_starts
True
# Rounding and truncation
>>> now.round("minute", increment=15)
Instant(2024-07-04 10:30:00Z)
# Formatting & parsing common formats (ISO8601, RFC3339, RFC2822)
>>> now.format_rfc2822()
"Thu, 04 Jul 2024 10:36:56 GMT"
# If you must: you can convert to/from the standard lib
>>> now.py_datetime()
datetime.datetime(2024, 7, 4, 10, 36, 56, tzinfo=datetime.timezone.utc)

阅读功能概述API 参考了解更多信息。

路线图

局限性

版本控制和兼容性策略

Whenever 遵循语义版本控制。 在 1.0 版本之前,API 可能会随着次要版本的发布而发生变化。 破坏性更改将在更新日志中详细说明。 由于 API 是完全类型化的,因此你的类型检查器和/或 IDE 将帮助你适应任何 API 更改。

⚠️ 注意:在 1.x 版本之前,Pickle 序列化的对象可能无法跨版本反序列化。 1.0 版本之后,将尽可能保持 Pickle 的向后兼容性。

许可证

Whenever 基于 MIT 许可证。二进制 wheels 包含基于类似许可的 Rust 依赖项(MIT、Apache-2.0 和其他)。 更多详情请参见发行版中包含的许可证。

鸣谢

这个项目受到以下项目的启发,并借鉴了它们的大部分概念。 去看看吧!

基准比较图基于 Ruff 项目中的图。 对于时区数据,Whenever 使用 Python 自己的 zoneinfo 模块。

关于

⏰ 现代 Python 日期时间库 whenever.rtfd.io

Topics

python rust datetime cpython type-safe utc pypy utc-offsets pure-python timezones mypy rfc3339

Resources

Readme

License

MIT license Activity

Stars

1.4k stars

Watchers

13 watching

Forks

17 forks Report repository

Releases 36

0.7.3 Latest Mar 19, 2025 [+ 35 releases](