Warum Excel, SQL, Python und JavaScript für dasselbe Datum unterschiedliche Wochennummern liefern

Du berechnest eine Wochennummer in Python, öffnest dann dasselbe Datum in Excel – und die Zahlen passen nicht. Du führst eine SQL‑Abfrage aus und erhältst ein drittes Ergebnis. Du suchst online und findest ein viertes.

Das ist kein Bug. Es ist eine Designentscheidung, die jedes Tool anders trifft — und die meisten dokumentieren sie nicht deutlich genug.

Es gibt mindestens zwei große Systeme zur Wochennummerierung, mehrere Varianten innerhalb jedes Systems und keinen universellen Standard‑Default. Wenn du die Unterschiede einmal verstanden hast, dauert das Debugging von Abweichungen Sekunden. Bis dahin ist es extrem frustrierend.

Die zwei Hauptsysteme

ISO 8601 (in den meisten Teilen Europas, im internationalen Business und in wissenschaftlichen Kontexten genutzt)

  • Wochen laufen von Montag bis Sonntag
  • Woche 1 ist die Woche, die den ersten Donnerstag des Jahres enthält
  • Ein Jahr hat 52 oder 53 Wochen
  • Das Wochenjahr kann an Jahresgrenzen vom Kalenderjahr abweichen

US‑/„einfaches“ System (in Nordamerika und als Standard in vielen Tabellenkalkulationen)

  • Wochen laufen von Sonntag bis Samstag (oder manchmal Montag bis Sonntag, je nach Locale)
  • Woche 1 ist die Woche, die den 1. Januar enthält
  • Der 1. Januar liegt immer in Woche 1, unabhängig vom Wochentag
  • Teilwochen am Jahresende bekommen hohe Nummern (52 oder 53) und werden nicht dem Folgejahr zugeschlagen

Der praktische Unterschied zeigt sich am deutlichsten Ende Dezember und Anfang Januar.

DatumISO‑WocheUS‑Woche (Start So)
28. Dezember 2025Woche 52, 2025Woche 53, 2025
29. Dezember 2025Woche 1, 2026Woche 53, 2025
30. Dezember 2025Woche 1, 2026Woche 53, 2025
31. Dezember 2025Woche 1, 2026Woche 53, 2025
1. Januar 2026Woche 1, 2026Woche 1, 2026
2. Januar 2026Woche 1, 2026Woche 1, 2026
3. Januar 2026Woche 1, 2026Woche 1, 2026
4. Januar 2026Woche 1, 2026Woche 2, 2026

Der 29.–31. Dezember 2025 liegen in ISO‑Woche 1 von 2026 — weil der Donnerstag dieser Woche (1. Januar) in 2026 liegt. Das US‑System lässt sie in Woche 53 von 2025.

Excel: WEEKNUM vs. ISOWEEKNUM

Excel hat zwei getrennte Funktionen — das ist klarer als bei den meisten Tools.

WEEKNUM(date, [return_type]) — US‑Stil, mit konfigurierbarem Wochenstart

Das Argument return_type steuert, an welchem Tag die Woche beginnt:

return_typeWoche beginnt am
1 (Standard)Sonntag
2Montag
11Montag
12Dienstag
13Mittwoch
14Donnerstag
15Freitag
16Samstag
17Sonntag
21Montag (ISO 8601)

return_type = 21 macht WEEKNUM ISO‑kompatibel — aber das ist schlecht dokumentiert und viele Nutzer wissen nicht, dass es existiert.

ISOWEEKNUM(date) — ISO 8601, immer Montag‑Start, Donnerstag‑Regel

Diese Funktion wurde in Excel 2013 hinzugefügt. Sie liefert die korrekte ISO‑Wochennummer und ist eindeutig.

=ISOWEEKNUM("2025-12-31")   → 1    (Woche 1 von 2026)
=WEEKNUM("2025-12-31", 1)   → 53   (Woche 53 von 2025, Start Sonntag)
=WEEKNUM("2025-12-31", 2)   → 53   (Woche 53 von 2025, Start Montag)
=WEEKNUM("2025-12-31", 21)  → 1    (ISO‑kompatibel, wie ISOWEEKNUM)

Häufiger Fehler: WEEKNUM mit Standardparametern verwenden und mit einem ISO‑basierten System vergleichen. Für die meisten Daten stimmen die Zahlen, aber um den Jahreswechsel divergieren sie still.

Google Sheets: Gleiche Funktionen, gleiche Fallstricke

