在 Postgresql 中获取 ISO 日期的奇怪结果

Getting a weird result for ISO Date in Postgresql

我有一个tabletask_details。我需要从这个 table select 它的 每周日期 。我使用 ISO Year & ISO Week 从 table 中提取每周日期,因为我想将其周数提取为 53如果是 2015 年 12 月,那么在 2015 年 12 月 28 日、12 月 29 日、12 月 30 日、12 月 31 日和 16 年 1 月 1 日、2016 年 1 月 2 日,因为这些日期不应分为两个不同的星期。
下面给出了我用于 ISO Year & ISO Week 的查询。

select
    name, id,
    to_date(week || ' ' || yr, 'IW IYYY') week_date,
    sum(worked_hours) worked_hours_per_week,
    week, yr
from (
    select
        name, id,
        newdate, hours worked_hours,
        to_number(to_char(newdate, 'IW'), '99') week,
        extract( year from newdate) yr
    from task_details t
) sub
where worked_hours > 0 
group by name, id, to_date(week || ' ' || yr, 'IW IYYY'), week, yr 
order by yr, week

这几周工作正常,但后来我在 table.
中的一个记录日期得到了这个奇怪的结果 table 没有2017.Also 年的数据,yr 列显示的是 2016 年,这符合要求,但 newdate 列和 week 列给出了奇怪的结果。为什么会这样?我该如何解决这个问题?

这里是 SQL fiddle :http://sqlfiddle.com/#!15/53abf/1

您不应在提取函数中混合使用 weekyear,因为 year 适用于公历而不是特殊的 ISO 日历。

参见 section 9.9.1 and comments about week

to_number(to_char(newdate, 'IW'), '99') 实际上是 extract(week from newdate)

yr 列更改为 extract(isoyear from newdate) 即可解决您的问题。

Adjusted SQL Fiddle

已经消除了您对公历和 ISO 年份的困惑。

但是,使用 date_trunc() 获取每周的第一天,您的查询会更简单、更快速:

SELECT name, id
     , <b>date_trunc('week', newdate)::date AS week_date</b>
     , extract(week FROM newdate)::int       AS week
     , extract(isoyear from newdate)::int    AS isoyr  -- must be ISO year to match
     , sum(hours)                            AS worked_hours_per_week
FROM   task_details
WHERE  hours > 0
GROUP  BY name, id, week_date, week, yr
ORDER  BY week_date;

还简化了您的查询。

SQL Fiddle.

无论哪种方式,如果您使用 timestamptz,那么年、周或日期取决于您当前的时区设置。 (可能是不同的年份,具体取决于您现在所在的位置。)