time 模块
学习层次
标准库不要求逐项背诵。先掌握导入、查阅和根据任务选择模块的方法;每章的常用操作需要能复现,进阶参数在项目用到时回查。
面对“记录任务时间、暂停程序或统计耗时”这类需求,应该选哪个时间接口?程序经常需要处理与时间有关的任务,例如:
- 获取当前时刻
- 暂停一段时间
- 统计代码运行耗时
- 把时间转换成适合显示的字符串
- 把字符串解析成程序能够处理的时间
Python 标准库中的 time 模块提供了这些基础能力。本章重点认识三种时间表示,并学习它们之间的转换关系。
| 表示方式 | 示例 | 适合的场景 |
|---|---|---|
| 时间戳 | 1757640600.0 | 保存时刻、比较先后、进行计算 |
| 结构化时间 | time.struct_time(...) | 读取年、月、日、时、分、秒等字段 |
| 格式化字符串 | "2026-09-12 09:30:00" | 显示时间、接收文本输入 |
时间戳适合程序计算,结构化时间适合拆分字段,字符串适合展示和输入。
当前时间戳
如果需要保存一个可以比较和计算的时刻,先使用时间戳表示当前时间。
time.time() 返回当前时间戳,结果通常是一个浮点数:
import time
now_timestamp = time.time()
print(now_timestamp)时间戳表示从 1970-01-01 00:00:00 UTC 到某个时刻经过的秒数。小数部分表示不足一秒的时间。
如果某个系统要求整数秒,可以使用 int() 去掉小数部分:
seconds = int(time.time())
print(seconds)有些接口使用毫秒值,可以在秒级时间戳的基础上换算:
milliseconds = int(time.time() * 1000)
print(milliseconds)这里得到的是“秒”和“毫秒”两种单位。不要把它们简单理解成永远固定的“10 位时间戳”和“13 位时间戳”,位数会随时间范围发生变化。
程序暂停
如果任务需要等待一段时间,或循环需要控制执行频率,可以使用 sleep() 暂停当前程序。
time.sleep(seconds) 会让当前程序暂停指定秒数:
import time
print("准备开始")
time.sleep(2)
print("暂停结束")参数可以是整数,也可以是浮点数:
time.sleep(0.5)sleep() 适合模拟耗时任务、控制循环频率或等待一段时间。它表示程序至少暂停相应时长,实际恢复时间还会受到操作系统调度影响。
运行耗时测量
获取当前时刻和统计运行耗时是两个不同的需求。
time.time() 表示系统当前时间,系统时钟可能被人工调整或自动校准。因此,统计一段代码经过了多久时,优先使用 time.perf_counter():
import time
start = time.perf_counter()
time.sleep(1)
end = time.perf_counter()
elapsed = end - start
print(f"运行耗时:{elapsed:.2f} 秒")一次可能的运行结果:
运行耗时:1.00 秒perf_counter() 使用适合短时间测量的高精度计时器,并且不会因为系统时间被调快或调慢而倒退。它返回的数值本身没有日期含义,主要用于计算两次调用之间的差值。
| 需求 | 推荐工具 |
|---|---|
| 获取当前时刻 | time.time() |
| 统计运行耗时 | time.perf_counter() |
| 暂停程序 | time.sleep() |
时间戳与结构化时间
时间戳适合保存和计算,但不能直接看出年月日。localtime() 和 gmtime() 可以把时间戳转换成结构化时间。
本地时间:time.localtime()
time.localtime() 返回当前本地时间:
import time
local_time = time.localtime()
print(local_time)也可以传入指定时间戳:
local_time = time.localtime(0)
print(local_time)localtime() 的结果会受到计算机系统时区影响。同一个时间戳,在东八区和零时区会显示成不同的本地时间。
UTC 时间:time.gmtime()
time.gmtime() 把时间戳转换为 UTC 结构化时间:
import time
utc_time = time.gmtime(0)
print(utc_time)UTC 不使用计算机的本地时区。对于时间戳 0,结果对应 1970-01-01 00:00:00 UTC。
struct_time 字段
localtime() 和 gmtime() 都会返回 struct_time 对象。它包含 9 个字段,可以通过属性名或下标读取:
import time
current = time.localtime()
print(current.tm_year)
print(current.tm_mon)
print(current.tm_mday)
print(current[3])常用字段如下:
| 属性 | 含义 | 常见范围 |
|---|---|---|
tm_year | 年 | 完整年份 |
tm_mon | 月 | 1~12 |
tm_mday | 日 | 1~31 |
tm_hour | 时 | 0~23 |
tm_min | 分 | 0~59 |
tm_sec | 秒 | 通常为 0~59 |
tm_wday | 星期 | 0~6,0 表示周一 |
tm_yday | 一年中的第几天 | 1~366 |
tm_isdst | 夏令时状态 | -1、0 或 1 |
struct_time 与元组相似,但内容是只读的,不能直接修改:
current.tm_year = 2030运行后会抛出 AttributeError。
结构化时间与时间戳
time.mktime() 把表示本地时间的 struct_time 或时间元组转换成时间戳:
import time
local_time = time.localtime()
timestamp = time.mktime(local_time)
print(timestamp)localtime() 和 mktime() 可以看作一组方向相反的本地时间转换:
时间戳 ──localtime()──> 本地结构化时间
时间戳 <───mktime()──── 本地结构化时间mktime() 按本地时间解释传入的内容,不能把 UTC 结构化时间直接交给它并期待得到正确结果。如果确实需要把 UTC 结构化时间转回时间戳,可以使用 calendar.timegm():
import calendar
import time
utc_time = time.gmtime(0)
timestamp = calendar.timegm(utc_time)
print(timestamp)运行结果:
0时间格式化
快速格式化:time.ctime()
time.ctime() 可以把时间戳转换成本地时间字符串:
import time
print(time.ctime())
print(time.ctime(0))不传参数时,它使用当前时间戳。输出内容会受到操作系统、时区和语言环境影响,因此适合快速查看,不适合要求固定格式的输出。
自定义格式化:time.strftime()
time.strftime(format, struct_time) 按指定格式把结构化时间转换成字符串:
import time
local_time = time.localtime()
text = time.strftime("%Y-%m-%d %H:%M:%S", local_time)
print(text)如果省略第二个参数,strftime() 默认使用当前本地时间:
text = time.strftime("%Y/%m/%d %H:%M")
print(text)本章常用的格式符如下:
| 格式符 | 含义 | 示例 |
|---|---|---|
%Y | 四位年份 | 2026 |
%m | 两位月份 | 09 |
%d | 两位日期 | 12 |
%H | 24 小时制小时 | 09 |
%M | 分钟 | 30 |
%S | 秒 | 05 |
%w | 星期编号,星期日为 0 | 6 |
%j | 一年中的第几天 | 255 |
%% | 字符 % | % |
横线、斜线、空格和冒号只是普通字符,可以根据显示要求自由组合。
不同平台对部分扩展格式符的支持可能不同。需要微秒时,下一章将使用 datetime 对象处理,不在 time.strftime() 中使用 %f。
时间字符串解析
time.strptime(text, format) 按指定格式把字符串解析为 struct_time:
import time
text = "2026-09-12 09:30:00"
parsed_time = time.strptime(text, "%Y-%m-%d %H:%M:%S")
print(parsed_time)
print(parsed_time.tm_year)字符串内容必须与格式一一对应。日期范围、分隔符或格式不匹配时,会抛出 ValueError:
import time
time.strptime("2026/09/12", "%Y-%m-%d")这里的字符串使用斜线,格式却要求横线,因此无法解析。
时间表示转换关系
常用转换可以整理成下面这张表:
| 从 | 到 | 方法 |
|---|---|---|
| 时间戳 | 本地结构化时间 | time.localtime() |
| 时间戳 | UTC 结构化时间 | time.gmtime() |
| 本地结构化时间 | 时间戳 | time.mktime() |
| UTC 结构化时间 | 时间戳 | calendar.timegm() |
| 结构化时间 | 格式化字符串 | time.strftime() |
| 格式化字符串 | 结构化时间 | time.strptime() |
| 时间戳 | 快速显示字符串 | time.ctime() |
下面把一个本地时间字符串转换成时间戳,再恢复成相同格式的字符串:
import time
original_text = "2026-09-12 09:30:00"
time_format = "%Y-%m-%d %H:%M:%S"
structured_time = time.strptime(original_text, time_format)
timestamp = time.mktime(structured_time)
restored_text = time.strftime(time_format, time.localtime(timestamp))
print(f"原始字符串:{original_text}")
print(f"本地时间戳:{timestamp}")
print(f"恢复字符串:{restored_text}")由于 mktime() 按本地时区解释字符串,不同系统得到的时间戳可能不同,但恢复后的本地时间字符串应该一致。
综合案例:记录任务时间并统计耗时
需求: 记录任务的开始和结束时刻,并统计任务实际运行了多久。
功能分析: 使用格式化字符串展示发生时间,使用 perf_counter() 计算耗时,使用 sleep() 模拟需要等待的任务。
下面模拟一个需要等待的任务。程序使用 strftime() 记录开始和结束时刻,使用 perf_counter() 统计实际耗时:
import time
def run_task():
print("正在执行任务……")
time.sleep(1)
def main():
started_at = time.strftime("%Y-%m-%d %H:%M:%S")
start_counter = time.perf_counter()
run_task()
elapsed = time.perf_counter() - start_counter
finished_at = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"开始时间:{started_at}")
print(f"结束时间:{finished_at}")
print(f"运行耗时:{elapsed:.2f} 秒")
if __name__ == "__main__":
main()一次可能的运行结果:
正在执行任务……
开始时间:2026-09-12 09:30:00
结束时间:2026-09-12 09:30:01
运行耗时:1.00 秒开始时间和结束时间用于展示任务发生在什么时候;perf_counter() 的差值用于回答任务实际运行了多久。两个需求不要混在一起。
小结
time.time()获取当前时间戳,适合表示当前时刻。time.sleep()让程序至少暂停指定时长。time.perf_counter()适合统计代码运行耗时。localtime()返回本地结构化时间,gmtime()返回 UTC 结构化时间。mktime()把本地结构化时间转换成时间戳。strftime()负责格式化时间,strptime()负责解析时间字符串。- 本地时间结果会受到系统时区和语言环境影响。
- 日期加减和更完整的日期对象操作,将在下一章使用
datetime模块完成。
练习
- 使用
time.time()分别输出当前时间的秒值和换算后的毫秒值。 - 使用
time.perf_counter()统计一段循环代码的运行耗时,并保留 4 位小数。 - 分别使用
localtime(0)和gmtime(0),观察当前系统时区下的结果是否相同。 - 把字符串
"2028/05/01 08:30"解析成结构化时间,再格式化为"2028-05-01 08:30:00"。 - 修改综合案例的暂停时间,确认显示时刻和统计耗时会如何变化。