Time & dates
Concept  ·  SQL & Querying

ISO week vs engine default, and month arithmetic at the 31st, both shift boundaries silently.

ISO weeks start Monday and week 1 contains the year's first Thursday — clean for week-over-week ops, but it means the week's year is its own column: pair weekofyear with isoyear, never with EXTRACT(year), or New Year's Day books into 'week 53 of 2027' (which doesn't exist). Engines add a second axis: week-start (Sunday vs Monday) differs by locale. Definition first, functions second.

See it break
harvest
dkg
2027-01-0140
The trap
SELECT
  EXTRACT (
    year
    FROM
      d) AS yr,
  week(d) AS wk,
  SUM(kg) AS kg
FROM
  harvest
GROUP BY
  yr,
  wk
ORDER BY
  yr,
  wk;
The fix
SELECT
  isoyear(d) AS iso_yr,
  week(d) AS wk,
  SUM(kg) AS kg
FROM
  harvest
GROUP BY
  iso_yr,
  wk
ORDER BY
  iso_yr,
  wk;
INPUTYour queryThe fix
2027534040

Grouping the New Year harvest by (calendar year, week) booked it into week 53 of 2027 — ISO week 53 belongs to ISO year 2026, so the calendar year and the ISO week don't pair; isoyear does.

The rule

(isoyear, isoweek) as the grouping pair, or date_trunc('week', d) — the truncated date carries its year for free.

Week-start and week-1 rules vary; ISO functions where they exist, explicit definitions where they don't.

Shows up elsewhere
Truncate vs extractHalf-open intervals
Try one →Prove it in practice →