一、time/datetime 模块是什么
time和datetime是 Python 标准库中专门用于时间处理的核心模块,无需额外安装,直接导入即可使用,二者分工互补,覆盖了从底层时间操作到高级日期计算的所有时间处理场景。
time模块:偏底层实现,基于 Unix 时间戳封装基础功能,主打简单计时、延迟操作、时间戳与基础时间格式转换;datetime模块:面向对象的封装设计,提供了date/time/datetime/timedelta等类,主打复杂日期计算、灵活的时间格式转换、日期字段精准操作,是实际开发中的首选。
1.1 为什么需要它们?
表格
| 场景 | 解决方案 |
|---|---|
| 获取当前时间戳 / 本地时间 | time.time() / datetime.now() |
| 程序计时 / 延迟执行 | time.time() 计时 / time.sleep() 延迟 |
| 时间戳与字符串时间互转 | time.strftime()/datetime.strptime() |
| 日期加减 / 时间差计算 | datetime.timedelta() |
| 提取年 / 月 / 日 / 时等时间字段 | datetime对象直接属性访问 |
1.2 快速上手
python
运行
import time
from datetime import datetime, timedelta
# 查看模块所有功能
print(dir(time))
print(dir(datetime))
# 最简单的时间获取
print("当前时间戳:", time.time())
print("当前本地时间:", datetime.now())
二、核心基础:Unix 时间戳操作
Unix 时间戳是 time/datetime 模块的底层核心,是跨时区时间处理、时间计算的基础,所有高级时间操作最终都可映射到时间戳的处理。
2.1 基本用法
python
运行
import time
from datetime import datetime
# 1. time模块获取时间戳(float类型,含微秒,最常用)
ts1 = time.time()
print(f"time模块获取:{ts1}") # 示例:1712000000.123456
# 2. datetime模块获取时间戳
ts2 = datetime.timestamp(datetime.now())
print(f"datetime模块获取:{ts2}") # 与ts1结果一致
# 3. 时间戳转整数(忽略微秒,适合数据库存储)
ts_int = int(time.time())
print(f"整数时间戳:{ts_int}") # 示例:1712000000
2.2 时间戳转本地时间
python
运行
import time
from datetime import datetime
ts = 1712000000
# 1. time模块:时间戳 → 结构化时间(struct_time)
struct_time = time.localtime(ts)
print(f"结构化时间:{struct_time}") # 包含年、月、日等所有字段
# 提取结构化时间字段
print(f"年份:{struct_time.tm_year},小时:{struct_time.tm_hour}")
# 2. datetime模块:时间戳 → datetime对象(推荐,操作更灵活)
dt = datetime.fromtimestamp(ts)
print(f"datetime对象:{dt}") # 示例:2026-04-01 08:26:40
# 提取datetime对象字段
print(f"年份:{dt.year},小时:{dt.hour}")
2.3 时间戳转 UTC 时间
python
运行
import time
from datetime import datetime
ts = 1712000000
# 1. time模块:时间戳 → UTC结构化时间
utc_struct = time.gmtime(ts)
print(f"UTC结构化时间:{utc_struct}")
# 2. datetime模块:时间戳 → UTC datetime对象
utc_dt = datetime.utcfromtimestamp(ts)
print(f"UTC datetime对象:{utc_dt}") # 比本地时间晚8小时(北京时间)
三、时间格式转换:结构化 / 对象 → 字符串
开发中常需要将计算机可识别的结构化时间 /.datetime 对象 ,转换为人类易读的字符串时间 (如2026-04-01 10:30:00),核心是掌握格式化符号。
3.1 常用格式化符号(必记)
表格
| 符号 | 含义 | 示例 |
|---|---|---|
| %Y | 4 位年份 | 2026 |
| %m | 2 位月份 | 04(4 月) |
| %d | 2 位日期 | 01 |
| %H | 24 小时制小时 | 10(上午 10 点)/22(晚上 10 点) |
| %M | 2 位分钟 | 30 |
| %S | 2 位秒 | 59 |
| %w | 星期(0 = 周日,1 = 周一) | 2(周二) |
3.2 time 模块:结构化时间 → 字符串
python
运行
import time
# 获取当前结构化时间
local_struct = time.localtime()
# 自定义格式转换
time_str1 = time.strftime("%Y-%m-%d", local_struct) # 仅日期
time_str2 = time.strftime("%Y-%m-%d %H:%M:%S", local_struct) # 日期+时间
time_str3 = time.strftime("%Y年%m月%d日 %H时%M分", local_struct) # 中文格式
print(time_str1, time_str2, time_str3)
# 快捷获取默认格式字符串时间
default_str = time.ctime()
print(f"默认格式:{default_str}") # 示例:Wed Apr 1 10:30:00 2026
3.3 datetime 模块:datetime 对象 → 字符串(推荐)
python
运行
from datetime import datetime
# 获取当前datetime对象
now = datetime.now()
# 自定义格式转换(直接调用对象方法,更简洁)
dt_str1 = now.strftime("%Y-%m-%d")
dt_str2 = now.strftime("%Y-%m-%d %H:%M:%S")
print(dt_str1, dt_str2)
# 特殊格式:ISO标准时间
iso_str = now.isoformat()
print(f"ISO格式:{iso_str}") # 示例:2026-04-01T10:30:00.123456
四、时间格式转换:字符串 → 结构化 / 对象
开发中也常需要将用户输入、接口传参的字符串时间 ,转换为计算机可处理的结构化时间 /datetime 对象 ,核心要求:格式化符号必须与字符串格式完全匹配。
4.1 time 模块:字符串 → 结构化时间
python
运行
import time
# 待转换字符串时间
time_str1 = "2026-04-01 10:30:00"
time_str2 = "2026年04月01日"
# 转换:格式与字符串完全匹配
struct1 = time.strptime(time_str1, "%Y-%m-%d %H:%M:%S")
struct2 = time.strptime(time_str2, "%Y年%m月%d日")
print(f"字符串转结构化时间1:{struct1}")
print(f"字符串转结构化时间2:{struct2}")
# 结构化时间可再转时间戳
ts = time.mktime(struct1)
print(f"转换为时间戳:{ts}")
4.2 datetime 模块:字符串 → datetime 对象(推荐)
python
运行
from datetime import datetime
# 待转换字符串时间
time_str = "2026-04-01 10:30:00"
# 转换:格式与字符串完全匹配
dt = datetime.strptime(time_str, "%Y-%m-%d %H:%M:%S")
print(f"字符串转datetime对象:{dt}")
# 直接操作转换后的对象(提取字段、计算)
print(f"提取月份:{dt.month}")
print(f"提取星期:{dt.weekday()}") # 0=周一,6=周日(与time模块的%w不同,注意区分)
4.3 常见错误避坑
python
运行
from datetime import datetime
# 错误示例:格式符号与字符串格式不匹配(字符串是-,格式是/)
# dt = datetime.strptime("2026-04-01", "%Y/%m/%d") # 会抛出ValueError
# 正确示例:完全匹配
dt = datetime.strptime("2026-04-01", "%Y-%m-%d")
五、高级日期计算:timedelta 类
datetime模块的timedelta类是处理日期加减、时间差计算 的核心,支持天、小时、分钟、秒等单位,可直接与datetime对象进行算术运算,是datetime模块优于time模块的核心特性。
5.1 基本用法
python
运行
from datetime import datetime, timedelta
# 获取当前时间
now = datetime.now()
print(f"当前时间:{now.strftime('%Y-%m-%d %H:%M:%S')}")
# 1. 创建时间差对象(参数:days, hours, minutes, seconds, microseconds)
delta1 = timedelta(days=1) # 1天
delta2 = timedelta(hours=2, minutes=30) # 2小时30分钟
delta3 = timedelta(days=-1) # 负数值:代表过去的时间
# 2. datetime对象 + 时间差 → 未来时间
tomorrow = now + delta1
next_time = now + delta2
print(f"明天此时:{tomorrow.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"2小时30分钟后:{next_time.strftime('%Y-%m-%d %H:%M:%S')}")
# 3. datetime对象 - 时间差 → 过去时间
yesterday = now + delta3 # 等价于 now - timedelta(days=1)
half_hour_ago = now - timedelta(minutes=30)
print(f"昨天此时:{yesterday.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"30分钟前:{half_hour_ago.strftime('%Y-%m-%d %H:%M:%S')}")
5.2 时间差计算
python
运行
from datetime import datetime
# 两个datetime对象相减 → 得到timedelta对象
dt1 = datetime(2026, 4, 1, 10, 0, 0)
dt2 = datetime(2026, 4, 5, 12, 30, 0)
diff = dt2 - dt1
print(f"时间差:{diff}") # 示例:4 days, 2:30:00
# 提取时间差的具体信息
print(f"相差天数:{diff.days}")
print(f"相差总秒数:{diff.total_seconds()}") # 含小时、分钟、秒的总秒数
print(f"相差秒数(仅当天):{diff.seconds}") # 不含天数,范围0-86399
5.3 实战:计算指定日期的前后 N 天
python
运行
from datetime import datetime, timedelta
def get_date_by_days(target_date_str, days):
"""
计算指定日期的前后N天
:param target_date_str: 目标日期字符串,格式%Y-%m-%d
:param days: 偏移天数,正数=未来,负数=过去
:return: 偏移后的日期字符串
"""
target_dt = datetime.strptime(target_date_str, "%Y-%m-%d")
result_dt = target_dt + timedelta(days=days)
return result_dt.strftime("%Y-%m-%d")
# 测试
print(get_date_by_days("2026-04-01", 7)) # 7天后:2026-04-08
print(get_date_by_days("2026-04-01", -3)) # 3天前:2026-03-29
六、time 模块专属:计时与延迟操作
time模块在程序计时、主动延迟执行场景下更简洁高效,是开发中高频使用的功能,如测试代码执行效率、爬虫反爬延迟、定时等待等。
6.1 程序精准计时
python
运行
import time
# 记录开始时间
start_ts = time.time()
# 模拟耗时操作(如循环、数据处理、接口请求)
total = 0
for i in range(1000000):
total += i
# 记录结束时间
end_ts = time.time()
# 计算执行耗时(保留4位小数,更精准)
cost = end_ts - start_ts
print(f"代码执行耗时:{cost:.4f} 秒")
print(f"计算结果:{total}")
6.2 程序延迟执行(sleep)
python
运行
import time
print("程序开始执行...")
# 延迟指定秒数,支持小数(如0.5=500毫秒)
time.sleep(2) # 休眠2秒
print("2秒后,继续执行后续逻辑...")
# 实战:循环中延迟(如爬虫每隔1秒请求一次)
for i in range(3):
print(f"执行第{i+1}次操作")
time.sleep(1) # 每次操作间隔1秒
6.3 高精度计时(perf_counter)
对于微秒级高精度计时 ,使用time.perf_counter(),比time.time()更精准,适合测试超短代码的执行效率。
python
运行
import time
start = time.perf_counter()
# 超短耗时操作
[i ** 2 for i in range(1000)]
end = time.perf_counter()
print(f"高精度计时耗时:{end - start:.8f} 秒")
七、专属类操作:date /time 类
datetime模块还提供了仅处理日期 的date类和仅处理时间 的time类,适合场景单一的时间处理需求,操作与datetime类一致,更轻量。
7.1 date 类:仅处理年 / 月 / 日
python
运行
from datetime import date, timedelta
# 1. 获取当前日期
today = date.today()
print(f"当前日期:{today}") # 示例:2026-04-01
# 2. 手动创建日期对象
custom_date = date(2026, 4, 1)
print(f"自定义日期:{custom_date}")
# 3. 提取日期字段
print(f"年:{today.year},月:{today.month},日:{today.day}")
# 4. 日期加减
tomorrow = today + timedelta(days=1)
print(f"明天日期:{tomorrow}")
# 5. 日期格式转换
date_str = today.strftime("%Y年%m月%d日")
print(f"日期转字符串:{date_str}")
# 字符串转日期
str2date = date.fromisoformat("2026-04-01")
print(f"字符串转日期:{str2date}")
7.2 time 类:仅处理时 / 分 / 秒 / 微秒
python
运行
from datetime import time, timedelta
# 1. 手动创建时间对象(时、分为必填,秒、微秒可选)
t1 = time(10, 30, 0)
t2 = time(14, 20, 59, 123456)
print(f"时间1:{t1}") # 10:30:00
print(f"时间2:{t2}") # 14:20:59.123456
# 2. 提取时间字段
print(f"小时:{t1.hour},分钟:{t1.minute},秒:{t1.second}")
# 3. 时间格式转换
time_str = t1.strftime("%H:%M:%S")
print(f"时间转字符串:{time_str}")
八、时区处理:基础与简易兼容
Python 原生 time/datetime 模块对时区的支持较弱,默认处理的是本地时间 和UTC 时间,开发中跨时区业务需注意时区转换,以下是基础的时区兼容操作。
8.1 本地时间与 UTC 时间互转
python
运行
from datetime import datetime, timedelta
# 1. 获取本地时间和UTC时间
local_now = datetime.now()
utc_now = datetime.utcnow()
print(f"本地时间:{local_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"UTC时间:{utc_now.strftime('%Y-%m-%d %H:%M:%S')}")
# 2. UTC时间 → 北京时间(UTC+8)
bj_now = utc_now + timedelta(hours=8)
print(f"UTC转北京时间:{bj_now.strftime('%Y-%m-%d %H:%M:%S')}")
# 3. 本地时间 → UTC时间
local2utc = local_now - timedelta(hours=8)
print(f"本地时间转UTC:{local2utc.strftime('%Y-%m-%d %H:%M:%S')}")
8.2 实战:统一存储 UTC 时间(推荐)
跨时区业务中,数据库统一存储 UTC 时间,展示层转换为本地时间是最佳实践,避免时区混乱。
python
运行
from datetime import datetime, timedelta
# 1. 写入数据库:存储UTC时间戳/UTC datetime
utc_ts = datetime.timestamp(datetime.utcnow())
print(f"写入数据库的UTC时间戳:{utc_ts}")
# 2. 读取展示:UTC时间戳 → 本地时间
local_dt = datetime.fromtimestamp(utc_ts)
print(f"展示给用户的本地时间:{local_dt.strftime('%Y-%m-%d %H:%M:%S')}")
8.3 第三方时区库:pytz(拓展)
原生模块功能有限,复杂时区(如夏令时、不同时区偏移)推荐使用第三方库pytz,需提前安装:pip install pytz。
python
运行
from datetime import datetime
import pytz
# 1. 获取指定时区的时间
bj_tz = pytz.timezone("Asia/Shanghai")
ny_tz = pytz.timezone("America/New_York")
bj_now = datetime.now(bj_tz)
ny_now = datetime.now(ny_tz)
print(f"北京时间:{bj_now.strftime('%Y-%m-%d %H:%M:%S')}")
print(f"纽约时间:{ny_now.strftime('%Y-%m-%d %H:%M:%S')}")
# 2. 时区转换
bj2ny = bj_now.astimezone(ny_tz)
print(f"北京时间转纽约时间:{bj2ny.strftime('%Y-%m-%d %H:%M:%S')}")
九、完整实战案例
案例 1:日志时间格式化工具
开发中自定义日志,需要将时间格式化为固定字符串,包含毫秒,提升日志可读性。
python
运行
import time
from datetime import datetime
def get_log_time(with_ms=True):
"""
获取日志专用时间字符串
:param with_ms: 是否包含毫秒
:return: 格式化时间字符串
"""
if with_ms:
# 包含毫秒:%Y-%m-%d %H:%M:%S.%f(%f为微秒,取前3位为毫秒)
return datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
else:
# 不包含毫秒
return datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# 测试使用
if __name__ == "__main__":
print(f"日志时间(含毫秒):{get_log_time()}") # 示例:2026-04-01 10:30:00.123
print(f"日志时间(无毫秒):{get_log_time(with_ms=False)}") # 示例:2026-04-01 10:30:00
# 模拟日志输出
print(f"[{get_log_time()}] 程序启动成功")
print(f"[{get_log_time()}] 执行数据处理操作")
案例 2:倒计时工具
实现一个简单的倒计时功能,指定目标时间,实时输出剩余时间。
python
运行
from datetime import datetime, timedelta
import time
def count_down(target_time_str):
"""
倒计时功能
:param target_time_str: 目标时间字符串,格式%Y-%m-%d %H:%M:%S
"""
target_dt = datetime.strptime(target_time_str, "%Y-%m-%d %H:%M:%S")
print(f"倒计时开始,目标时间:{target_time_str}")
while True:
now = datetime.now()
# 计算剩余时间
diff = target_dt - now
if diff.total_seconds() <= 0:
print("倒计时结束!")
break
# 提取剩余时、分、秒
hours = diff.seconds // 3600
minutes = (diff.seconds % 3600) // 60
seconds = diff.seconds % 60
print(f"剩余时间:{hours:02d}:{minutes:02d}:{seconds:02d}", end="\r")
time.sleep(1)
# 测试:倒计时到2026-04-01 12:00:00
if __name__ == "__main__":
count_down("2026-04-01 12:00:00")
案例 3:时间范围数据筛选
根据指定的开始时间和结束时间,筛选列表中符合时间范围的数据(模拟数据库数据筛选)。
python
运行
from datetime import datetime
# 模拟数据:列表中每个元素包含id和create_time(字符串格式)
data_list = [
{"id": 1, "create_time": "2026-04-01 09:00:00"},
{"id": 2, "create_time": "2026-04-01 10:30:00"},
{"id": 3, "create_time": "2026-04-01 11:00:00"},
{"id": 4, "create_time": "2026-04-01 12:00:00"},
{"id": 5, "create_time": "2026-04-01 13:00:00"},
]
def filter_data_by_time(data, start_str, end_str):
"""
按时间范围筛选数据
:param data: 原始数据列表
:param start_str: 开始时间字符串%Y-%m-%d %H:%M:%S
:param end_str: 结束时间字符串%Y-%m-%d %H:%M:%S
:return: 筛选后的列表
"""
start_dt = datetime.strptime(start_str, "%Y-%m-%d %H:%M:%S")
end_dt = datetime.strptime(end_str, "%Y-%m-%d %H:%M:%S")
filtered = []
for item in data:
item_dt = datetime.strptime(item["create_time"], "%Y-%m-%d %H:%M:%S")
if start_dt <= item_dt <= end_dt:
filtered.append(item)
return filtered
# 测试:筛选2026-04-01 10:00:00 到 2026-04-01 12:00:00的数据
if __name__ == "__main__":
result = filter_data_by_time(data_list, "2026-04-01 10:00:00", "2026-04-01 12:00:00")
print("筛选后的结果:")
for item in result:
print(item)
十、常见问题与避坑
10.1 六大常见坑点
表格
| 坑点 | 说明 | 解决方案 |
|---|---|---|
| 格式化符号不匹配 | 字符串转时间时,格式符号与字符串格式不一致,抛出 ValueError | 严格保证格式符号与字符串的分隔符、位数完全匹配 |
| 星期标识混淆 | time 模块 % w(0 = 周日),datetime.weekday ()(0 = 周一) | 记清两种星期的标识规则,按需使用 |
| 时区处理混乱 | 直接将 UTC 时间作为本地时间展示,导致时间偏差 | 数据库统一存 UTC 时间,展示层转换为本地时间 |
| sleep 传入非数字 | time.sleep () 传入字符串 / 其他类型,抛出 TypeError | 确保 sleep 参数为 int/float 类型 |
| 微秒处理忽略 | 时间戳转字符串时,忽略微秒导致精度丢失 | 需高精度时使用 % f 格式化符号,或保留原始时间戳 |
| 日期计算用 time 模块 | 用 time 模块做日期加减,代码繁琐且易出错 | 日期计算优先使用 datetime.timedelta 类 |
10.2 最佳实践
python
运行
from datetime import datetime, timedelta
import time
# 1. 安全的字符串转时间(带异常捕获)
def safe_str2dt(time_str, fmt="%Y-%m-%d %H:%M:%S"):
try:
return datetime.strptime(time_str, fmt)
except ValueError:
print(f"时间格式错误,要求格式:{fmt}")
return None
# 2. 统一时间戳获取(兼容Python所有版本)
def get_uniq_ts():
return int(time.time() * 1000) # 毫秒级时间戳,避免重复
# 3. 时间差计算(友好展示)
def get_friendly_diff(dt1, dt2):
diff = abs(dt1 - dt2)
days = diff.days
hours = diff.seconds // 3600
minutes = (diff.seconds % 3600) // 60
seconds = diff.seconds % 60
return f"{days}天{hours}小时{minutes}分钟{seconds}秒"
# 测试最佳实践
if __name__ == "__main__":
print(safe_str2dt("2026-04-01 10:30:00"))
print(f"毫秒级时间戳:{get_uniq_ts()}")
print(get_friendly_diff(datetime(2026,4,1), datetime(2026,4,5,2,30)))
十一、速查表
11.1 常用函数 / 方法速查
表格
| 模块 / 类 | 方法 / 函数 | 用途 | 示例 |
|---|---|---|---|
| time | time() | 获取当前时间戳 | time.time() |
| time | localtime(ts) | 时间戳转本地结构化时间 | time.localtime(1712000000) |
| time | strftime(fmt, struct) | 结构化时间转字符串 | time.strftime("%Y-%m-%d", struct) |
| time | strptime(str, fmt) | 字符串转结构化时间 | time.strptime("2026-04-01", "%Y-%m-%d") |
| time | sleep(sec) | 程序延迟执行 | time.sleep(2) |
| datetime | now() | 获取当前本地 datetime 对象 | datetime.now() |
| datetime | utcnow() | 获取当前 UTC datetime 对象 | datetime.utcnow() |
| datetime | timestamp(dt) | datetime 对象转时间戳 | datetime.timestamp(dt) |
| datetime | fromtimestamp(ts) | 时间戳转 datetime 对象 | datetime.fromtimestamp(1712000000) |
| datetime | strftime(fmt) | datetime 对象转字符串 | dt.strftime("%Y-%m-%d %H:%M:%S") |
| datetime | strptime(str, fmt) | 字符串转 datetime 对象 | datetime.strptime(str, fmt) |
| timedelta | timedelta(days=1) | 创建时间差对象 | timedelta(hours=2, minutes=30) |
| date | today() | 获取当前日期 | date.today() |
11.2 常用格式化符号速查
表格
| 符号 | 含义 | 示例 |
|---|---|---|
| %Y | 4 位年份 | 2026 |
| %m | 2 位月份 | 01-12 |
| %d | 2 位日期 | 01-31 |
| %H | 24 小时制小时 | 00-23 |
| %M | 2 位分钟 | 00-59 |
| %S | 2 位秒 | 00-59 |
| %f | 6 位微秒 | 123456 |
| %w | 星期(0 = 周日,1 = 周一) | 0-6 |
11.3 核心属性速查
表格
| 对象类型 | 属性 | 用途 | 示例 |
|---|---|---|---|
| struct_time | tm_year/tm_mon/tm_mday | 年 / 月 / 日 | struct.tm_year |
| struct_time | tm_hour/tm_min/tm_sec | 时 / 分 / 秒 | struct.tm_hour |
| datetime/date | year/month/day | 年 / 月 / 日 | dt.year |
| datetime/time | hour/minute/second | 时 / 分 / 秒 | dt.hour |
| timedelta | days | 相差天数 | diff.days |
| timedelta | total_seconds() | 相差总秒数 | diff.total_seconds() |
十二、总结
核心要点
time模块偏底层,主打时间戳操作、计时、延迟,适合简单的时间处理场景;datetime模块面向对象,主打日期计算、灵活的格式转换、字段提取 ,通过timedelta实现便捷的日期加减,是开发中的首选;- 时间格式转换的核心是格式化符号,字符串与格式必须完全匹配,否则会抛出异常;
- 跨时区业务的最佳实践是数据库存储 UTC 时间,展示层转换为本地时间 ,复杂时区使用
pytz库; - 避免 90% 的时间处理 bug,只需掌握:时间戳的底层逻辑、格式化符号的正确使用、时区的基本转换。
学习路径
- 入门 :掌握时间戳获取、基础格式转换(字符串↔时间对象)、
time.sleep()延迟; - 进阶 :掌握
timedelta日期计算、date/time类的使用、日志时间格式化; - 精通:掌握跨时区处理、高精度计时、时间范围筛选等实战场景,能规避所有常见坑点。
一句话总结
time是 Python 时间处理的基础,datetime是 Python 时间处理的利器,二者结合,能解决所有 Python 开发中的时间处理需求。