A Pitfall-Avoidance Guide to Elegantly Handling Date and Time in Modern Python
Still falling into traps with Python time handling? `datetime`, `time`, and `calendar` will make your head spin, and the Naive vs Aware timezone trap is even worse. Still using `pytz` in 2026? The standard library's `ZoneInfo` plus `Pendulum` and `Arrow` is what modern looks like—at least you don't have to write those user-hostile time-string parsers anymore. Store UTC in the database, send ISO 8601 on the frontend—can we keep it simple?
目录8 个章节
Introduction
Many Python beginners (and even veterans) have fallen into these pitfalls:
- Too many modules: You have to deal with three modules at once:
datetime,time, andcalendar. Want a timestamp? Go totime. Want to add or subtract dates? Back todatetime. - Naive vs Aware (the timezone trap): This is the worst of them. By default, Python creates
datetimeobjects without timezone information (Naive). If you compare or add a timezone-aware object with a naive one, the program will throw aTypeErrorand crash. - A fragmented API: To subtract 3 days, you have to import
timedeltaand writedatetime.now() - timedelta(days=3); to parse an ISO string, you have to write a longstrptimeformat string. - No support for "human language": You can't directly handle logic like "yesterday" or "in two weeks"; you have to compute
timedeltaby hand.
By comparison, Go may force you to memorize the magical reference time 2006-01-02 15:04:05, but at least the logic is self-consistent. Python's native experience feels more like endlessly patching things up.
Recommended New Tools
It's 2026. Both the community ecosystem and the Python standard library have evolved. Let's look at these modern approaches to handling time.
| Library | Role | Why recommend it |
|---|---|---|
| ZoneInfo | Standard library | Built into Python 3.9+, completely replaces pytz, handles IANA timezones. |
| Pendulum | Core logic | A subclass of datetime, extremely elegant syntax; "in a few days" and "next Monday" come naturally. |
| Arrow | Collector | A must-have for web scraping. Excellent compatibility with messy strings—one .get() and you're done. |
Before Python 3.9, pytz was the only option for timezone handling, but its API design is extremely user-hostile (for example, the infamous localize trap).
Today in 2026, ZoneInfo together with the IANA timezone database is very mature. If you're running on Windows, remember to install the tzdata package; on Linux, it reads the system database directly. This is truly Pythonic.
How to choose?
- Want "zero dependencies" and only need timezone conversion: Choose
ZoneInfo(standard library). - Need complex date arithmetic (e.g. "the third Friday of next month"): Choose
Pendulum. - Writing a scraper and facing all kinds of weird time strings: Choose
Arrow. - Using Django: Stick with Django's built-in
timezoneutilities (under the hood it has fully embracedZoneInfo).
Code examples
Complex timezone conversion and arithmetic (using Pendulum)
import pendulum
# 1. 语义化创建
now = pendulum.now('Asia/Shanghai')
future = now.add(months=2).end_of('week')
# 2. 极简的“人类化”显示
print(future.diff_for_humans()) # "2 months from now"
# 3. 彻底解决时区比对崩溃
dt_utc = pendulum.now('UTC')
if now > dt_utc: # Pendulum 会自动处理比对逻辑
print("安全比对,不再报错")
Parsing messy timestamps from APIs or scrapers (using Arrow)
import arrow
# 不管是时间戳、ISO 8601 还是特定格式,统统 get
raw_date = "2026-03-24T10:13:35+08:00"
t = arrow.get(raw_date)
# 转换成北京时间并格式化
print(t.to('Asia/Shanghai').format('YYYY-MM-DD HH:mm:60'))
Timezone conversion with the standard library (ZoneInfo)
If you're writing a lightweight script and don't want extra dependencies, you can use the standard library's ZoneInfo directly.
from datetime import datetime
from zoneinfo import ZoneInfo
# 1. 创建一个带时区的 UTC 时间(2026 年的标配起点)
utc_now = datetime.now(ZoneInfo("UTC"))
print(f"UTC 时间: {utc_now}")
# 2. 一行代码转成本地时间(比如北京时间)
# 再也不需要 pytz.timezone('...').localize(...) 这种阴间操作了
beijing_time = utc_now.astimezone(ZoneInfo("Asia/Shanghai"))
print(f"北京时间: {beijing_time}")
# 3. 甚至可以处理极其冷门的时区,比如你想看看纽约的开发者在干嘛
ny_time = beijing_time.astimezone(ZoneInfo("America/New_York"))
print(f"纽约时间: {ny_time}")
# 4. 获取简写的时区名称(如 CST, EST)
print(f"当前时区缩写: {ny_time.tzname()}")
Wrapping Up
Never use datetime.now(): Get into the habit of using datetime.now(ZoneInfo("UTC")) or pendulum.now().
Always store UTC in the database: No matter where the user is, what you store in the database must be UTC.
Deliver ISO 8601 to the frontend: Don't send timestamps; send a standard string like 2026-03-25T11:30:00Z. That's the least painful for the frontend to parse.
_EOF_
A Pitfall-Avoidance Guide to Elegantly Handling Date and Time in Modern Python
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
关于Python的异常处理
前言 异常处理在任何一门编程语言里都是值得关注的一个话题,良好的异常处理可以让你的程序更加健壮,清晰的错误信息更能帮助你快速修复问题。在Python中,和部分高级语言一样,使用了try/except/finally语句块来处理异常,如果你有其他编程语言的经验,实践起来并不难。 Python 中(至少)有两种错误:语法错误和异常( syntax errors 和 exceptions )。下面稍微介
2022-05-27 · Python · 约 1 分钟
我用Qt和Python开发了一个视频合并工具
想合并视频,但是却找不到比较好用的工具,很多都要收费,我想着「这破功能还得收费?」,于是决定自己搞一个,一开始用Python做了一个,效果还不错,完美完成了我的视频合并任务,不过没有图形界面,想分享给朋友一起用也没办法,于是昨天用Qt写了个图形界面套上去,中间还是遇到一些问题的,通过这篇文章记录一下。 软件的界面就是这样啦,用Qt Designer随便拖出来的,和VS拖控件也差不了多少。 用起来挺
2021-12-18 · Python · 约 1 分钟
Python实现从Excel生成Model和导入脚本
前言 最近遇到一个需求,有几十个Excel,每个的字段都不一样,然后都差不多是第一行是表头,后面几千上万的数据,需要把这些Excel中的数据全都加入某个已经上线的Django项目 这就需要每个Excel建个表,然后一个个导入了 这样的效率太低,不能忍 所以我造了个自动生成 Model 和导入脚本的轮子 思路 首先拿出 pandas,它的 DataFrame 用来处理数据很方便 pandas 加载
2022-11-22 · Python · 约 1 分钟
Python-本地时间和UTC时间转换
代码 import time import datetime def utc2local(utc_st): UTC时间转本地时间(+8: 00) now_stamp = time.time() local_time = datetime.datetime.fromtimestamp(now_stamp) utc_time = datetime.datetime.ut
2021-12-18 · Python · 约 1 分钟
讨论
共 0 条加载评论中…