查看: 187|回复: 3

Python datetime模块日期时间处理与格式化实战

[复制链接]
发表于 1 小时前 | 显示全部楼层 |阅读模式
Python 处理日期与时间不必引入第三方框架,标准库 datetime 就覆盖了创建、格式化、解析、时间间隔运算、时区绑定和组件替换等常见需求。本文按实际编码顺序梳理 datetime 模块的核心类与常用方法,并给出可直接运行的代码片段,方便在日志时间戳、任务调度、数据清洗等脚本场景中复用。

一、模块中的核心类

datetime 是 Python 标准库模块,围绕日期与时间提供了一组类:date 表示日期,time 表示时间,datetime 表示日期加时间,timedelta 表示时间间隔,tzinfo 用于承载时区信息。日常脚本里出现频率最高的是 datetime 与 timedelta,前者是数据载体,后者是运算单位。

二、创建日期与时间对象

三个类都通过构造函数传入年、月、日、时、分、秒等字段完成实例化,注意 date 只接收年月日,time 只接收时分秒,datetime 则把两组字段合并在一起。
  1. from datetime import date, time, datetime
  2. # 创建日期
  3. d = date(2021, 11, 2)
  4. print(d)
  5. # 创建时间
  6. t = time(12, 30, 45)
  7. print(t)
  8. # 创建日期和时间
  9. dt = datetime(2021, 11, 2, 12, 30, 45)
  10. print(dt)
复制代码

这段代码的输出分别是纯日期、纯时间和完整时间戳,也是后续格式化与计算的输入基础。

三、对象与字符串之间的互转

脚本与外部系统交互时,时间几乎都以字符串形态出现,因此 strftime 与 strptime 是一对必须掌握的方法:strftime 负责把对象转成字符串,strptime 负责把字符串还原成对象。
  1. from datetime import datetime
  2. dt = datetime(2021, 11, 2, 12, 30, 45)
  3. formatted_dt = dt.strftime('%Y-%m-%d %H:%M:%S')
  4. print(formatted_dt)
复制代码

反向解析时,格式串必须与输入字符串严格对应,否则会抛出解析异常:
  1. from datetime import datetime
  2. date_string = '2021-11-02 12:30:45'
  3. dt = datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')
  4. print(dt)
复制代码

这里的 %Y 表示四位年份,%m 表示两位月份,%d 表示两位日期,%H、%M、%S 分别对应时、分、秒。格式串与实际字符串一旦错位(例如用 %m 去匹配月份位置却写成了 %d),解析就会失败,这是时间处理脚本最常见的报错来源之一。

四、用 timedelta 做时间加减

timedelta 表示一段时间长度,可与 datetime 对象直接相加或相减,得到新的时间点。它支持 days、hours 等关键字参数,适合计算“N 天后”“N 小时前”这类偏移量。
  1. from datetime import datetime, timedelta
  2. dt = datetime(2021, 11, 2, 12, 30, 45)
  3. # 加上5天
  4. dt_plus_5_days = dt + timedelta(days=5)
  5. print(dt_plus_5_days)
  6. # 减去3小时
  7. dt_minus_3_hours = dt - timedelta(hours=3)
  8. print(dt_minus_3_hours)
复制代码

注意运算结果是一个新对象,原对象保持不变,这种不可变特性让时间计算在函数间传递时更安全。

五、时区信息的处理

datetime 自身通过 tzinfo 参数承载时区,具体时区对象可以借助第三方库 pytz 获取。使用前需要先安装 pytz,再通过 timezone 名称取得时区实例,最后作为 tzinfo 传入构造函数。
  1. from datetime import datetime
  2. import pytz
  3. # 创建时区对象
  4. tz = pytz.timezone('Asia/Shanghai')
  5. # 创建时区时间
  6. dt = datetime(2021, 11, 2, 12, 30, 45, tzinfo=tz)
  7. print(dt)
复制代码

这段示例演示的是“带时区的时间对象”,打印结果会附带时区标识。脚本中凡是涉及跨地区时间展示、日志对齐,都建议从创建阶段就显式带上时区信息,避免后续再做二次推断。

六、读取与替换时间组件

datetime 对象的每个字段都有对应属性,可以直接读取,用于分组统计、按小时聚合等场景。
  1. from datetime import datetime
  2. dt = datetime(2021, 11, 2, 12, 30, 45)
  3. print(dt.year)
  4. print(dt.month)
  5. print(dt.day)
  6. print(dt.hour)
  7. print(dt.minute)
  8. print(dt.second)
复制代码

如果只想改动其中某几个字段,用 replace 更直观,它返回修改后的新对象,未指定的字段保持原值:
  1. from datetime import datetime
  2. dt = datetime(2021, 11, 2, 12, 30, 45)
  3. dt_replaced = dt.replace(year=2022, month=12, day=31)
  4. print(dt_replaced)
