Python时间日期处理:datetime库完全指南
文章目录
- Python时间日期处理:datetime库完全指南
-
- 前言
- [一、`datetime` 模块核心类](#一、
datetime模块核心类) - 二、获取当前时间
- 三、创建指定日期时间
- [四、`strftime` 与 `strptime`:格式化与解析](#四、
strftime与strptime:格式化与解析) -
- [4.1 `strftime`:日期时间 → 字符串](#4.1
strftime:日期时间 → 字符串) - [4.2 `strptime`:字符串 → 日期时间](#4.2
strptime:字符串 → 日期时间) - [4.3 格式化代码速查表](#4.3 格式化代码速查表)
- [4.1 `strftime`:日期时间 → 字符串](#4.1
- 五、`timedelta`:日期计算
- [六、`time` 模块补充](#六、
time模块补充) - 七、实战案例
-
- [7.1 日期范围生成器](#7.1 日期范围生成器)
- [7.2 日志时间戳解析工具](#7.2 日志时间戳解析工具)
- [7.3 简易倒计时器](#7.3 简易倒计时器)
- [7.4 工作日计算器](#7.4 工作日计算器)
- 总结
- [✅ 亮点总结](#✅ 亮点总结)
- 适用场景
- 扩展方向
前言
时间日期处理是编程中最常见的需求之一------无论是记录日志时间戳、计算日期差、格式化输出,还是处理时区转换,都离不开时间和日期操作。Python提供了 datetime、time 和 calendar 三个核心模块来应对这些需求。
时间处理的常见坑 :很多开发者在处理时间时踩过"时区"的坑------服务器在UTC时区,数据库存的是本地时间,前端又显示用户时区,三种时间混在一起调试时让人抓狂。此外,strftime 和 strptime 的格式化代码容易混淆,闰年、月末、夏令时等边界条件也常常导致bug。本文将以 datetime 模块为主线,带你全面掌握Python时间日期处理的核心技巧,并特别强调那些容易出错的"暗坑"。
一、datetime 模块核心类
datetime 模块主要包含四个类:
python
from datetime import date, time, datetime, timedelta
# 1. date:只包含日期(年、月、日)
d = date(2024, 1, 15)
print(f"date: {d}") # 2024-01-15
# 2. time:只包含时间(时、分、秒、微秒)
t = time(14, 30, 45, 500000)
print(f"time: {t}") # 14:30:45.500000
# 3. datetime:日期 + 时间
dt = datetime(2024, 1, 15, 14, 30, 45)
print(f"datetime: {dt}") # 2024-01-15 14:30:45
# 4. timedelta:时间间隔(两个日期/时间之间的差值)
delta = timedelta(days=7, hours=3, minutes=30)
print(f"timedelta: {delta}") # 7 days, 3:30:00
二、获取当前时间
python
from datetime import datetime, date, time
# 当前日期时间
now = datetime.now()
print(f"当前日期时间: {now}")
# 当前日期
today = date.today()
print(f"当前日期: {today}")
# UTC时间(世界协调时)
utc_now = datetime.utcnow()
print(f"UTC时间: {utc_now}")
# 获取年月日时分秒等属性
print(f"年: {now.year}, 月: {now.month}, 日: {now.day}")
print(f"时: {now.hour}, 分: {now.minute}, 秒: {now.second}")
print(f"微秒: {now.microsecond}")
print(f"星期几 (0=周一): {now.weekday()}")
print(f"星期几 (1=周日): {now.isoweekday()}")
三、创建指定日期时间
python
from datetime import datetime, date, time
# 直接构造
dt1 = datetime(2025, 6, 1, 9, 0, 0)
print(dt1) # 2025-06-01 09:00:00
# 只提供日期部分
dt2 = datetime(2025, 12, 31)
print(dt2) # 2025-12-31 00:00:00
# 从时间戳创建
timestamp = 1705315200 # 2024-01-15 12:00:00 UTC
dt3 = datetime.fromtimestamp(timestamp)
print(f"从时间戳: {dt3}")
# 从ISO格式字符串创建
dt4 = datetime.fromisoformat("2024-06-15T09:30:00")
print(f"从ISO格式: {dt4}")
# 合并date和time
d = date(2025, 1, 1)
t = time(12, 30, 0)
dt5 = datetime.combine(d, t)
print(f"合并: {dt5}") # 2025-01-01 12:30:00
四、strftime 与 strptime:格式化与解析
这是实际开发中使用频率最高的两个方法。两者的方向相反 :strftime(format time)将 datetime 对象转换为字符串;strptime(parse time)将字符串解析为 datetime 对象。记住它们的区别有一个简单方法:f 代表 format(格式化输出),p 代表 parse(解析输入)。
4.1 strftime:日期时间 → 字符串
python
from datetime import datetime
now = datetime.now()
# 常用格式
print(now.strftime("%Y-%m-%d")) # 2024-01-15
print(now.strftime("%Y年%m月%d日")) # 2024年01月15日
print(now.strftime("%Y/%m/%d %H:%M:%S")) # 2024/01/15 14:30:45
print(now.strftime("%Y-%m-%d %I:%M %p")) # 2024-01-15 02:30 PM
print(now.strftime("%A, %B %d, %Y")) # Monday, January 15, 2024
print(now.strftime("%j")) # 015 (一年中的第几天)
print(now.strftime("%U")) # 03 (一年中的第几周)
4.2 strptime:字符串 → 日期时间
python
from datetime import datetime
# 解析各种格式的日期字符串
date_str1 = "2024-01-15"
dt1 = datetime.strptime(date_str1, "%Y-%m-%d")
print(dt1) # 2024-01-15 00:00:00
date_str2 = "2024年01月15日 14:30:45"
dt2 = datetime.strptime(date_str2, "%Y年%m月%d日 %H:%M:%S")
print(dt2) # 2024-01-15 14:30:45
date_str3 = "15/Jan/2024:14:30:45"
dt3 = datetime.strptime(date_str3, "%d/%b/%Y:%H:%M:%S")
print(dt3) # 2024-01-15 14:30:45
# 解析中文日期
date_str4 = "2024年1月15日"
dt4 = datetime.strptime(date_str4, "%Y年%m月%d日")
print(dt4)
4.3 格式化代码速查表
| 代码 | 含义 | 示例 |
|---|---|---|
%Y |
4位年份 | 2024 |
%m |
月份 (01-12) | 01 |
%d |
日期 (01-31) | 15 |
%H |
24小时 (00-23) | 14 |
%I |
12小时 (01-12) | 02 |
%M |
分钟 (00-59) | 30 |
%S |
秒 (00-59) | 45 |
%p |
AM/PM | PM |
%A |
完整星期名 | Monday |
%B |
完整月份名 | January |
%j |
一年中第几天 | 015 |
五、timedelta:日期计算
timedelta 是日期运算的核心工具,它表示两个日期/时间之间的差值 。你可以用它对日期进行加减操作,也可以计算两个日期之间的间隔。常见陷阱 :timedelta 只支持 days、seconds 和 microseconds,不支持 months 和 years------因为月份和年份的长度不是固定的(28-31天,365/366天)。如果需要按月或按年进行计算,推荐使用第三方库 dateutil 的 relativedelta。
python
from datetime import datetime, timedelta
now = datetime.now()
# 日期加减
tomorrow = now + timedelta(days=1)
yesterday = now - timedelta(days=1)
next_week = now + timedelta(weeks=1)
three_hours_later = now + timedelta(hours=3)
half_hour_ago = now - timedelta(minutes=30)
print(f"明天: {tomorrow.strftime('%Y-%m-%d')}")
print(f"昨天: {yesterday.strftime('%Y-%m-%d')}")
print(f"下周: {next_week.strftime('%Y-%m-%d')}")
print(f"3小时后: {three_hours_later.strftime('%H:%M')}")
print(f"半小时前: {half_hour_ago.strftime('%H:%M')}")
# 计算两个日期的差值
birthday = datetime(1995, 8, 22)
age_delta = now - birthday
print(f"自出生已过: {age_delta.days} 天")
print(f"约 {age_delta.days // 365} 年")
# 计算项目截止时间
deadline = datetime(2024, 12, 31, 23, 59, 59)
remaining = deadline - now
print(f"距离截止还有: {remaining.days}天 {remaining.seconds // 3600}小时")
六、time 模块补充
time 模块提供更底层的操作,主要处理时间戳 和程序休眠 。time 和 datetime 的分工是:time 模块处理底层的时间戳和系统时钟操作,datetime 模块提供高级的面向对象的日期时间接口。在实际开发中,你可以根据需求灵活选择:需要处理人类可读的日期和时间时用 datetime,需要操作时间戳或高精度计时时用 time。
python
import time
# 当前时间戳(自1970-01-01以来的秒数)
timestamp = time.time()
print(f"当前时间戳: {timestamp}")
# 休眠
print("等待3秒...")
time.sleep(3)
print("继续执行!")
# 时间戳 ↔ 结构化时间
local_time = time.localtime(timestamp)
print(f"本地时间: {time.strftime('%Y-%m-%d %H:%M:%S', local_time)}")
# UTC结构化时间
utc_time = time.gmtime(timestamp)
print(f"UTC时间: {time.strftime('%Y-%m-%d %H:%M:%S', utc_time)}")
# 结构化时间 → 时间戳
new_timestamp = time.mktime(local_time)
print(f"转回时间戳: {new_timestamp}")
# 性能计时(高精度)
start = time.perf_counter()
result = sum(range(1000000))
end = time.perf_counter()
print(f"计算耗时: {end - start:.6f}秒")
七、实战案例
理论知识最终要落地到实际场景。以下四个案例覆盖了时间日期处理最常见的工作场景------日期范围生成、日志时间戳解析、倒计时器和工作日计算。每个案例都可以作为模板代码直接使用。
7.1 日期范围生成器
python
from datetime import datetime, timedelta
def date_range(start_date, end_date):
"""生成两个日期之间的所有日期"""
current = start_date
while current <= end_date:
yield current
current += timedelta(days=1)
# 生成某月所有日期
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 31)
for d in date_range(start, end):
if d.weekday() < 5: # 仅工作日
weekday_name = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
print(f"{d.strftime('%Y-%m-%d')} {weekday_name[d.weekday()]}")
7.2 日志时间戳解析工具
python
from datetime import datetime
import re
LOG_PATTERNS = [
# 常见日志格式
r"\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}", # 2024-01-15 14:30:45
r"\d{2}/\w{3}/\d{4}:\d{2}:\d{2}:\d{2}", # 15/Jan/2024:14:30:45
r"\d{4}/\d{2}/\d{2} \d{2}:\d{2}:\d{2}", # 2024/01/15 14:30:45
]
def parse_log_timestamp(line):
"""尝试多种格式解析日志中的时间戳"""
for pattern in LOG_PATTERNS:
match = re.search(pattern, line)
if match:
ts_str = match.group()
# 尝试多种格式
for fmt in [
"%Y-%m-%d %H:%M:%S",
"%d/%b/%Y:%H:%M:%S",
"%Y/%m/%d %H:%M:%S",
]:
try:
return datetime.strptime(ts_str, fmt)
except ValueError:
continue
return None
# 测试
log_lines = [
'2024-01-15 14:30:45 INFO Server started',
'15/Jan/2024:14:31:20 ERROR Connection refused',
'2024/01/15 14:32:00 WARN Disk usage 90%',
]
for line in log_lines:
ts = parse_log_timestamp(line)
if ts:
print(f"{ts} -> {line}")
7.3 简易倒计时器
python
from datetime import datetime, timedelta
import time
def countdown(target_desc, target_datetime):
"""显示活动倒计时"""
while True:
now = datetime.now()
remaining = target_datetime - now
if remaining.total_seconds() <= 0:
print(f"\r{target_desc} 已到来!" + " " * 20)
break
days = remaining.days
hours, remainder = divmod(remaining.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
display = f"\r距离{target_desc}还有: {days}天 {hours:02d}时 {minutes:02d}分 {seconds:02d}秒"
print(display, end="", flush=True)
time.sleep(1)
print()
# 使用示例(设置一个未来时间点)
# target = datetime(2025, 1, 1, 0, 0, 0)
# countdown("2025年元旦", target)
print("倒计时器已就绪(取消注释上方代码运行)")
7.4 工作日计算器
python
from datetime import datetime, timedelta
def add_business_days(start_date, days):
"""在start_date基础上增加days个工作日"""
current = start_date
remaining = days
while remaining > 0:
current += timedelta(days=1)
# weekday(): 0=周一, 6=周日
if current.weekday() < 5: # 周一至周五
remaining -= 1
return current
def business_days_between(start, end):
"""计算两个日期之间的工作日天数"""
current = start
count = 0
while current <= end:
if current.weekday() < 5:
count += 1
current += timedelta(days=1)
return count
# 使用示例
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
deadline = add_business_days(today, 10)
print(f"今天: {today.strftime('%Y-%m-%d')}")
print(f"10个工作日后: {deadline.strftime('%Y-%m-%d')}")
start = datetime(2024, 1, 1)
end = datetime(2024, 1, 31)
working_days = business_days_between(start, end)
print(f"2024年1月工作日: {working_days}天")
总结
Python时间日期处理的核心要点:
| 需求 | 推荐方案 |
|---|---|
| 获取当前时间 | datetime.now() |
| 格式化输出 | 使用 strftime() |
| 解析日期字符串 | 使用 strptime() |
| 日期加减计算 | 使用 timedelta |
| 时间戳处理 | 使用 time.time() / datetime.fromtimestamp() |
| 程序休眠 | 使用 time.sleep() |
| 高精度计时 | 使用 time.perf_counter() |
掌握 datetime 模块能让你轻松应对90%以上的时间日期处理需求。下一篇我们将学习数据序列化(JSON与Pickle),看看如何持久化和传输Python对象。
✅ 亮点总结
- 清晰梳理
date、time、datetime、timedelta四大核心类的职责与关系 strftime()与strptime()的格式化速查表,覆盖日期时间字符串的转换全场景- 时间戳(timestamp)与时区(timezone)处理,解决跨时区应用的常见问题
- 实战案例:工作日计算器,演示 timedelta 累计、日期范围判断、节假日排除
适用场景
- 日志系统:为每条日志添加高精度时间戳,用于问题追踪和性能分析
- 定时任务:计算下一次执行的精确时间,如每日报表生成、定时数据清理
- 业务系统:计算合同期限、会员有效期、倒计时等时间相关的业务逻辑
扩展方向
- 学习
dateutil第三方库,支持更灵活的日期解析(如"下周三"、"3天后"等自然语言) - 探索
pytz库处理全球时区,结合datetime实现真正的跨时区时间计算 - 掌握
arrow/pendulum等新一代时间库,获得更人性化的 API 体验