不知道你有没有遇到过这些场景:给当前日期加一周、解析日志时间戳、两个看起来完全一样的时间却无法进行相等对比?Python 内置的 datetime 模块功能很强大,但也很容易踩坑。今天我们的主要任务就是来看看它。datetime模块提供三个基础时间类date /time/datetime,根据业务场景选择对应类型:from datetime import date, time, datetime# date:仅年月日,不含时分秒d = date(2025, 5, 6)print(d) # 2025-05-06# time:仅时分秒,不含日期t = time(14, 30, 0)print(t) # 14:30:00# datetime:同时包含日期+时间,90% 业务场景首选dt = datetime(2025, 5, 6, 14, 30, 0)print(dt) # 2025-05-06 14:30:00
- date可以用于生日、过期日期、事件排期、不需要精确到时刻的业务
- time用于固定重复时段(每日 9 点执行任务),独立于日期
- datetime用于日志时间戳、高精度定时任务、同时需要日期 + 时间的场景
from datetime import datetime, date# 获取本地完整时间(无时区信息,朴素时间)now = datetime.now()print(now)# 仅获取今日日期today = date.today()print(today)
strftime:时间对象格式化输出字符串。strftime = string format time,通过格式化占位符,把时间转为自定义文本。from datetime import datetimenow = datetime(2025, 5, 6, 14, 30, 5)# 标准ISO8601格式(接口、日志通用,机器可读)print(now.strftime("%Y-%m-%dT%H:%M:%S")) # 2025-05-06T14:30:05# 可读完整日期print(now.strftime("%B%d, %Y at %I:%M%p")) # May 06, 2025 at 02:30 PM# 文件名专用紧凑日期print(now.strftime("%Y%m%d")) # 20250506
from datetime import datetime# 解析日志ISO时间字符串raw = "2025-05-06T14:30:05"dt = datetime.strptime(raw, "%Y-%m-%dT%H:%M:%S")print(dt.year) # 2025# 解析英文人类可读日期raw2 = "May 06, 2025"dt2 = datetime.strptime(raw2, "%B%d, %Y")print(dt2) # 2025-05-06 00:00:00
需要注意的是格式化字符串分隔符必须和输入文本完全匹配。例如:字符串2025/05/06 不能使用 %Y-%m-%d 解析,会直接抛出 ValueError。from datetime import datetime, timedeltanow = datetime(2025, 5, 6, 14, 30, 0)# 加7天(一周后)next_week = now + timedelta(days=7)print(next_week)# 减2小时(两小时前)two_hours_ago = now - timedelta(hours=2)print(two_hours_ago)# 计算两个时间的间隔start = datetime(2025, 5, 1, 9, 0, 0)end = datetime(2025, 5, 6, 14, 30, 0)delta = end - startprint(delta.days) # 间隔总天数 5print(delta.total_seconds()) # 间隔总秒数 484200.0
from datetime import datetimedt1 = datetime(2025, 5, 1)dt2 = datetime(2025, 5, 6)print(dt1 < dt2) # Trueprint(dt1 == dt2) # False# 筛选2025年5月的所有事件events = [ datetime(2025, 4, 30), datetime(2025, 5, 3), datetime(2025, 5, 15), datetime(2025, 6, 1),]may_start = datetime(2025, 5, 1)may_end = datetime(2025, 5, 31, 23, 59, 59)may_events = [e for e in events if may_start <= e <= may_end]# 时间列表升序排序sorted_events = sorted(events)
带时区的时间 zoneinfo。默认 datetime.now() 生成的时间不带时区标记。服务器跨时区、多数据源时间对比时极易出错,生产环境必须使用带时区的。from datetime import datetimefrom zoneinfo import ZoneInfo# 时间:无tzinfo,生产日志禁止使用naive = datetime.now()print(naive.tzinfo) # None# 带纽约时区的时间aware = datetime.now(tz=ZoneInfo("America/New_York"))print(aware) # 2025-05-06 14:30:00-04:00print(aware.tzinfo) # America/New_York# 时区互相转换utc_dt = datetime.now(tz=ZoneInfo("UTC"))eastern = utc_dt.astimezone(ZoneInfo("America/New_York"))print(eastern)
接下来我们看看Unix 时间戳互转 timestamp () /fromtimestamp ()from datetime import datetimefrom zoneinfo import ZoneInfo# datetime 转时间戳dt = datetime(2025, 5, 6, 14, 30, 0, tzinfo=ZoneInfo("UTC"))ts = dt.timestamp()print(ts) # 1746541800.0# 时间戳转回datetime(不传时区默认本地时间,环境不一致会出错)dt_back = datetime.fromtimestamp(ts)# 推荐写法:指定UTC时区,全环境结果统一dt_utc = datetime.fromtimestamp(ts, tz=ZoneInfo("UTC"))print(dt_utc)
搞清楚上面的内容,对于datetime应用大概就已经掌握了。更具体的还是需要去实践来解决了。