Python解析年-周数字符串时%W与%U的结果不一致问题
Python datetime中%W与%U解析年周字符串的不一致问题及原因
正常解析情况
from datetime import datetime print("\nISO周:") # ISO标准周(周一为起始,周数从1开始) for i in range(1,8): # %u 是1-based(1=周一,7=周日) print(datetime.strptime(f"2019-01-{i}", "%G-%V-%u")) # 输出: # 2018-12-31 00:00:00 # 2019-01-01 00:00:00 # 2019-01-02 00:00:00 # ... # %U -> 以周日为一周起始的年度周数 # 2019年第一个周日是2019-01-06 print("\n%U格式解析:") for i in range(0,7): # %w 是0-based(0=周日,6=周六) print(datetime.strptime(f"2019-01-{i}", "%Y-%U-%w")) # 输出: # 2019-01-06 00:00:00 # 2019-01-07 00:00:00 # 2019-01-08 00:00:00 # ...
异常情况
# %W -> 以周一为一周起始的年度周数 # 2019年第一个周一是2019-01-07 print("\n%W格式解析:") for i in range(0,7): print(datetime.strptime(f"2019-01-{i}", "%Y-%W-%w")) # 输出: # 2019-01-13 00:00:00 ## <-- 预期为2019-01-06 # 2019-01-07 00:00:00 # 2019-01-08 00:00:00 # 2019-01-09 00:00:00 # 2019-01-10 00:00:00 # 2019-01-11 00:00:00 # 2019-01-12 00:00:00
问题原因分析
1. Python datetime的%W逻辑细节
Python的%W格式符规则是:以周一为一周起始,新年中第一个周一之前的所有日期都归为第0周。而%w格式符的定义固定为0代表周日、6代表周六,和周数的起始日无关。
在测试场景中:
- 2019年第一个周一是1月7日,因此1月1日至1月6日都属于
%W的第0周,1月7日起进入第1周。 - 当解析
"2019-01-0"时,%W=01(第1周)、%w=0(周日),对应第1周的最后一天——1月13日(第1周从1月7日周一到1月13日周日),这就是第一个输出结果的由来。 - 若要解析1月6日(第0周的周日),需使用
%W=00,比如执行datetime.strptime("2019-00-0", "%Y-%W-%w")会返回2019-01-06。
对比%U的逻辑:%U是以周日为一周起始,新年中第一个周日之前的日期属于第0周。2019年第一个周日是1月6日,因此"2019-01-0"对应第1周的周日(1月6日),后续日期依次递增,符合预期。
2. Rust chrono库报错的原因
chrono库对日期组合的有效性校验更严格:当用%W(周一为起始的周数)搭配%w=0(周日)解析2019-01-0时,它会校验该周数对应的星期是否存在。由于2019年第1周从1月7日周一才开始,该周的周日是1月13日,输入的%w=0无法对应第1周的有效日期,因此chrono判定该组合无效并抛出错误。
内容的提问来源于stack exchange,提问作者FObersteiner
相关产品推荐
相关产品推荐

