Python时间日期处理函数怎么用?datetime模块核心方法详解

周予安
周予安
发布时间:2026-10-20 | 5人浏览过
原创
在日常 Python 开发中,记录系统日志、统计业务数据指标、安排定时任务调度等场景都离不开时间与日期的处理。Python 官方标准库内置的 datetime 模块提供了完备的工业级解决方案。理解该模块的关键在于掌握三条主线:对象获取与构造、字符串双向转换(格式化与解析)以及时间差量(timedelta)的算术推移。本文将系统拆解 datetime 的核心类与高频方法,帮助你在实际项目中准确、高效地解决各类时间处理需求。

一、认识 datetime 模块的核心对象与分工

很多初学者容易将 datetime 模块当成一个单一的工具包,甚至误以为 datetime 只有一个类。实际上,标准库针对时间概念的不同维度进行了精巧的职责分离。datetime 模块内部主要包含以下五个核心类:

  • date 类:仅表示纯日期信息,包含年(year)、月(month)、日(day)。适用于不需要关心具体时间点的业务场景,例如生日记录、公休假日清单、合同起止日等。
  • time 类:仅表示一天内的时间,包含时(hour)、分(minute)、秒(second)、微秒(microsecond)及可选的时区信息。它独立于具体的日期,适用于记录每日开盘时间、定时巡检时刻等。
  • datetime 类:最常用的核心枢纽,同时包含完整的日期与时间信息,相当于 date 与 time 的集合体。
  • timedelta 类:表示两个时间点之间的持续时间或差量。所有的日期加减、天数推移都必须借助它来完成。
  • timezone / tzinfo 类:负责抽象时区规则与 UTC 偏移量,用于将没有地理概念的“天真时间”(Naive)转化为具备明确时区属性的“感知时间”(Aware)。
Python时间日期处理函数怎么用?datetime模块核心方法详解
图 1:datetime 模块核心类协同架构与职责分工关系

二、获取与构建时间对象的核心方法

在编写业务逻辑时,首要任务就是实例化时间对象。无论是获取系统当前时刻、从时间戳还原,还是手工指定具体的年月日时分秒,datetime 都提供了简洁直接的方法。

1. 获取当前系统时间:now() 与 today()

获取当前本地时间最标准的方式是调用 datetime.now()。虽然也可以调用 datetime.today(),但 now() 的灵活性更高,因为它允许直接传入 tz 参数来获取特定时区的当前时间。

from datetime import datetime, timezone

# 获取系统当前本地时间(无时区信息的 Naive 对象)
local_now = datetime.now()
print("当前本地时间:", local_now)

# 获取带有时区感知的当前 UTC 时间(推荐实践)
utc_now = datetime.now(timezone.utc)
print("当前 UTC 时间:", utc_now)

示例输出:

当前本地时间: 2026-10-20 12:18:34.125080
当前 UTC 时间: 2026-10-20 04:18:34.125080+00:00

2. 静态构造指定时间点与属性访问

构造特定时刻只需向 datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0) 传入数值。构造完成后,可直接通过属性读取具体时间成分:

from datetime import datetime

# 构造 2026 年 10 月 1 日 08:30:00
target_dt = datetime(2026, 10, 1, 8, 30, 0)

print(f"年: {target_dt.year}, 月: {target_dt.month}, 日: {target_dt.day}")
print(f"时: {target_dt.hour}, 分: {target_dt.minute}, 秒: {target_dt.second}")
# 获取星期几(0 代表周一,6 代表周日)
print("星期索引:", target_dt.weekday())

3. 时间戳与 datetime 对象的互转

在与数据库交互、消息队列传输或前端接口对接时,经常使用自 1970 年 1 月 1 日(Epoch)以来的秒数(Unix 时间戳)。转换方法非常直观:

from datetime import datetime

# 1. 将 datetime 对象转换为浮点型秒级时间戳
current_ts = datetime.now().timestamp()
print("时间戳:", current_ts)