Google Sheets hat sowohl WEEKNUM als auch ISOWEEKNUM mit demselben Verhalten wie Excel. Das Standard‑WEEKNUM ist US‑Stil, Start Sonntag. ISOWEEKNUM ist ISO 8601.

Ein Unterschied: Google Sheets ist konsistenter darin, das ISO‑Wochenjahr zu berücksichtigen, wenn du ISOWEEKNUM zusammen mit YEAR nutzt. Schreibst du =YEAR("2025-12-31"), bekommst du 2025, aber die ISO‑Woche gehört zu 2026. Es gibt keine einzelne eingebaute Funktion, die das ISO‑Wochenjahr zurückgibt — du musst es berechnen:

=IF(ISOWEEKNUM(A1) > 50, IF(MONTH(A1) = 1, YEAR(A1) - 1, YEAR(A1)),
   IF(ISOWEEKNUM(A1) < 3, IF(MONTH(A1) = 12, YEAR(A1) + 1, YEAR(A1)),
   YEAR(A1)))

Das ist lang. Wenn du in Sheets ernsthaft mit Wochenjahren arbeitest, ist ein Export nach Python oder SQL oft sauberer.

Python: isocalendar() ist ISO, aber strftime('%W') nicht

Pythons datetime‑Modul bietet zwei verschiedene Ansätze.

date.isocalendar() — ISO 8601, liefert (year, week, weekday)

from datetime import date

d = date(2025, 12, 31)
d.isocalendar()
# IsoCalendarDate(year=2026, week=1, weekday=3)

Beachte: Das zurückgegebene Jahr ist das ISO‑Wochenjahr (2026), nicht das Kalenderjahr (2025). Das ist korrekt und wichtig — wenn du Wochen labelst, nutze iso_year, nicht d.year.

strftime('%W') und strftime('%U') — US‑Stil, unterschiedliche Wochenstarts

d.strftime('%W')   # Wochennummer, Montag als Wochenanfang → '52'
d.strftime('%U')   # Wochennummer, Sonntag als Wochenanfang → '52'
d.strftime('%V')   # ISO‑Wochennummer → '01'
d.strftime('%G')   # ISO‑Wochenjahr → '2026'

Die Kombination %V / %G ist ISO‑korrekt. %W / %U sind US‑Stil und weichen an Jahresgrenzen von ISO ab.

Häufiger Fehler: d.strftime('%W') für Wochennummern verwenden, obwohl die anderen Systeme ISO nutzen. 48+ Wochen im Jahr stimmen sie überein, dann divergieren sie still in Dezember/Januar.

# Falsch für ISO‑Vergleich — am Jahreswechsel passt es nicht
week = int(d.strftime('%W'))

# Richtig für ISO
iso_year, iso_week, _ = d.isocalendar()

JavaScript: Kein Built‑in, selbst berechnen

JavaScripts Date‑Objekt hat keine native Methode für Wochennummern. Date.getDay() liefert 0 (Sonntag) bis 6 (Samstag). Du musst die Wochennummer selbst berechnen oder eine Library wie date-fns oder dayjs verwenden.

Manuelle ISO‑Wochenberechnung:

function isoWeek(date) {
  const d = new Date(date)
  d.setHours(0, 0, 0, 0)
  // Thursday in current week decides the year
  d.setDate(d.getDate() + 3 - (d.getDay() + 6) % 7)
  const jan4 = new Date(d.getFullYear(), 0, 4)
  return 1 + Math.round(((d - jan4) / 86400000 - 3 + (jan4.getDay() + 6) % 7) / 7)
}

function isoWeekYear(date) {
  const d = new Date(date)
  d.setDate(d.getDate() + 3 - (d.getDay() + 6) % 7)
  return d.getFullYear()
}

isoWeek(new Date('2025-12-31'))      // 1
isoWeekYear(new Date('2025-12-31'))  // 2026

Mit date-fns:

import { getISOWeek, getISOWeekYear } from 'date-fns'

getISOWeek(new Date('2025-12-31'))      // 1
getISOWeekYear(new Date('2025-12-31'))  // 2026

Häufiger Fehler: Ein einfaches Math.ceil(dayOfYear / 7) schreiben und das „Wochennummer“ nennen. Das liefert weder ISO noch US‑Standard — es ist ein komplett anderes (und falsches) System.

SQL: Es hängt von der Datenbank ab

Jede große Datenbank behandelt Wochennummern anders.

PostgreSQL — ISO standardmäßig

