Pourquoi Excel, SQL, Python et JavaScript donnent des numéros de semaine différents pour la même date
Vous calculez un numéro de semaine en Python, puis vous ouvrez la même date dans Excel et les nombres ne correspondent pas. Vous exécutez une requête SQL et vous obtenez un troisième résultat. Vous cherchez en ligne et vous trouvez un quatrième.
Ce n’est pas un bug. C’est un choix de conception que chaque outil fait différemment — et que la plupart ne documentent pas assez clairement.
Il existe au moins deux grands systèmes de numérotation des semaines couramment utilisés, plusieurs variantes dans chacun, et aucun “défaut” universel. Une fois que vous comprenez les différences, déboguer ces écarts prend quelques secondes. Avant ça, c’est exaspérant.
Les deux principaux systèmes
ISO 8601 (utilisé dans la plupart de l’Europe, le commerce international et les contextes scientifiques)
- Les semaines vont du lundi au dimanche
- La semaine 1 est celle qui contient le premier jeudi de l’année
- Une année compte 52 ou 53 semaines
- L’année de semaine peut différer de l’année civile aux frontières
Système US / “simple” (utilisé en Amérique du Nord et par défaut dans beaucoup de tableurs)
- Les semaines vont du dimanche au samedi (ou parfois du lundi au dimanche selon la locale)
- La semaine 1 est celle qui contient le 1er janvier
- Le 1er janvier est toujours en semaine 1, quel que soit le jour
- Les semaines partielles en fin d’année gardent des numéros élevés (52 ou 53), elles ne sont pas “rebasculées” sur l’année suivante
La différence pratique se voit surtout fin décembre et début janvier.
| Date | Semaine ISO | Semaine US (début dimanche) |
|---|---|---|
| 28 décembre 2025 | Semaine 52, 2025 | Semaine 53, 2025 |
| 29 décembre 2025 | Semaine 1, 2026 | Semaine 53, 2025 |
| 30 décembre 2025 | Semaine 1, 2026 | Semaine 53, 2025 |
| 31 décembre 2025 | Semaine 1, 2026 | Semaine 53, 2025 |
| 1 janvier 2026 | Semaine 1, 2026 | Semaine 1, 2026 |
| 2 janvier 2026 | Semaine 1, 2026 | Semaine 1, 2026 |
| 3 janvier 2026 | Semaine 1, 2026 | Semaine 1, 2026 |
| 4 janvier 2026 | Semaine 1, 2026 | Semaine 2, 2026 |
Les 29–31 décembre 2025 tombent en semaine ISO 1 de 2026 — parce que le jeudi de cette semaine (le 1er janvier) est en 2026. Le système US les garde en semaine 53 de 2025.
Excel : WEEKNUM vs ISOWEEKNUM
Excel a deux fonctions distinctes, ce qui est plus clair que la plupart des outils.
WEEKNUM(date, [return_type]) — style US, avec un début de semaine configurable
L’argument return_type contrôle quel jour commence la semaine :
| return_type | La semaine commence le |
|---|---|
| 1 (défaut) | Dimanche |
| 2 | Lundi |
| 11 | Lundi |
| 12 | Mardi |
| 13 | Mercredi |
| 14 | Jeudi |
| 15 | Vendredi |
| 16 | Samedi |
| 17 | Dimanche |
| 21 | Lundi (ISO 8601) |
return_type = 21 fait se comporter WEEKNUM comme ISO — mais c’est mal mis en avant et la plupart des utilisateurs ne savent pas que ça existe.
ISOWEEKNUM(date) — ISO 8601, début lundi, règle du jeudi
Ajoutée dans Excel 2013. Elle renvoie le bon numéro de semaine ISO et ne prête pas à confusion.
=ISOWEEKNUM("2025-12-31") → 1 (semaine 1 de 2026)
=WEEKNUM("2025-12-31", 1) → 53 (semaine 53 de 2025, début dimanche)
=WEEKNUM("2025-12-31", 2) → 53 (semaine 53 de 2025, début lundi)
=WEEKNUM("2025-12-31", 21) → 1 (compatible ISO, comme ISOWEEKNUM)
Erreur fréquente : utiliser WEEKNUM avec ses arguments par défaut lorsqu’on compare à un système basé sur ISO. Les nombres concordent pour la plupart des dates mais divergent silencieusement près de la fin d’année.
Google Sheets : mêmes fonctions, mêmes pièges
Google Sheets possède aussi WEEKNUM et ISOWEEKNUM avec le même comportement qu’Excel. WEEKNUM par défaut est de style US (début dimanche). ISOWEEKNUM est ISO 8601.
Une différence : Google Sheets est plus cohérent quand vous utilisez ISOWEEKNUM avec YEAR. Si vous écrivez =YEAR("2025-12-31") vous obtenez 2025, mais la semaine ISO appartient à 2026. Il n’existe pas de fonction intégrée unique qui renvoie l’année ISO de la semaine — il faut la calculer :
=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)))
C’est verbeux. Si vous travaillez sérieusement avec les semaines/années ISO dans Sheets, il est souvent plus propre d’exporter vers Python ou SQL.
Python : isocalendar() est ISO, mais strftime('%W') ne l’est pas
Le module datetime de Python vous donne deux approches différentes.
date.isocalendar() — ISO 8601, renvoie (année, semaine, jour_de_semaine)
from datetime import date
d = date(2025, 12, 31)
d.isocalendar()
# IsoCalendarDate(year=2026, week=1, weekday=3)
Notez que l’année renvoyée est l’année ISO de la semaine (2026), pas l’année civile (2025). C’est correct et important — si vous devez étiqueter la semaine, utilisez iso_year et pas d.year.
strftime('%W') et strftime('%U') — style US, débuts de semaine différents
d.strftime('%W') # Numéro de semaine, lundi = premier jour → '52'
d.strftime('%U') # Numéro de semaine, dimanche = premier jour → '52'
d.strftime('%V') # Numéro de semaine ISO → '01'
d.strftime('%G') # Année ISO de la semaine → '2026'
La combinaison %V / %G est correcte pour ISO. Les directives %W / %U sont de style US et ne correspondent pas à ISO aux frontières d’année.
Erreur fréquente : utiliser d.strftime('%W') pour obtenir des numéros de semaine alors que vos autres systèmes utilisent ISO. Ils seront d’accord 48+ semaines par an, puis divergeront discrètement en décembre et janvier.
# Faux pour une comparaison ISO — décalage en fin/début d’année
week = int(d.strftime('%W'))
# Correct pour ISO
iso_year, iso_week, _ = d.isocalendar()
JavaScript : pas de méthode intégrée, il faut calculer
L’objet Date de JavaScript n’a pas de méthode native pour le numéro de semaine. Date.getDay() renvoie 0 (dimanche) à 6 (samedi). Il faut calculer manuellement ou utiliser une bibliothèque comme date-fns ou dayjs.
Calcul manuel de la semaine ISO :
function isoWeek(date) {
const d = new Date(date)
d.setHours(0, 0, 0, 0)
// Le jeudi de la semaine courante détermine l’année
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
Avec date-fns :
import { getISOWeek, getISOWeekYear } from 'date-fns'
getISOWeek(new Date('2025-12-31')) // 1
getISOWeekYear(new Date('2025-12-31')) // 2026
Erreur fréquente : écrire un calcul simple Math.ceil(dayOfYear / 7) et appeler ça un numéro de semaine. Ça ne correspond ni à ISO ni au système US — c’est un autre système (et il est faux).
SQL : ça dépend de la base
Chaque base de données majeure gère les numéros de semaine différemment.
PostgreSQL — ISO par défaut
SELECT EXTRACT(week FROM DATE '2025-12-31');
-- Renvoie 1 (semaine ISO)
SELECT DATE_PART('week', DATE '2025-12-31');
-- Renvoie 1 (idem, ISO)
-- Obtenir l’année ISO de la semaine
SELECT EXTRACT(isoyear FROM DATE '2025-12-31');
-- Renvoie 2026
Dans PostgreSQL, EXTRACT(week ...) suit ISO 8601. L’année de semaine est disponible via isoyear.
MySQL / MariaDB — plusieurs modes
-- Le mode 3 est ISO 8601 (début lundi, semaine 1 contient le jeudi)
SELECT WEEK('2025-12-31', 3); -- 1
-- Le mode 0 (défaut) est de style US, début dimanche
SELECT WEEK('2025-12-31', 0); -- 53
SELECT WEEK('2025-12-31'); -- 53 (mode 0 par défaut)
-- YEARWEEK renvoie année+semaine combinées
SELECT YEARWEEK('2025-12-31', 3); -- 202601
L’argument “mode” dans MySQL est crucial et a 8 options (0–7). Le mode 3 est ISO. Le défaut (mode 0) est US. C’est une source fréquente de bugs quand on change de backend.
SQL Server — pas ISO par défaut
-- DATEPART(week, ...) par défaut n’est pas ISO
SELECT DATEPART(week, '2025-12-31'); -- 53
-- Semaine ISO : utiliser isowk ou iso_week
SELECT DATEPART(isowk, '2025-12-31'); -- 1
SELECT DATEPART(iso_week, '2025-12-31'); -- 1 (idem)
Le DATEPART(week, ...) par défaut de SQL Server suit le style US. L’alias isowk est la version ISO. Pour des rapports comparés à des systèmes européens, utilisez toujours isowk.
SQLite — pas de fonction semaine native
SQLite n’a ni WEEKNUM ni EXTRACT(week ...). On utilise strftime :
-- '%W' = début lundi, style US
SELECT strftime('%W', '2025-12-31'); -- 52
-- La semaine ISO nécessite un contournement
SELECT (strftime('%j', date('2025-12-31', '-3 days', 'weekday 4')) - 1) / 7 + 1;
-- 1
Le contournement ISO trouve le jeudi de la semaine et compte à partir de là. C’est correct mais peu évident.
Aide-mémoire
| Outil | Semaine ISO | Semaine US | Notes |
|---|---|---|---|
| Excel | ISOWEEKNUM() ou WEEKNUM(d, 21) | WEEKNUM() par défaut | ISOWEEKNUM ajouté en 2013 |
| Google Sheets | ISOWEEKNUM() | WEEKNUM() par défaut | Même logique qu’Excel |
| Python | date.isocalendar()[1] ou %V | %W (lun) / %U (dim) | Utiliser %G pour l’année ISO |
| JavaScript | Manuel ou date-fns getISOWeek() | Manuel | Pas de semaine native |
| PostgreSQL | EXTRACT(week ...) | Pas intégré | ISO par défaut |
| MySQL | WEEK(d, 3) | WEEK(d) ou WEEK(d, 0) | Mode 3 = ISO |
| SQL Server | DATEPART(isowk, d) | DATEPART(week, d) | Défaut = US |
| SQLite | Contournement requis | strftime('%W', d) | Pas de support natif |
Comment éviter les écarts en pratique
Choisissez un système et imposez-le partout. ISO est un meilleur défaut pour la plupart des nouveaux systèmes — c’est standardisé internationalement et ce que la plupart des bibliothèques modernes implémentent.
Stockez toujours l’année ISO de la semaine avec le numéro de semaine. Semaine 1, 2026 et semaine 1, 2025 ne sont pas la même semaine. Une colonne qui stocke juste 1 est ambiguë sans l’année.
Testez explicitement les cas de frontière d’année. Les dates du 28 au 31 décembre et du 1 au 3 janvier sont celles où les écarts apparaissent. Faites tourner votre pipeline avec des dates de test dans cette plage avant de déployer.
En cas de doute, stockez et comparez des dates complètes. Les numéros de semaine sont faits pour l’affichage et le reporting, pas pour des clés primaires ou des jointures. Si vous joignez des données entre systèmes sur un numéro de semaine, convertissez d’abord vers une date canonique (le lundi de la semaine).
Utilisez le ISO Week Number Calculator pour vérifier le bon numéro de semaine ISO pour n’importe quelle date, y compris une vue calendrier complète de l’année.