
使用 datetime.strptime() 将 ISO 周号(如 isocalendar() 返回的年份与周数)转换为对应周一日期时,必须配合 ISO 8601 专用格式符(如 %G、%V、%u),否则会因标准不一致导致日期错位。
使用 `datetime.strptime()` 将 iso 周号(如 `isocalendar()` 返回的年份与周数)转换为对应周一日期时,必须配合 iso 8601 专用格式符(如 `%g`、`%v`、`%u`),否则会因标准不一致导致日期错位。
在 Python 中,date.isocalendar() 返回的是符合 ISO 8601 标准的三元组 (ISO_year, ISO_week, ISO_weekday),其中:
-
ISO_year是“包含该周大部分天数”的年份(可能与日历年不同,例如 2024 年 12 月 30 日属于 ISO 2025 年第 1 周); -
ISO_week范围是 01–53,定义为“包含 1 月 4 日的那一周为第 01 周”,且每周始于周一; -
ISO_weekday范围是 1(周一)至 7(周日)。
但许多开发者误用传统格式符(如 %Y + %W + %w)进行反向解析,这会导致严重偏差:
from datetime import date, datetime
today = date(2025, 2, 13) # Thursday
iso_year, iso_week, iso_wday = today.isocalendar() # → (2025, 7, 4)
# ❌ 错误:混用 ISO 数据 + 非 ISO 格式符
d_bad = f"{iso_year}-W{iso_week}-1"
bad_date = datetime.strptime(d_bad, "%Y-W%W-%w").date() # → 2025-02-17(实际是 ISO 第 8 周!)
print(bad_date.isocalendar()) # (2025, 8, 1) —— 偏移了一周!根本原因在于:
-
%Y和%W基于日历年和以周日为起点的周计数(%W将年初首个周一前的天数归为第 0 周); - 而
isocalendar()的年份和周号严格遵循 ISO 8601,二者语义不兼容。
✅ 正确做法:全程使用 ISO 8601 格式符:
| 格式符 | 含义 |
|---|---|
%G |
ISO 年份(与 isocalendar()[0] 一致) |
%V |
ISO 周号(01–53,与 isocalendar()[1] 一致) |
%u |
ISO 工作日(1=周一,7=周日,与 isocalendar()[2] 一致) |
# ✅ 正确:ISO 输入 → ISO 解析
d_good = f"{iso_year}-{iso_week:02d}-1" # 格式:YYYY-VV-u(u=1 表示周一)
good_date = datetime.strptime(d_good, "%G-%V-%u").date()
print(good_date) # 2025-02-10
print(good_date.isocalendar()) # (2025, 7, 1) —— 完全匹配!⚠️ 注意事项:
-
%V必须搭配%G(不可用%Y),因为 ISO 年可能跨日历年(如 2024-12-30 属于 ISO 2025-W01); - 周号需补零为两位(
f"{week:02d}"),否则%V解析可能失败; - 若需获取其他工作日(如周三),将
%u替换为对应数字(3)即可; -
strptime不支持%-V等无前导零格式,务必统一使用%V和两位周号。
? 总结:isocalendar() 与 strptime 的 ISO 格式符(%G/%V/%u)是一套完整、自洽的 ISO 8601 工具链;混用非 ISO 格式符(%Y/%W/%w)是常见陷阱,务必避免。

















