目录

Python datetime 与时间处理

学习目标

  • 掌握 datetime 模块的核心类
  • 学会时间格式化与解析
  • 理解时区处理
  • 掌握时间计算和比较

1. datetime 核心类

from datetime import datetime, date, time, timedelta

# date - 日期(年月日)
d = date(2024, 1, 15)
print(d)          # 2024-01-15
print(d.year)     # 2024
print(d.month)    # 1
print(d.day)      # 15

# time - 时间(时分秒微秒)
t = time(14, 30, 45, 123456)
print(t)          # 14:30:45.123456
print(t.hour)     # 14
print(t.minute)   # 30

# datetime - 日期时间
dt = datetime(2024, 1, 15, 14, 30, 45)
print(dt)         # 2024-01-15 14:30:45

1.1 获取当前时间

from datetime import datetime, date

# 当前日期时间
now = datetime.now()
print(f"现在: {now}")

# 当前日期
today = date.today()
print(f"今天: {today}")

# 时间戳转 datetime
timestamp = 1705312245
dt = datetime.fromtimestamp(timestamp)
print(f"时间戳转换: {dt}")

# datetime 转时间戳
ts = datetime.now().timestamp()
print(f"当前时间戳: {ts}")

2. 格式化与解析

2.1 strftime - 格式化输出

from datetime import datetime

now = datetime.now()

# 常用格式
print(now.strftime("%Y-%m-%d"))           # 2024-01-15
print(now.strftime("%H:%M:%S"))           # 14:30:45
print(now.strftime("%Y-%m-%d %H:%M:%S"))  # 2024-01-15 14:30:45
print(now.strftime("%A, %B %d, %Y"))      # Monday, January 15, 2024

# 格式说明符
# %Y - 四位年份  %y - 两位年份
# %m - 月份(01-12)  %d - 日期(01-31)
# %H - 小时(00-23)  %M - 分钟(00-59)  %S - 秒(00-59)
# %A - 星期全称    %a - 星期缩写
# %B - 月份全称    %b - 月份缩写

2.2 strptime - 字符串解析

from datetime import datetime

# 解析日期字符串
date_str = "2024-01-15 14:30:00"
dt = datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S")
print(dt)  # 2024-01-15 14:30:00

# 解析不同格式
date_str2 = "15/01/2024"
dt2 = datetime.strptime(date_str2, "%d/%m/%Y")
print(dt2)  # 2024-01-15 00:00:00

# 解析带时区的 ISO 格式
dt3 = datetime.fromisoformat("2024-01-15T14:30:00")
print(dt3)

3. 时间计算

3.1 timedelta - 时间差

from datetime import datetime, timedelta

now = datetime.now()

# 加法
future = now + timedelta(days=7)
print(f"7天后: {future}")

# 减法
past = now - timedelta(hours=3)
print(f"3小时前: {past}")

# 时间差计算
dt1 = datetime(2024, 1, 15)
dt2 = datetime(2024, 2, 20)
diff = dt2 - dt1
print(f"相差: {diff.days} 天")

# timedelta 属性
print(f"总秒数: {diff.total_seconds()}")

# 复杂计算
print(now + timedelta(weeks=2, days=3, hours=5))

3.2 日期比较

from datetime import datetime

d1 = datetime(2024, 1, 15)
d2 = datetime(2024, 2, 20)

print(d1 < d2)    # True
print(d1 == d2)   # False
print(d1 != d2)   # True

# 判断日期范围
now = datetime.now()
start = datetime(2024, 1, 1)
end = datetime(2024, 12, 31)

if start <= now <= end:
    print("当前时间在范围内")

4. 时区处理

4.1 使用 datetime.timezone

from datetime import datetime, timezone, timedelta

# UTC 时间
utc_now = datetime.now(timezone.utc)
print(f"UTC: {utc_now}")

# 创建指定时区
china_tz = timezone(timedelta(hours=8))
beijing_time = datetime.now(china_tz)
print(f"北京时间: {beijing_time}")

