You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite中如何正确获取符合ISO-8601标准的周数?

如何在SQLite中正确获取符合ISO-8601标准的周数

确实,SQLite自带的STRFTIME('%W')并不遵循ISO-8601的周规则——它默认以周日为一周起始,且把每年1月1日所在的周算作第0周(或第1周,取决于年份),这就导致像2018-12-31这类边缘日期计算出错。要拿到完全符合标准的ISO周(包含正确的年份和周数),我们可以通过ISO周的核心规则来构建查询:

先明确ISO周的核心规则

要搞对计算逻辑,得先记住ISO周的两个关键:

  • 一周的第一天是周一,不是周日
  • 每年的第1周是当年第一个包含周四的周——这意味着:
    • 如果1月1日是周一到周四,那它属于当年第1周
    • 如果1月1日是周五到周日,它会被归到上一年的最后一周
    • 同理,年末的几天可能属于下一年的第1周(比如你提到的2018-12-31)

正确的SQL查询语句

下面这个查询可以精准返回ISO标准的年份和周数,还能合并成YYYY-WW的规范格式:

SELECT 
  -- 获取ISO年份
  strftime('%Y', date('2018-12-31', '-3 days', 'weekday 4')) AS iso_year,
  -- 获取ISO周数(带两位数字格式)
  printf('%02d', (strftime('%j', date('2018-12-31', '-3 days', 'weekday 4')) - 1) / 7 + 1) AS iso_week,
  -- 合并成年份-周数的标准格式
  strftime('%Y', date('2018-12-31', '-3 days', 'weekday 4')) || '-W' || printf('%02d', (strftime('%j', date('2018-12-31', '-3 days', 'weekday 4')) - 1) / 7 + 1) AS iso_week_full;

针对2018-12-31执行这个查询,会得到:

  • iso_year: 2019
  • iso_week: 01
  • iso_week_full: 2019-W01
    完全符合ISO-8601的要求。

拆解一下这个逻辑为什么有效

我们一步步看每个部分的作用:

  1. date('2018-12-31', '-3 days', 'weekday 4'):
    • 在SQLite的date函数里,weekday 4代表周四(取值规则是0=周日,1=周一,…,4=周四)
    • 先把目标日期减3天,再调整到最近的周四。这一步的核心是找到当前日期所在ISO周的周四——根据ISO规则,周四所在的年份就是这个ISO周对应的年份,完美解决跨年周的归属问题。
  2. 计算ISO年份:直接取这个周四的年份,就是当前日期所属的ISO年,不会出错。
  3. 计算ISO周数:
    • strftime('%j', ...)获取该周四是当年的第几天(范围1-366)
    • 减1后除以7取整(整数除法),再加1,就能得到该周四所在的周数,也就是当前日期的ISO周数。
    • 用printf('%02d', ...)是为了让周数保持两位数字(比如第1周显示为01),严格遵循ISO格式的要求。

测试几个边界案例验证

可以用这些边缘日期测试,确保逻辑正确:

  • 2019-01-01(周二):返回2019-W01,正确
  • 2020-12-31(周四):返回2020-W53,正确
  • 2021-01-01(周五):返回2020-W53,正确
  • 2023-12-31(周日):返回2024-W01,正确

内容的提问来源于stack exchange,提问作者shashank s

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:33:02