You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python 3.8.3中ISO周格式(%V)异常:2019年首尾日均属第1周的原因

关于Python中ISO周格式(%V)的“异常”解析

哈哈,这个看起来矛盾的输出其实完全符合ISO 8601周编号标准的规则,可不是Python的bug哦!我来给你拆解清楚背后的逻辑:

先搞懂ISO周的核心规则

ISO 8601对周的定义有几个关键要点:

  • 每周从周一开始,周日结束
  • 第1周的判定标准:包含当年第一个周四的那一周(也可以等价理解为:包含1月4日的周,或者该周至少有4天属于当前日历年)
  • 当某一周跨两年时,这一周属于“包含更多天数的那个年份”的周数

对应到你遇到的2019年情况

1. 2019年1月1日的输出(2019-W01)

2019年1月1日是周二,它所在的周是2018年12月31日(周一)到2019年1月6日(周日)。这一周里,2019年的天数有6天(周二到周日),远超过4天,同时也包含2019年1月4日,所以这一周被认定为2019年的第1周,输出2019-W01是完全正确的。

2. 2019年12月31日的输出(2019-W01)

这是最容易困惑的点:2019年12月31日是周二,它所在的周是2019年12月30日(周一)到2020年1月5日(周日)。这一周里,2020年的天数有5天(1月1日到1月5日),而2019年只有2天(12月30、31日),所以这一周实际上是2020年的第1周

那为什么输出是2019-W01?问题出在你用的格式符:

  • %Y:取的是日期的日历年份(也就是2019年,因为12月31日确实在2019年的日历里)
  • %V:取的是ISO周数(这一周是第1周,但属于2020年的第1周)

两者搭配就出现了“2019年的第1周”这种看似矛盾的表述——这其实是格式符搭配错误导致的不规范输出。

正确的ISO周年份格式符:%G

如果要输出符合ISO标准的完整周标识,应该用%G(ISO周对应的年份)代替%Y,这样就能得到正确的结果:

from datetime import date
print(date(2019, 1, 1).strftime('%G-W%V'))  # 输出:2019-W01
print(date(2019, 12, 29).strftime('%G-W%V'))  # 输出:2019-W52
print(date(2019, 12, 31).strftime('%G-W%V'))  # 输出:2020-W01

这样就完全符合ISO 8601的规范了,不会再出现看似矛盾的结果。

内容的提问来源于stack exchange,提问作者Charles R

火山引擎 最新活动