# 2. 从时间戳恢复为本地 datetime 对象
restored_dt = datetime.fromtimestamp(current_ts)
print("还原时间:", restored_dt)

三、字符串与时间的相互转换(格式化与解析)

数据在网络传输或日志落盘时通常表现为字符串文本,而在程序内部运算时则需要还原为 datetime 对象。这一进一出的桥梁正是 strptime 与 strftime。

Python时间日期处理函数怎么用?datetime模块核心方法详解
图 2:时间字符串解析(strptime)与对象格式化(strftime)双向流程

1. strptime:将字符串解析为时间对象

方法名字中的 p 代表 parse(解析)。调用时必须显式提供与字符串完全一致的格式模板:

from datetime import datetime

date_str = "2026-10-20 15:30:00"
# 按照对应格式进行精准匹配
parsed_dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")

print("解析出的对象:", parsed_dt)
print("提取年份:", parsed_dt.year)
注意事项:字符串中的字符(包括连接符、空格、冒号)必须与格式控制符严格一一对应。若字符串中含有毫秒但格式串中遗漏了 %f,Python 会直接抛出 ValueError: time data '...' does not match format '...'。

2. strftime:将时间对象格式化为字符串

方法名字中的 f 代表 format(格式化)。该方法由具体的 datetime 实例调用,将内存对象转化为所需风格的文本:

from datetime import datetime

now = datetime(2026, 10, 20, 15, 30, 0)

# 输出为常见的中国地区常用格式
formatted_str = now.strftime("%Y年%m月%d日 %H时%M分%S秒")
print("中文格式化:", formatted_str)

# 紧凑型时间戳格式(常用于文件命名)
compact_str = now.strftime("%Y%m%d_%H%M%S")
print("文件名格式:", compact_str)

3. 高频使用的格式控制符速查

控制符 含义 取值范围与说明 示例(以 2026-10-20 为例)
%Y 四位年份 完整四位数字 2026
%m 月份 两位数字(前导补零 01-12) 10
%d 日(月中天) 两位数字(前导补零 01-31) 20
%H 24小时制小时 00-23 15
%I 12小时制小时 01-12 03
%M 分钟 00-59 30
%S 秒 00-59 00
%f 微秒 000000-999999(六位微秒) 125080
%z UTC 偏移量 +HHMM 或 -HHMM +0800

四、时间差量与计算——timedelta 的妙用

在业务逻辑中,常见的需求诸如“计算会员到期日(当前时间往后顺延 30 天)”、“获取昨天此时的统计快照”或“计算任务耗时”,这些都必须依赖 timedelta 类来完成。

Python时间日期处理函数怎么用?datetime模块核心方法详解
图 3:timedelta 时间加减推移与内部属性度量机制

1. 时间加减推移

timedelta 构造函数支持 days, seconds, microseconds, milliseconds, minutes, hours, weeks。直接将其加减到 datetime 对象上即可实现推移:

from datetime import datetime, timedelta

now = datetime(2026, 10, 20, 12, 0, 0)

# 计算 7 天后的时间
future_time = now + timedelta(days=7)
print("7 天后:", future_time)

# 计算 2 小时 30 分钟前的时间
past_time = now - timedelta(hours=2, minutes=30)
print("过去时间:", past_time)

2. 两个时间相减与 total_seconds() 的避坑要点

当两个 datetime 实例相减时,Python 会自动返回一个 timedelta 实例。很多开发者最容易在这里犯错:误用 delta.seconds 当作总相差秒数。

from datetime import datetime, timedelta

start = datetime(2026, 10, 20, 10, 0, 0)
end = datetime(2026, 10, 21, 10, 0, 15)  # 相隔 1 天零 15 秒

delta = end - start

# 常见误区:以为 delta.seconds 是总秒数
print("delta.days:", delta.days)         # 输出: 1
print("delta.seconds:", delta.seconds)   # 输出: 15 (仅仅是不足一天的余数部分!)

