date.isocalendar / fromisocalendar
ISO weeks start on Monday, and week 1 is the week containing the year's first Thursday. So the ISO year can differ from the calendar year for a few days around New Year.
Common call
d.isocalendar().week
Returns
40 for 2026-09-29
Replaces
int(d.strftime('%V')) and hand-written week logic
Watch out
Use .year from isocalendar() with .week, not d.year
d.isocalendar()
→ IsoCalendarDate
Demo
Live evaluation
Try dates near New Year: the ISO year and the calendar year part ways.
Try:
Inputs
whenstrYYYY-MM-DD
Code
from datetime import date d = date.fromisoformat('2026-09-29') (d.year, d.isocalendar())
Result
(2026, datetime.IsoCalendarDate(year=2026, week=40, weekday=2))
1 January 2027 is a Friday, so it still belongs to the last ISO week of 2026 (week 53), while Monday 29 December 2025 already starts 2026-W01. 2026 has 53 ISO weeks because it begins on a Thursday; 2025 has only 52.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| year | int | yes | fromisocalendar: the ISO year, 1..9999. |
| week | int | yes | fromisocalendar: 1..52, or 53 in long ISO years. |
| day | int | yes | fromisocalendar: 1 (Monday) .. 7 (Sunday). |
Return value
IsoCalendarDate — A named tuple (year, week, weekday) — weekday 1 = Monday. fromisocalendar returns a date.
Common patterns
Group by ISO week
Key on (ISO year, week) — never (calendar year, week).
key = d.isocalendar()[:2] # (year, week)
Monday of an ISO week
fromisocalendar with day 1.
from datetime import date week_start = date.fromisocalendar(2026, 40, 1)
Examples
1. Named tuple (3.9+)
from datetime import date
date(2026, 9, 29).isocalendar()
Returns
datetime.IsoCalendarDate(year=2026, week=40, weekday=2)2. Access by name
from datetime import date
date(2026, 9, 29).isocalendar().week
Returns
403. It is still a tuple
from datetime import date
tuple(date(2026, 9, 29).isocalendar())
Returns
(2026, 40, 2)4. New Year in the old ISO year
from datetime import date
date(2027, 1, 1).isocalendar()
Returns
datetime.IsoCalendarDate(year=2026, week=53, weekday=5)5. Back to a date
from datetime import date
date.fromisocalendar(2026, 40, 2)
Returns
datetime.date(2026, 9, 29)6. Week 1 can start in December
from datetime import date
date.fromisocalendar(2026, 1, 1)
Returns
datetime.date(2025, 12, 29)7. Validation
from datetime import date
date.fromisocalendar(2025, 53, 1)
Returns
ValueError: Invalid week: 53Pitfalls
1. Pairing the ISO week with the calendar year
Around New Year the week belongs to the other year. Take the year from isocalendar() too.
d.year + week
from datetime import date d = date(2025, 12, 29) (d.year, d.isocalendar().week)
(2025, 1)
ISO year + week
from datetime import date d = date(2025, 12, 29) d.isocalendar()[:2]
(2026, 1)
2. Zero-based weekday
fromisocalendar uses ISO weekdays 1..7, not weekday()'s 0..6.
day 0
from datetime import date date.fromisocalendar(2026, 1, 0)
ValueError: Invalid day: 0 (range is [1, 7])
day 1 = Monday
from datetime import date date.fromisocalendar(2026, 1, 1)
datetime.date(2025, 12, 29)
When to use
Use it
- Weekly reports, sprints and payroll periods
- Parsing and writing YYYY-Www-D week dates
Reach for something else
- US-style weeks starting on Sunday → strftime %U
- Calendar months → date fields
Notes
CPython impl
iso_week1_monday / iso_to_ymd in Modules/_datetimemodule.c; fromisocalendar validates year, then week, then day
Week 53
A year has 53 ISO weeks when it starts on a Thursday, or on a Wednesday in a leap year
Inherited
datetime.isocalendar and datetime.fromisocalendar (midnight) are the same methods
History
isocalendar returned a plain tuple before 3.9; fromisocalendar was added in 3.8
FAQ
d.isocalendar().week for the ISO 8601 week (Monday start, week 1 contains the first Thursday). strftime("%U") and "%W" give other, non-ISO week numbers.