Python 时间处:深入理解 datetime 模块

日期与时间是编程中常见的难题,从简单的时间获取到复杂的时区转换,Python 的 datetime 模块都能轻松应对。本文将带你从基础到进阶,彻底掌握这个强大的工具。

在 Python 开发中,处理日期和时间几乎是每个项目都会遇到的需求。无论是记录日志、计算时间差、处理用户所在时区,还是生成时间戳,datetime 模块都是最得力的助手。本文将系统讲解 datetime 的核心用法,并重点攻克时区处理这一难点

一、datetime 模块的核心组件

datetime 模块主要包含以下几个核心类:

类名 功能描述
date 处理年、月、日的日期对象
time 处理时、分、秒、微秒的时间对象
datetime 日期和时间的组合对象
timedelta 表示两个时间点之间的差值
timezone 时区对象(Python 3.2+ 引入)
tzinfo 时区信息抽象基类

二、基础操作:创建与获取时间

2.1 获取当前时间

from datetime import datetime, date, time

# 获取当前本地日期时间
now = datetime.now()
print(f"当前本地时间: {now}")

# 获取当前 UTC 时间
utc_now = datetime.utcnow()
print(f"当前UTC时间: {utc_now}")

# 仅获取今天的日期
today = date.today()
print(f"今天日期: {today}")

2.2 创建指定日期时间

# 创建指定日期时间
dt = datetime(2026, 4, 25, 15, 30, 45)
print(dt)  # 2026-04-25 15:30:45

# 仅创建日期
d = date(2026, 4, 25)
print(d)  # 2026-04-25

# 仅创建时间
t = time(15, 30, 45)
print(t)  # 15:30:45

三、时间运算:timedelta 的妙用

timedelta 可以表示时间差,支持加减运算,非常灵活:

from datetime import datetime, timedelta

now = datetime.now()

# 计算 7 天后的时间
future = now + timedelta(days=7)
print(f"一周后: {future}")

# 计算 2 小时前的时间
past = now - timedelta(hours=2)
print(f"两小时前: {past}")

# 同时指定多个时间单位
delta = timedelta(days=5, hours=3, minutes=30)
new_time = now + delta
print(f"5天3小时30分钟后: {new_time}")

# 时间差计算
diff = future - now
print(f"时间差: {diff.days} 天, {diff.seconds} 秒")

四、时间格式化与解析

4.1 strftime:将 datetime 转为字符串

from datetime import datetime

now = datetime.now()

# 常用格式示例
print(now.strftime("%Y-%m-%d %H:%M:%S"))     # 2026-04-25 15:30:45
print(now.strftime("%Y年%m月%d日"))           # 2026年04月25日
print(now.strftime("%A"))                    # 星期六(完整星期名)
print(now.strftime("%a"))                    # 周六(缩写星期名)
print(now.strftime("%p %I:%M"))              # PM 03:30(12小时制)

4.2 strptime:将字符串转为 datetime

from datetime import datetime

date_str = "2026-04-25 15:30:45"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt)  # 2026-04-25 15:30:45

# 处理不同格式
str2 = "25/04/2026"
dt2 = datetime.strptime(str2, "%d/%m/%Y")
print(dt2)  # 2026-04-25 00:00:00

常用格式化代码速查:%Y 四位年份、%m 两位月份、%d 两位日期、%H 24小时制、%M 分钟、%S 秒、%A 完整星期、%a 缩写星期、%p AM/PM。

五、进阶难点:时区处理

时区处理是时间操作中最容易出错的环节。Python 提供了两种时区处理方式:标准库的 timezone 和第三方库 pytz

5.1 认知两类 datetime 对象

  • Naive(朴素)datetime:不包含时区信息,就像“2026-04-25 15:30:45”这样的时间,存在歧义。
  • Aware(感知)datetime:包含时区信息,是绝对明确的时间点。
from datetime import datetime, timezone

# 朴素时间对象
naive_now = datetime.now()
print(f"朴素时间: {naive_now}")
print(f"是否含时区信息: {naive_now.tzinfo}")  # None

