By Ether DataRequest data sample
All sections

Week Systems

ISO, US/retail, broadcast (Nielsen), and Middle-East week conventions disagree on the start day and on how weeks roll into months and years, so a bare week number is meaningless without its system.

stable4 min read
Source time
instant
Destination time
iso_week

Purpose

"Week 29" means at least four different things depending on which week system produced the number. This page catalogs the competing conventions this KB has to interoperate with, states which one it standardizes on, and gives the crosswalk logic for translating between them.

The competing systems

ISO-8601
Monday start. Week 1 is the week containing the year's first Thursday (equivalently, the week containing January 4). Years have 52 or 53 weeks. Used by: this KB, most of Europe, ISO-conformant systems generally.
US / retail (NRF 4-5-4)
Sunday start. The National Retail Federation's 4-5-4 fiscal calendar groups weeks into quarters of 4, 5, and 4 weeks (13 weeks/quarter), with its own fiscal year start (often the Sunday closest to Jan 31 or Feb 1), not the Gregorian calendar.
Broadcast / Nielsen
Monday start, like ISO, but organized into its own broadcast month and quarter — a broadcast month is a whole number of broadcast weeks (typically 4 or 5) and does not align to the Gregorian month; a broadcast quarter runs 13 or 14 weeks. See broadcast-calendar-month below.
Middle East
Common convention starts the week on Saturday (some countries: Sunday), reflecting a Friday-Saturday or Friday-only weekend. Week numbering under this convention does not agree with ISO week boundaries.

A single instant can therefore carry a different week number under each system, and even systems that agree on the start day (ISO and broadcast both start Monday) can still disagree on which week is "week 1" of the year, because their year boundaries and roll-up rules differ.

This KB's standard: ISO for the canonical key

This knowledge base standardizes on ISO-8601 for the (isoYear, isoWeek, slot) key used everywhere — see ISO Week and The 168 Axis. ISO was chosen because it is parameter-free and exact (no declared cutover, no fiscal-year anchor to configure) and because its Monday start aligns naturally with slot 0 = Monday 00:00 UTC. Any other week system a downstream platform reports in (US/retail, broadcast) is treated as a presentation crosswalk applied on top of the canonical ISO key, not as an alternate canonical grain.

Crosswalk logic

import { isoWeekOf } from "@/lib/time/isoweek";
import { DateTime } from "luxon";

// ISO week (this KB's canonical): Monday start.
const iso = isoWeekOf(Date.parse("2026-07-19T00:00:00Z")); // a Sunday
// -> { isoYear: 2026, isoWeek: 29, isoWeekday: 7 }

// US/retail week number (Sunday start) for the SAME instant requires a
// different anchor rule entirely — it is not a fixed offset from the ISO
// week, because the two systems' "week 1" definitions diverge independently
// each year. A retail crosswalk must be computed against the retailer's own
// declared fiscal calendar, not derived from the ISO week number.
const dt = DateTime.fromMillis(Date.parse("2026-07-19T00:00:00Z"), { zone: "utc" });
const sundayStartWeekday = dt.weekday % 7; // 0 = Sunday ... 6 = Saturday

The critical point the snippet makes explicit: because ISO and US/retail weeks can start their year in different places (ISO week 1 anchors to the first Thursday; a retail fiscal year anchors to a declared date near month-end), there is no universal arithmetic formula converting an ISO week number directly into a retail week number — the retailer's specific fiscal calendar (its declared year-start date) must be consulted. The only safe general crosswalk is instant-based: resolve the target instant, then apply each system's own rule to that instant independently, rather than transforming one week number into another.

Why a bare week number is a bug

Always declare the system

A payload containing only "week": 29 cannot be interpreted correctly by any receiving system without also knowing which week system produced it — ISO week 29 of 2026 (Jul 13-19), a US/retail week 29 (a different date range, anchored to that retailer's fiscal year start), and a broadcast week 29 (aligned to Nielsen's broadcast calendar) are three different seven-day spans that happen to share a number. Always pair a week number with its system, and prefer the full (isoYear, isoWeek) pair — or the combined week_slot_key — as the canonical join key.

Edge cases

Week-numbering systems is this page's core subject. Broadcast calendar month: because a broadcast month is a whole number of broadcast weeks rather than a Gregorian month, reconciling broadcast-month reporting against calendar-month reporting requires a declared week-to-month crosswalk, not a date-range assumption — see Broadcast Day for the related per-day convention. Week-year boundary and fifty-three-week years are properties of the ISO system specifically and are detailed on the ISO Week page.

Python parity

from datetime import datetime, timezone

def iso_week(epoch_ms: int) -> tuple[int, int, int]:
    return datetime.fromtimestamp(epoch_ms / 1000, tz=timezone.utc).isocalendar()

def sunday_start_weekday(epoch_ms: int) -> int:
    # 0 = Sunday ... 6 = Saturday, for building a US/retail-style crosswalk.
    dt = datetime.fromtimestamp(epoch_ms / 1000, tz=timezone.utc)
    return (dt.isoweekday()) % 7

Python's isocalendar() gives the ISO figures natively; a US/retail or broadcast crosswalk still requires each system's own declared calendar (a retailer's 4-5-4 fiscal year, or Nielsen's broadcast calendar) as external input — no standard library or package encodes those rules generically, since they are business conventions, not international standards.

Edge cases affecting this page

ISO WeekCalendar & weekBroadcast DayCalendar & week