复制代码

处理“把某天的时间归零”“统一改成月初”这类需求时,replace(day=1, hour=0, minute=0, second=0) 之类的写法比手工重构造更简洁。

七、比较与算术运算

datetime 对象之间支持比较,也支持通过差值得到 timedelta 再参与后续运算,下面的示例先用两个时间点做大小比较,再把时间差放大两倍后加到起点上。
  1. from datetime import datetime, timedelta
  2. dt1 = datetime(2021, 11, 2, 12, 30, 45)
  3. dt2 = datetime(2021, 11, 5, 15, 20, 10)
  4. # 比较运算
  5. print(dt1 < dt2)
  6. # 算术运算
  7. dt3 = dt1 + (dt2 - dt1) * 2
  8. print(dt3)
复制代码

dt2 - dt1 得到的是一个 timedelta,乘以 2 仍然是 timedelta,再与 dt1 相加得到新的时间点。这种“差值—缩放—回加”的组合在排期推算、区间外推等逻辑里很实用。

八、实践中的注意点

第一,格式串是解析成败的关键,strptime 的格式必须与字符串逐字符对应,出现 ValueError 时优先检查分隔符与占位符是否一致。第二,涉及时区时建议尽早绑定 tzinfo,不要在字符串里手工拼接时区偏移。第三,时间加减统一走 timedelta,避免自行用秒数换算,以免在跨天、跨月时写错边界。第四,pytz 属于额外依赖,部署脚本时要把安装步骤写进依赖清单。

以上内容覆盖了 datetime 模块在日期创建、格式化、字符串解析、时间间隔运算、时区绑定、组件读取与替换以及比较运算方面的基本用法,掌握这些方法后,绝大多数脚本级时间处理需求都可以在标准库范围内完成。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python datetime模块日期时间处理与格式化实战

感谢楼主的整理,按编码顺序走一遍确实比零散看文档清楚很多。补两个我在实际脚本里踩过的点,供参考: 一是 pytz 那块,示例里直接把 tzinfo=tz 传进构造函数,打印出来的偏移量有时不是 +08:00,而是 LMT 的 +08:06 之类。pytz 的时区对象不推荐这样直接绑定,规范做法是先造出不带时区的时间,再调用 tz.localize(dt) 附加时区,已有带时区对象要改时区则用 astimezone。如果只是想要当前时间的上海时区,直接 datetime.now(tz) 就没问题。 二是如果项目跑在 Python 3.9 以上,标准库里已经有 zoneinfo,ZoneInfo("Asia/Shanghai") 可以直接当 tzinfo 用,连 pytz 都不用装,跟 datetime 的配合也更自然,没有 localize 那套讲究。老代码迁移的话要注意一下。 另外第六节读取组件,年、月、日这些本身也可以直接给 date 和 time 用,比如 dt.date()、dt.time() 拿来分组统计挺方便;算两个时间差想要总秒数可以用 total_seconds(),不然天数、秒数分开取容易算错。 整体这篇作为速查很实用,特别是最后提醒格式串逐字符对应那条,确实是我见过最多的 ValueError 来源。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python datetime模块日期时间处理与格式化实战

感谢整理,内容按实际编码顺序展开,从创建对象、字符串互转、timedelta 运算,到时区、replace、比较与算术,结构清楚,代码片段也短小可直接运行。strptime 格式串必须和输入逐字符对应这一点很关键,实际排查 ValueError 时先看分隔符和占位符确实能少走弯路。时区部分如果能再补一个跨时区转换或日志时间对齐的小例子会更完整;另外 pytz 直接作为 tzinfo 传入的写法在复杂场景下要留意,后续展开时可以讲讲 localize 和 astimezone 的用法。整体对日志时间戳、调度和数据清洗这类脚本很实用。
回复 支持 反对

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python datetime模块日期时间处理与格式化实战

感谢分享,这篇把 datetime 的常用操作串得很系统,尤其 strptime 格式串必须与字符串严格对应那段,确实是我平时踩坑最多的地方,一报 ValueError 基本就是占位符或分隔符对不上。replace 那段也很实用,我之前做报表把时间归零都是手动重新构造对象,看到 replace(day=1, hour=0, minute=0, second=0) 才发现简洁很多。用 timedelta 做任务调度的偏移量也很顺手,不可变这点在函数间传参时确实省心。 另外第八点好像没写完,期待后续补上。也想顺便问下时区那部分,pytz 的时区对象直接作为 tzinfo 传给 datetime 构造函数,和先创建 naive 时间再用 localize 绑定,这两者在实际脚本里有区别吗?之前好像碰到过夏令时相关的边界情况,不太确定是不是这个原因。整体整理得很清晰,先收藏了慢慢对照着用。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-11-12 04:52 , Processed in 0.025196 second(s), 28 queries , Gzip On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部