SELECT EXTRACT(week FROM DATE '2025-12-31');
-- Gibt 1 zurück (ISO‑Woche)

SELECT DATE_PART('week', DATE '2025-12-31');
-- Gibt 1 zurück (gleich, ISO)

-- ISO‑Wochenjahr
SELECT EXTRACT(isoyear FROM DATE '2025-12-31');
-- Gibt 2026 zurück

PostgreSQLs EXTRACT(week ...) folgt ISO 8601. Das Wochenjahr bekommst du über isoyear.

MySQL / MariaDB — mehrere Modi

-- Modus 3 ist ISO 8601 (Start Montag, Woche 1 hat Donnerstag)
SELECT WEEK('2025-12-31', 3);   -- 1

-- Modus 0 (Standard) ist US‑Stil, Start Sonntag
SELECT WEEK('2025-12-31', 0);   -- 53
SELECT WEEK('2025-12-31');      -- 53 (Standardmodus 0)

-- YEARWEEK liefert kombiniert Jahr+Woche
SELECT YEARWEEK('2025-12-31', 3);  -- 202601

Das Mode‑Argument in MySQL ist entscheidend und hat 8 Optionen (0–7). Modus 3 ist ISO. Der Default (Modus 0) ist US‑Stil. Das ist eine häufige Fehlerquelle beim Wechsel des DB‑Backends.

SQL Server — nicht ISO standardmäßig

-- Default DATEPART(week, ...) ist nicht ISO
SELECT DATEPART(week, '2025-12-31');   -- 53

-- ISO‑Woche: isowk oder iso_week
SELECT DATEPART(isowk, '2025-12-31');  -- 1
SELECT DATEPART(iso_week, '2025-12-31');  -- 1 (gleich)

SQL Servers Default DATEPART(week, ...) ist US‑Stil. isowk ist die ISO‑Variante. Für Reports, die mit europäischen Systemen verglichen werden, immer isowk verwenden.

SQLite — keine native Wochenfunktion

SQLite hat kein WEEKNUM oder EXTRACT(week ...). Du nutzt strftime:

-- '%W' ist Montag‑Start, US‑Stil
SELECT strftime('%W', '2025-12-31');   -- 52

-- ISO‑Woche braucht einen Workaround
SELECT (strftime('%j', date('2025-12-31', '-3 days', 'weekday 4')) - 1) / 7 + 1;
-- 1

Der ISO‑Workaround sucht den Donnerstag der Woche und zählt von dort. Korrekt, aber nicht offensichtlich.

Spickzettel

ToolISO‑WocheUS‑WocheHinweis
ExcelISOWEEKNUM() oder WEEKNUM(d, 21)WEEKNUM() StandardISOWEEKNUM seit 2013
Google SheetsISOWEEKNUM()WEEKNUM() StandardWie Excel
Pythondate.isocalendar()[1] oder %V%W (Mo) / %U (So)Für ISO‑Jahr %G
JavaScriptManuell oder date-fns getISOWeek()ManuellKeine native Wochennummer
PostgreSQLEXTRACT(week ...)Nicht eingebautISO standardmäßig
MySQLWEEK(d, 3)WEEK(d) oder WEEK(d, 0)Modus 3 = ISO
SQL ServerDATEPART(isowk, d)DATEPART(week, d)Default ist US
SQLiteWorkaround nötigstrftime('%W', d)Keine native Unterstützung

So vermeidest du Mismatches in der Praxis

Wähle ein System und erzwinge es überall. ISO ist für die meisten neuen Systeme der bessere Default — international standardisiert und von den meisten modernen Libraries implementiert.

Speichere immer das ISO‑Wochenjahr вместе mit der Wochennummer. Woche 1, 2026 und Woche 1, 2025 sind unterschiedliche Wochen. Eine Spalte, die nur 1 speichert, ist ohne Jahr mehrdeutig.

Teste explizit die Jahreswechsel‑Fälle. Abweichungen passieren bei Dezember 28–31 und Januar 1–3. Lass deine Pipeline mit Testdaten in diesem Bereich laufen, bevor du ausrollst.

Im Zweifel: volle Daten speichern und vergleichen. Wochennummern sind für Darstellung und Reporting, nicht für Primärschlüssel oder Joins. Wenn du Daten über Systeme hinweg über Wochennummern joinst, wandle zuerst in ein kanonisches Datum um (z. B. den Montag der Woche).

Nutze den ISO Week Number Calculator, um die korrekte ISO‑Wochennummer für beliebige Daten zu prüfen — inklusive vollständiger Kalenderansicht.