# 感知时间对象(带 UTC 时区)
aware_utc = datetime.now(timezone.utc)
print(f"感知时间(UTC): {aware_utc}")
print(f"时区信息: {aware_utc.tzinfo}")

5.2 时区转换实战

方法一:使用 datetime 自带的 timezone(适用于简单场景)

from datetime import datetime, timezone, timedelta

# 创建东八区时区对象
tz_utc_8 = timezone(timedelta(hours=8))

# 获取当前 UTC 时间(感知型)
utc_now = datetime.now(timezone.utc)
print(f"UTC 时间: {utc_now}")

# 转换为东八区时间
beijing_time = utc_now.astimezone(tz_utc_8)
print(f"北京时间: {beijing_time}")

# 直接获取东八区当前时间
beijing_now = datetime.now(tz_utc_8)
print(f"直接获取北京时间: {beijing_now}")

方法二:使用 pytz 库(处理历史时区变化和夏令时的推荐方案)

# 需要先安装 pytz: pip install pytz
import pytz
from datetime import datetime

# 获取指定时区
tz_shanghai = pytz.timezone('Asia/Shanghai')
tz_ny = pytz.timezone('America/New_York')

# 将朴素时间本地化为感知时间
naive_time = datetime(2026, 4, 25, 15, 30, 0)
shanghai_time = tz_shanghai.localize(naive_time)
print(f"北京时间: {shanghai_time}")

# 时区转换:上海 -> 纽约
ny_time = shanghai_time.astimezone(tz_ny)
print(f"纽约时间: {ny_time}")

5.3 关键注意事项

问题场景 错误做法 正确做法
获取当前时间 datetime.now() 用于感知时间 datetime.now(timezone.utc)
时区转换 直接给朴素时间设置 tzinfo 使用 localize()astimezone()
时间差计算 混合 naive 和 aware 对象 保持统一,尽量使用 UTC 存储

六、实用技巧与最佳实践

6.1 时间戳与 datetime 互转

import time
from datetime import datetime

# datetime 转时间戳
now = datetime.now()
timestamp = now.timestamp()
print(f"时间戳: {timestamp}")

# 时间戳转 datetime
dt = datetime.fromtimestamp(timestamp)
print(f"恢复时间: {dt}")

# UTC 时间戳转 datetime
dt_utc = datetime.utcfromtimestamp(timestamp)
print(f"UTC 时间: {dt_utc}")

6.2 多时区网站的最佳实践

对于面向全球用户的 Web 应用,推荐以下模式:

  1. 统一使用 UTC 时间存储数据库中的所有时间字段
  2. 仅在展示层进行时区转换,根据用户偏好时区转换显示
  3. 使用 pytzzoneinfo(Python 3.9+)处理完整时区数据库
# Python 3.9+ 推荐 zoneinfo(标准库)
from zoneinfo import ZoneInfo
from datetime import datetime

# 存储(始终使用 UTC)
utc_time = datetime.now(ZoneInfo("UTC"))

# 展示时转换给用户(假设用户时区为美国东部)
user_tz = ZoneInfo("America/New_York")
user_time = utc_time.astimezone(user_tz)
print(user_time.strftime("%Y-%m-%d %H:%M:%S %Z"))

6.3 性能小提示

  • 频繁调用 datetime.now() 有一定开销,可以重用变量。
  • 大量时间解析时,预编译 strptime 格式会略微提升性能。

七、总结

datetime 模块是 Python 时间处理的基石,掌握它可以让你的代码更加健壮和国际化。回顾一下今天学到的核心要点:

  • 创建时间now(), utcnow(), 直接构造
  • 时间运算:使用 timedelta 进行加减
  • 格式化strftime 输出,strptime 解析
  • 时区处理:区分 naive 与 aware,使用 timezonepytz 正确转换
  • 最佳实践:内部存储用 UTC,展示时按需转换
Logo

这里是“一人公司”的成长家园。我们提供从产品曝光、技术变现到法律财税的全栈内容,并连接云服务、办公空间等稀缺资源,助你专注创造,无忧运营。