Python datetime模块:时间处理的瑞士军刀

147 阅读9分钟

在Python编程中,时间处理是绕不开的核心需求。无论是记录日志、计算程序运行时长,还是处理时区转换,都需要精准的时间操作工具。Python标准库中的datetime模块就像一把瑞士军刀,用简洁的API解决了90%的时间处理场景。本文将通过实际代码示例,带你掌握这个模块的核心用法。

免费python编程教程:pan.quark.cn/s/2c17aed36…

一、基础时间对象:构建时间数据的基石

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对象:明确时区信息(需配合pytzzoneinfo

    # 创建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))  # 输出:True2024是闰年)

转存失败,建议直接上传图片文件

问题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

转存失败,建议直接上传图片文件

七、总结与进阶建议

核心知识点回顾

  1. 基础对象date/time/datetime
  2. 时间运算timedelta实现加减
  3. 格式化strftime输出,strptime解析
  4. 时区处理:优先使用zoneinfo(Python 3.9+)

进阶学习路径

  1. 阅读官方文档:datetime — 基本日期和时间类型

  2. 掌握第三方库:

    • pytz:旧版Python的时区处理
    • dateutil:高级时间计算(如相对时间)
  3. 实践项目:

    • 开发一个带时区的日历应用
    • 编写日志分析工具,统计各时段访问量

Python的datetime模块通过简洁的设计,覆盖了90%的时间处理需求。从日志记录到跨时区协作,从简单日期比较到复杂时间运算,掌握这些核心用法将显著提升你的开发效率。记住:处理时间时,永远要明确时区状态,优先使用aware对象——这是避免80%时间相关bug的金科玉律。