Appearance
25|日期与时间
程序中处理时间的场景很多:记录事件发生的时刻、计算两个时间点之间的间隔、格式化输出给用户看、解析用户输入的时间字符串。Python 的 datetime 模块提供了完整的日期时间处理能力。
一、datetime 对象
python
from datetime import datetime, date, time, timedelta
# 当前日期时间
now = datetime.now()
print(now) # 2024-06-01 10:30:15.123456
# 当前日期
today = date.today()
print(today) # 2024-06-01
# 指定日期时间创建
dt = datetime(2024, 6, 1, 10, 30, 0)
print(dt) # 2024-06-01 10:30:00datetime 包含日期和时间两部分。date 只有日期,time 只有时间。
二、格式化输出
strftime() 把 datetime 对象格式化成字符串:
python
now = datetime.now()
now.strftime("%Y-%m-%d") # '2024-06-01'
now.strftime("%Y-%m-%d %H:%M:%S") # '2024-06-01 10:30:15'
now.strftime("%H:%M") # '10:30'常用格式符:
| 格式符 | 含义 | 示例 |
|---|---|---|
%Y | 四位年份 | 2024 |
%m | 月份(01-12) | 06 |
%d | 日期(01-31) | 01 |
%H | 小时(00-23) | 10 |
%M | 分钟(00-59) | 30 |
%S | 秒(00-59) | 15 |
%f | 微秒 | 123456 |
%A | 星期几(英文) | Saturday |
%a | 星期几缩写 | Sat |
三、解析字符串
strptime() 把字符串解析成 datetime 对象:
python
dt = datetime.strptime("2024-06-01 10:30:00", "%Y-%m-%d %H:%M:%S")
print(dt) # 2024-06-01 10:30:00格式字符串要和输入字符串严格匹配:
python
datetime.strptime("2024/06/01", "%Y-%m-%d") # ValueError,分隔符不匹配四、时间差
两个 datetime 相减得到 timedelta:
python
start = datetime(2024, 6, 1, 10, 0, 0)
end = datetime(2024, 6, 1, 10, 30, 15)
delta = end - start
print(delta) # 0:30:15
print(delta.days) # 0
print(delta.seconds) # 1815,注意:不是总秒数,是去掉天后的秒数
print(delta.total_seconds()) # 1815.0,总秒数timedelta 的属性容易混淆:
days:完整的天数seconds:去掉天数后剩余的秒数(0-86399)microseconds:去掉天数和秒数后剩余的微秒total_seconds():转换为总秒数(包含天数)
创建时间差:
python
from datetime import timedelta
future = now + timedelta(days=7) # 7 天后
past = now - timedelta(hours=3) # 3 小时前
interval = timedelta(weeks=1, days=2) # 9 天五、比较时间
datetime 对象可以直接比较:
python
dt1 = datetime(2024, 6, 1, 10, 0)
dt2 = datetime(2024, 6, 1, 11, 0)
dt1 < dt2 # True
dt1 == dt2 # False判断某个时间是否在范围内:
python
start = datetime(2024, 6, 1, 9, 0)
end = datetime(2024, 6, 1, 18, 0)
now = datetime.now()
start <= now <= end # 链式比较六、时区处理
不带时区的 datetime 叫"naive",带时区的叫"aware"。
python
from datetime import datetime, timezone, timedelta
# 创建带时区的时间
utc = timezone.utc
beijing_tz = timezone(timedelta(hours=8))
now_utc = datetime.now(utc)
now_bj = datetime.now(beijing_tz)
print(now_utc) # 2024-06-01 02:30:00+00:00
print(now_bj) # 2024-06-01 10:30:00+08:00转换时区:
python
now_bj.astimezone(utc) # 转成 UTCPython 3.9+ 推荐使用 zoneinfo 模块(标准库):
python
from zoneinfo import ZoneInfo
bj = ZoneInfo("Asia/Shanghai")
now_bj = datetime.now(bj)时区名称可以从 IANA 时区数据库查询(如 Asia/Shanghai、America/New_York)。
容器中的时区问题:容器默认使用 UTC,应用按本地时间记录日志时,和宿主机可能差 8 小时。解决方式是在容器内设置 TZ 环境变量,或程序显式处理时区。
七、时间戳
时间戳是从 1970-01-01 00:00:00 UTC 到指定时间的秒数:
python
now = datetime.now()
ts = now.timestamp() # 浮点数秒数
dt = datetime.fromtimestamp(ts) # 时间戳转 datetime时间戳是跨系统交换时间的常用格式——它是纯数字,不受时区和格式影响。
八、给文件名加日期
python
from datetime import datetime
from pathlib import Path
today = datetime.now().strftime("%Y%m%d")
backup = Path(f"backup-{today}.zip")
print(backup) # backup-20240601.zip记忆锚点:datetime.now() 获取当前时间;strftime() 格式化,strptime() 解析;timedelta 表示时间差,total_seconds() 转总秒数;datetime 可直接比较大小;naive 是不带时区的,aware 是带时区的;ZoneInfo 处理时区(Python 3.9+);时间戳是纯数字,跨系统交换用时间戳。