免费python编程教程:https://pan.quark.cn/s/2c17aed36b72
在Python编程中,时间处理是绕不开的核心需求。无论是记录日志、计算程序运行时长,还是处理时区转换,都需要精准的时间操作工具。Python标准库中的datetime模块就像一把瑞士军刀,用简洁的API解决了90%的时间处理场景。本文将通过实际代码示例,带你掌握这个模块的核心用法。
一、基础时间对象:构建时间数据的基石
1.1 创建时间点的三种方式
datetime模块提供了三种基础时间对象:date(仅日期)、time(仅时间)、datetime(日期+时间)。创建方式如下:
from datetime import date, time, datetime
仅日期(2025年10月29日)
d = date(2025, 10, 29)
print(d) # 输出:2025-10-29
仅时间(15点30分)
t = time(15, 30)
print(t) # 输出:15:30:00
日期+时间(2025年10月29日15:30)
dt = datetime(2025, 10, 29, 15, 30)
print(dt) # 输出:2025-10-29 15:30:00
应用场景:
记录系统启动时间(datetime)
统计每日访问量(仅用date)
计算任务执行时长(time差值)
1.2 获取当前时间的三种方法
方法1:now() 获取本地时间(含时区信息需额外处理)
now = datetime.now()
print(now) # 输出:2025-10-29 15:30:45.123456
方法2:today() 等同于now()但无参数
today = datetime.today()
方法3:utcnow() 获取UTC时间(无时区)
utc_now = datetime.utcnow()
print(utc_now) # 输出:2025-10-29 07:30:45.123456(假设UTC+8)
关键区别:
now()和today()返回本地时间,受系统时区影响
utcnow()返回零时区时间,适合跨时区计算
二、时间格式化:让机器时间人性化
2.1 字符串转时间对象(解析)
使用strptime()将字符串解析为datetime对象,需指定格式字符串:
from datetime import datetime
解析标准格式
dt1 = datetime.strptime("2025-10-29", "%Y-%m-%d")
print(dt1) # 输出:2025-10-29 00:00:00
解析带时间的字符串
dt2 = datetime.strptime("29/10/2025 15:30", "%d/%m/%Y %H:%M")
print(dt2) # 输出:2025-10-29 15:30:00
常见格式符说明
"""
%Y: 四位年份(2025)
%m: 两位月份(01-12)
%d: 两位日期(01-31)
%H: 24小时制小时(00-23)
%M: 分钟(00-59)
%S: 秒(00-59)
"""
避坑指南:
格式字符串必须与输入字符串完全匹配,否则会抛出ValueError
处理用户输入时,建议先用try-except捕获异常
2.2 时间对象转字符串(格式化)
使用strftime()将时间对象转为自定义格式字符串:
now = datetime.now()
常见格式示例
print(now.strftime("%Y-%m-%d")) # 输出:2025-10-29
print(now.strftime("%d/%m/%Y")) # 输出:29/10/2025
print(now.strftime("%A, %B %d")) # 输出:Wednesday, October 29
print(now.strftime("%H:%M:%S")) # 输出:15:30:45
print(now.strftime("%Y%m%d%H%M%S")) # 输出:20251029153045(常用作文件名)
本地化格式(需配合locale模块)
import locale
locale.setlocale(locale.LC_TIME, 'zh_CN.UTF-8')
print(now.strftime("%Y年%m月%d日")) # 输出:2025年10月29日
实用技巧:
生成日志文件名:f"log_{now.strftime('%Y%m%d')}.txt"
显示友好时间:now.strftime("%Y年%m月%d日 %H时%M分")
三、时间运算:让时间动起来
3.1 时间差计算(timedelta)
timedelta类表示两个时间点之间的间隔,支持天、秒、微秒等单位:
from datetime import datetime, timedelta
计算30天后的日期
now = datetime.now()
future = now + timedelta(days=30)
print(future) # 输出:2025-11-28 15:30:45.123456
计算2小时前的时间
past = now - timedelta(hours=2)
计算两个日期的差值
date1 = datetime(2025, 1, 1)
date2 = datetime(2025, 12, 31)
delta = date2 - date1
print(delta.days) # 输出:364(非闰年)
进阶用法:
计算工作日:需排除周末(可结合dateutil库)
计算年龄:age = (now - birth_date).days // 365
3.2 时间比较
datetime对象可直接比较大小:
date1 = datetime(2025, 10, 28)
date2 = datetime(2025, 10, 29)
if date1 < date2:
print("date1早于date2") # 会执行此分支
检查是否在某个时间段内
start = datetime(2025, 10, 1)
end = datetime(2025, 10, 31)
now = datetime.now()
if start <= now <= end:
print("当前时间在10月范围内")
四、时区处理:跨越时间的边界
4.1 时区基础概念
Python中的时间对象分为两类:
naive对象:不含时区信息(如datetime.now())
aware对象:明确时区信息(需配合pytz或zoneinfo)
创建aware对象(需安装pytz)
import pytz
from datetime import datetime
tz = pytz.timezone('Asia/Shanghai')
shanghai_time = tz.localize(datetime(2025, 10, 29, 15, 30))
print(shanghai_time) # 输出:2025-10-29 15:30:00+08:00
转换为UTC时间
utc_time = shanghai_time.astimezone(pytz.UTC)
print(utc_time) # 输出:2025-10-29 07:30:00+00:00
4.2 Python 3.9+的zoneinfo(推荐)
Python 3.9引入了标准库zoneinfo,无需安装第三方库:
from datetime import datetime
from zoneinfo import ZoneInfo
创建带时区的时间
tokyo_time = datetime(2025, 10, 29, 15, 30, tzinfo=ZoneInfo('Asia/Tokyo'))
print(tokyo_time) # 输出:2025-10-29 15:30:00+09:00
时区转换
ny_time = tokyo_time.astimezone(ZoneInfo('America/New_York'))
print(ny_time) # 输出:2025-10-29 02:30:00-04:00(夏令时)
关键提醒:
始终优先使用aware对象处理跨时区业务
数据库存储建议用UTC时间,显示时再转换本地时区
五、实战案例:从入门到精通
案例1:计算程序运行时间
import time
from datetime import datetime, timedelta
start = datetime.now()
模拟耗时操作
time.sleep(2.5)
end = datetime.now()
duration = end - start
print(f"程序运行耗时:{duration.total_seconds():.2f}秒")
输出:程序运行耗时:2.50秒
案例2:生成带时区的日志
from datetime import datetime
from zoneinfo import ZoneInfo
def log_message(message):
now = datetime.now(ZoneInfo('Asia/Shanghai'))
timestamp = now.strftime("%Y-%m-%d %H:%M:%S %Z")
print(f"[{timestamp}] {message}")
log_message("系统启动成功")
输出:[2025-10-29 15:30:45 CST] 系统启动成功
案例3:处理用户输入的日期
from datetime import datetime
def parse_user_date(date_str):
try:
# 尝试多种格式
for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%m-%d-%Y"):
try:
return datetime.strptime(date_str, fmt)
except ValueError:
continue
raise ValueError("日期格式不匹配")
except ValueError as e:
print(f"错误:{e}")
return None
测试
print(parse_user_date("2025-10-29")) # 成功
print(parse_user_date("29/10/2025")) # 成功
print(parse_user_date("10-29-2025")) # 成功
print(parse_user_date("2025/10/29")) # 报错
六、常见问题解决方案
问题1:strptime报错"unconverted data remains"
原因:格式字符串与输入不匹配
解决:
错误示例(字符串包含多余空格)
dt = datetime.strptime("2025-10-29 15:30 ", "%Y-%m-%d %H:%M") # 报错
正确做法:精确匹配格式
dt = datetime.strptime("2025-10-29 15:30", "%Y-%m-%d %H:%M")
问题2:闰年/月份天数验证
风险:直接创建date(2025, 2, 29)会抛出ValueError
解决:
from datetime import date
def is_valid_date(year, month, day):
try:
date(year, month, day)
return True
except ValueError:
return False
print(is_valid_date(2025, 2, 29)) # 输出:False
print(is_valid_date(2024, 2, 29)) # 输出:True(2024是闰年)
问题3:时区转换混乱
场景:需要显示多个时区的当前时间
解决:
from datetime import datetime
from zoneinfo import ZoneInfo
def get_world_times():
now = datetime.now(ZoneInfo('UTC'))
times = {
'UTC': now,
'北京': now.astimezone(ZoneInfo('Asia/Shanghai')),
'纽约': now.astimezone(ZoneInfo('America/New_York')),
'东京': now.astimezone(ZoneInfo('Asia/Tokyo'))
}
for tz, time in times.items():
print(f"{tz}: {time.strftime('%Y-%m-%d %H:%M:%S')}")
get_world_times()
输出示例:
UTC: 2025-10-29 07:30:45
北京: 2025-10-29 15:30:45
纽约: 2025-10-29 03:30:45
东京: 2025-10-29 16:30:45
七、总结与进阶建议
核心知识点回顾
基础对象:date/time/datetime
时间运算:timedelta实现加减
格式化:strftime输出,strptime解析
时区处理:优先使用zoneinfo(Python 3.9+)
进阶学习路径
阅读官方文档:datetime — 基本日期和时间类型
掌握第三方库:
pytz:旧版Python的时区处理
dateutil:高级时间计算(如相对时间)
实践项目:
开发一个带时区的日历应用
编写日志分析工具,统计各时段访问量
Python的datetime模块通过简洁的设计,覆盖了90%的时间处理需求。从日志记录到跨时区协作,从简单日期比较到复杂时间运算,掌握这些核心用法将显著提升你的开发效率。记住:处理时间时,永远要明确时区状态,优先使用aware对象——这是避免80%时间相关bug的金科玉律。