我有一个简单的 SQL 用于计算 SQLite 报告中的周数
SELECT STRFTIME('%W', 'date_column')
2009-2012 年是正确的。在 2013 年,我总是得到错误的周数。
例如
SELECT STRFTIME('%W', '2012-02-28')
返回 '09',这是正确的。
SELECT STRFTIME('%W', '2013-02-28')
return '08' 这是错误的。我们有第 9 周。
SQLite 日期时间函数中有什么我不明白的吗?还是 SQLite 的 bug?
CL 的答案适用于 OP 对“正确”的定义,这与 ISO 定义不太一样。 ISO 周数始终在 1-53 范围内(没有第 0 周),一年的最后 3 天可能会落入下一年的第 1 周,就像前 3 天可能会落入 52 周或 53 周一样前一年。要考虑这些极端情况,您需要执行以下操作:
SELECT
(strftime('%j', date(MyDate, '-3 days', 'weekday 4')) - 1) / 7 + 1 AS ISOWeekNumber
FROM MyTable;
作为旁注,SQLite 的日期和时间 文档确实链接到POSIX strftime 手册页,它将
%W
修饰符定义为:
“一年中的周数(星期一作为一周的第一天)作为十进制数 [00,53]。第一个星期一之前的新年中的所有日子都被认为是在第 0 周。”
从 SQLite 的未记录的周定义(第一周是一年中第一个星期一的那一周,或其中有 1 月 7 日的那一周)转换为 ISO 周定义(第一周是一年中第一个星期二的那一周,或其中包含 1 月 4 日的那一周),我们让 SQLite 计算一年中 1 月 4 日所在的那一周。如果那不是一个,我们必须增加周数:
SELECT strftime('%W', MyDate)
+ (1 - strftime('%W', strftime('%Y', MyDate) || '-01-04'))
FROM MyTable
根据 srdan 的回答,这是一个完整的解决方案,其中包括与确定的周数相对应的年份。这个表达式产生一个有效的 ISO 8601 周规范,并且可以按原样用于基于完整连续周的统计查询(没有新年前后奇怪的拆分行为)。
select format('%04d', strftime('%Y', date(_time_, '-3 days', 'weekday 4'))) || '-W' ||
format('%02d', (strftime('%j', date(_time_, '-3 days', 'weekday 4')) - 1) / 7 + 1);
PS:如果您收到
format
函数未定义的错误,请将其替换为旧别名 printf
。我找不到它是在哪个 SQLite 版本中更改的。