# 转换时区
utc_dt = datetime(2024, 1, 15, 14, 30, tzinfo=timezone.utc)
local_dt = utc_dt.astimezone(china_tz)
print(f"UTC: {utc_dt}")
print(f"北京: {local_dt}")

4.2 使用 pytz(第三方库)

# pip install pytz
# import pytz
# 
# # 常见时区
# utc = pytz.utc
# beijing = pytz.timezone('Asia/Shanghai')
# new_york = pytz.timezone('America/New_York')
# 
# # 带时区的当前时间
# now = datetime.now(beijing)
# print(now)
# 
# # 转换时区
# ny_time = now.astimezone(new_york)
# print(ny_time)

4.3 使用 zoneinfo(Python 3.9+)

from datetime import datetime
from zoneinfo import ZoneInfo

# 创建带时区的时间
beijing = ZoneInfo("Asia/Shanghai")
ny = ZoneInfo("America/New_York")

dt = datetime(2024, 1, 15, 14, 30, tzinfo=beijing)
print(f"北京: {dt}")

# 转换到纽约
ny_dt = dt.astimezone(ny)
print(f"纽约: {ny_dt}")

5. 实用工具

5.1 日期范围生成

from datetime import datetime, timedelta

def date_range(start, end, step=1):
    """生成日期范围"""
    current = start
    while current <= end:
        yield current
        current += timedelta(days=step)

# 使用
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 10)

for d in date_range(start, end):
    print(d.strftime("%Y-%m-%d"))

5.2 人性化时间显示

from datetime import datetime, timedelta

def human_time(dt):
    """人性化时间显示"""
    now = datetime.now()
    diff = now - dt
    
    if diff < timedelta(minutes=1):
        return "刚刚"
    elif diff < timedelta(hours=1):
        return f"{diff.seconds // 60} 分钟前"
    elif diff < timedelta(days=1):
        return f"{diff.seconds // 3600} 小时前"
    elif diff < timedelta(days=7):
        return f"{diff.days} 天前"
    else:
        return dt.strftime("%Y-%m-%d")

# 测试
print(human_time(datetime.now() - timedelta(minutes=5)))   # 5 分钟前
print(human_time(datetime.now() - timedelta(hours=3)))     # 3 小时前
print(human_time(datetime.now() - timedelta(days=2)))      # 2 天前
print(human_time(datetime(2023, 1, 1)))                     # 2023-01-01

5.3 日历操作

import calendar

# 打印月历
print(calendar.month(2024, 1))

# 判断闰年
print(calendar.isleap(2024))  # True
print(calendar.isleap(2023))  # False

# 星期几(0=周一)
print(calendar.weekday(2024, 1, 15))  # 0(周一)

# 月份天数
print(calendar.monthrange(2024, 2))  # (3, 29) - 周四开始,29天

# 迭代月份
cal = calendar.Calendar()
for week in cal.monthdayscalendar(2024, 1):
    print(week)

6. 时间性能测量

import time
from datetime import datetime

# 简单计时
start = time.time()
# ... 执行代码 ...
time.sleep(0.1)
elapsed = time.time() - start
print(f"耗时: {elapsed:.4f} 秒")

# 更精确的时间
start = time.perf_counter()
# ... 执行代码 ...
time.sleep(0.1)
elapsed = time.perf_counter() - start
print(f"精确耗时: {elapsed:.6f} 秒")

# 程序运行时间
print(f"程序运行时间: {time.process_time():.4f} 秒")

本节小结

  • datetimedatetimedatetime 三个核心类
  • 格式化strftime(格式化)、strptime(解析)
  • 计算timedelta 进行日期时间加减
  • 时区timezonezoneinfo(3.9+)、pytz
  • 工具calendar 模块处理日历相关操作
  • 性能time.perf_counter() 精确计时

练习

  1. 编写函数,计算两个日期之间的工作日天数(排除周末)
  2. 实现一个倒计时器,接受目标时间并每秒打印剩余时间
  3. 编写日期解析函数,支持多种常见格式自动识别
  4. 创建一个定时任务调度器,支持按天/周/月执行回调