# 正确做法:使用 total_seconds() 获取总秒数
total_sec = delta.total_seconds()
print("实际总秒数:", total_sec)          # 输出: 86415.0
原理解释:timedelta 在内部存储时,为了避免数值过大溢出,会自动归一化(Normalize)为仅由 days、seconds(0 到 86399 之间)和 microseconds(0 到 999999 之间)三个属性组成。因此,凡是涉及总耗时换算,永远应当使用 total_seconds()。

五、常见易混淆点与避坑指南

在 Python 时间处理的实践中,有几个经典陷阱经常导致线上数据异常或偶发报错。理解其背后的原理即可从根本上规避。

1. 为什么 Python 3.12 废弃了 utcnow()?

很多老旧教程依然推崇 datetime.utcnow()。但从 Python 3.12 起,官方正式将 datetime.utcnow() 标记为 Deprecated(已废弃)。原因在于:utcnow() 返回的是一个 Naive 对象(虽然时间数值是 UTC 的,但该对象本身并未附带任何时区标识)。

如果开发者误把这个对象当成本地时间写入数据库,或者直接拿它与带时区的感知对象进行运算,就会造成 8 小时的时区错位。现代推荐规范是始终显式传入 UTC 时区对象:

from datetime import datetime, timezone

# 推荐的标准写法
current_utc = datetime.now(timezone.utc)
print("标准 UTC 时间(带时区感知):", current_utc)

2. Naive 与 Aware 对象的混合比较异常

在 Python 中,未绑定时区的时间对象称为 Offset-naive,绑定了时区的时间对象称为 Offset-aware。两者直接进行比较或相减时,Python 会为了保证数据严肃性直接抛出异常:

from datetime import datetime, timezone

naive_dt = datetime.now()
aware_dt = datetime.now(timezone.utc)

try:
    if naive_dt > aware_dt:
        print("比较成功")
except TypeError as e:
    print("错误提示:", e)
    # 输出: TypeError: can't compare offset-naive and offset-aware datetimes

解决办法:在系统边界处统一时间形态。若需要统一为带时区对象,可使用 .astimezone() 进行显式转换;若只需要本地比较,则确保参与运算的双方都同为 Naive 或同为 Aware。

3. datetime 实例的不可变性(Immutable)

datetime、date 和 time 对象在 Python 内部均为不可变对象。你不能直接通过 dt.year = 2027 修改其属性,这样会触发 AttributeError。若需调整某个特定属性,必须使用 replace() 方法生成一个新的实例:

from datetime import datetime

original_dt = datetime(2026, 10, 20, 15, 30, 0)
# 将年份修改为 2027,其他属性保持不变
modified_dt = original_dt.replace(year=2027)

print("原始对象:", original_dt)
print("修改后新对象:", modified_dt)

六、全流程决策与核心方法速查

为了在实际编码过程中迅速找到最适用的方法,下方的决策导图梳理了从具体业务目标到标准库 API 的直接映射路径:

Python时间日期处理函数怎么用?datetime模块核心方法详解
图 4:Python datetime 核心操作场景与对应方法决策速查导图

七、总结与生产实践建议

掌握 datetime 模块的关键不仅在于熟记各种格式控制符,更在于在系统设计初期确立清晰的时间处理边界。在工业级项目中,建议遵循以下三条黄金准则:

  1. 存储与传输统一使用 UTC:数据库时间字段、日志索引、内部微服务通信统一采用带时区标记的 UTC 时间或直接存储 Unix 秒级时间戳。绝对不要在数据持久层混存无时区信息的本地时间。
  2. 展示层单向转换:仅在最终面向用户渲染(Web 界面、移动端 App、导出报表)时,再利用 astimezone() 转为用户当地时区,并通过 strftime() 输出友好文本。
  3. 时间跨度优先使用 total_seconds():在任何计算系统运行时长、缓存失效剩余时间、接口响应耗时的场景下,均通过 (end - start).total_seconds() 进行计算,坚决避免直接使用 delta.seconds 导致跨天数据失真。
相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表