How to Convert a Week Number to a Date Range — The Complete Guide
Someone sends you a schedule. "Delivery in W23." You open your calendar and stare at it. What dates is that, exactly?
Week numbers are used everywhere in project planning, manufacturing, retail, and logistics — but most people only know them as labels. Converting a week number back to actual calendar dates is less intuitive than it should be, and the year-boundary cases trip up even experienced developers.
This guide covers the full conversion: week number to Monday, week number to full date range (Monday–Sunday), and the reverse (date to week number). With code for Python, JavaScript, Excel, and SQL.
What a Week Number Actually Tells You
Before calculating anything, you need to know which week numbering system the number came from.
ISO 8601 (the international standard): Week 1 is the week containing the first Thursday of the year. Weeks run Monday to Sunday. A year has 52 or 53 ISO weeks. Critically — the ISO week year can differ from the calendar year. The last days of December are sometimes in Week 1 of the following year.
US-style: Week 1 contains January 1. Weeks may run Sunday to Saturday or Monday to Sunday depending on the tool. January 1 is always in week 1, no exceptions.
For the rest of this guide, "week number" means ISO 8601 unless stated otherwise. If someone gave you a week number from a US-based tool (like a default Excel WEEKNUM), the conversion formula is different — see the section below.
You also need the year. "Week 23" is meaningless without it. Always treat week numbers as the pair (year, week). Week 23 of 2025 starts on June 2. Week 23 of 2026 starts on June 1. Week 1 of 2026 starts on December 29 of 2025.
The Core Formula: ISO Week Number to Monday
Every ISO week starts on a Monday. To find the Monday of ISO week W in year Y:
Monday = Jan 4 of Y + (W - 1) × 7 days - weekday(Jan 4 of Y) + 1
The reasoning: January 4 is always in ISO Week 1 (by definition — it's within the first four days of the year, which guarantees the week contains a Thursday). Find the Monday of the week containing January 4, then step forward by (W - 1) weeks.
A cleaner equivalent:
Monday of W1 = Jan 4 of Y - weekday(Jan 4 of Y) + 1
Monday of W = Monday of W1 + (W - 1) × 7
where weekday returns 1 for Monday through 7 for Sunday (ISO weekday numbering).
Example: Week 23 of 2026
- January 4, 2026 is a Sunday. ISO weekday = 7.
- Monday of W1: Jan 4 − 7 + 1 = Dec 29, 2025.
- Monday of W23: Dec 29, 2025 + 22 × 7 = Dec 29 + 154 days = June 1, 2026.
- Sunday of W23: June 1 + 6 = June 7, 2026.
Week 23 of 2026 runs from June 1 (Monday) to June 7 (Sunday).
The Year Boundary Trap
The single most common mistake: assuming that Week 1 of year Y always starts in year Y.
It doesn't.
Week 1 of a year is the week containing the first Thursday. If that Thursday is in early January, the Monday of Week 1 can fall in the previous December.
Examples:
| ISO Week | Year | Monday | Sunday |
|---|---|---|---|
| W1 | 2025 | December 30, 2024 | January 5, 2025 |
| W1 | 2026 | December 29, 2025 | January 4, 2026 |
| W1 | 2027 | January 4, 2027 | January 10, 2027 |
| W1 | 2028 | January 3, 2028 | January 9, 2028 |
W1 of 2025 starts in December 2024. W1 of 2026 starts in December 2025.
This means:
- December 29–31, 2025 are in ISO Week 1 of 2026, not 2025.
- If someone says "deliver by W1 2026," the deadline is the week starting December 29, 2025.
The reverse trap also exists: the last days of some years fall in Week 1 of the following year, not the final week of the current year. Always use the ISO week year (the %G format code in Python, isoyear in PostgreSQL) when labelling a week — not the calendar year.
Full Date Range for Any Week Number
Once you have the Monday, the rest of the week is trivial:
| Day | Offset from Monday |
|---|---|
| Monday | +0 |
| Tuesday | +1 |
| Wednesday | +2 |
| Thursday | +3 |
| Friday | +4 |
| Saturday | +5 |
| Sunday | +6 |
The date range for week W is: [Monday, Monday + 6 days].
For working-day purposes (Mon–Fri only): [Monday, Monday + 4 days].
Python
from datetime import date, timedelta
def iso_week_to_monday(year: int, week: int) -> date:
# Jan 4 is always in ISO week 1
jan4 = date(year, 1, 4)
# Move back to Monday of that week
week1_monday = jan4 - timedelta(days=jan4.weekday())
# Step forward to the target week
return week1_monday + timedelta(weeks=week - 1)
def iso_week_to_range(year: int, week: int) -> tuple[date, date]:
monday = iso_week_to_monday(year, week)
sunday = monday + timedelta(days=6)
return monday, sunday
# Examples
monday, sunday = iso_week_to_range(2026, 23)
print(monday) # 2026-06-01
print(sunday) # 2026-06-07
monday, sunday = iso_week_to_range(2026, 1)
print(monday) # 2025-12-29 ← note: starts in 2025
print(sunday) # 2026-01-04
Python also has a built-in for the reverse (date to ISO week):
d = date(2026, 6, 4)
iso_year, iso_week, iso_weekday = d.isocalendar()
print(iso_year, iso_week) # 2026 23
Use d.isocalendar().year (not d.year) when you need the ISO year — they differ at year boundaries.
For the reverse lookup using fromisocalendar (Python 3.8+):
# Get Monday of ISO week 23, 2026 directly
monday = date.fromisocalendar(2026, 23, 1) # weekday 1 = Monday
print(monday) # 2026-06-01
date.fromisocalendar(year, week, weekday) is the cleanest approach if you're on Python 3.8 or later.
JavaScript
JavaScript has no native ISO week support. Manual implementation:
function isoWeekToMonday(year, week) {
// Jan 4 is always in ISO week 1
const jan4 = new Date(year, 0, 4)
const dayOfWeek = jan4.getDay() || 7 // convert Sun=0 to 7
const week1Monday = new Date(jan4)
week1Monday.setDate(jan4.getDate() - dayOfWeek + 1)
const monday = new Date(week1Monday)
monday.setDate(week1Monday.getDate() + (week - 1) * 7)
return monday
}
function isoWeekToRange(year, week) {
const monday = isoWeekToMonday(year, week)
const sunday = new Date(monday)
sunday.setDate(monday.getDate() + 6)
return { monday, sunday }
}
// Examples
const { monday, sunday } = isoWeekToRange(2026, 23)
console.log(monday.toISOString().slice(0, 10)) // 2026-06-01
console.log(sunday.toISOString().slice(0, 10)) // 2026-06-07
const w1 = isoWeekToRange(2026, 1)
console.log(w1.monday.toISOString().slice(0, 10)) // 2025-12-29
Using date-fns:
import { setISOWeek, setISOWeekYear, startOfISOWeek, endOfISOWeek } from 'date-fns'
function isoWeekToRange(year, week) {
let d = new Date(year, 0, 4) // any date in the target year
d = setISOWeekYear(d, year)
d = setISOWeek(d, week)
return {
monday: startOfISOWeek(d),
sunday: endOfISOWeek(d)
}
}
date-fns handles all the edge cases correctly and is the recommended approach for production code.
Excel and Google Sheets
Excel has no direct "week number to date" function, but you can construct it with a formula.
Monday of ISO Week W in Year Y:
=DATE(Y,1,4) - WEEKDAY(DATE(Y,1,4),2) + 1 + (W-1)*7
Breaking this down:
DATE(Y,1,4)— January 4 of the yearWEEKDAY(DATE(Y,1,4),2)— day of week where Monday=1, Sunday=7- Subtracting gives you the Monday of Week 1
- Adding
(W-1)*7moves to the target week
For a full range, the Sunday is simply:
=Monday_formula + 6
Example in a sheet (where A1 = year, B1 = week number):
Monday: =DATE(A1,1,4) - WEEKDAY(DATE(A1,1,4),2) + 1 + (B1-1)*7
Sunday: =Monday_cell + 6
Format both cells as dates. For year 2026, week 1, this returns December 29, 2025 for Monday — which is correct.
Reverse (date to ISO week number): Use ISOWEEKNUM(date). For the ISO year, use the workaround from the ISOWEEKNUM article since Excel has no native ISO year function.
SQL
PostgreSQL has the most complete ISO support:
-- Monday of ISO week W in year Y
SELECT
make_date(2026, 1, 4)
+ (23 - 1) * 7 -- step to week 23
- EXTRACT(isodow FROM make_date(2026, 1, 4))::int + 1
AS week_monday;
-- 2026-06-01
-- Or more cleanly using generate_series for a range lookup
SELECT
d::date AS week_monday,
(d + 6)::date AS week_sunday,
EXTRACT(isoyear FROM d) AS iso_year,
EXTRACT(week FROM d) AS iso_week
FROM generate_series(
DATE '2026-01-01',
DATE '2026-12-31',
INTERVAL '7 days'
) d
WHERE EXTRACT(week FROM d) = 23
AND EXTRACT(isoyear FROM d) = 2026;
A cleaner approach using PostgreSQL's to_date with ISO format codes:
-- Convert ISO year + week to Monday
SELECT to_date('2026' || '23' || '1', 'IYYYIWid') AS monday;
-- 2026-06-01
-- Format: IYYY=ISO year, IW=ISO week, id=ISO day (1=Monday)
This is the simplest PostgreSQL approach: format a string YYYYWWD and parse it with ISO format codes.
MySQL:
-- Monday of ISO week 23, 2026
SELECT STR_TO_DATE('202623 Monday', '%X%V %W');
-- 2026-06-01
-- Or step-based:
SELECT DATE_ADD(
DATE_ADD(STR_TO_DATE('2026-01-04', '%Y-%m-%d'),
INTERVAL (-(WEEKDAY(STR_TO_DATE('2026-01-04', '%Y-%m-%d')))) DAY),
INTERVAL (23 - 1) * 7 DAY
) AS week_monday;
SQL Server:
-- Monday of ISO week 23, 2026
DECLARE @year INT = 2026, @week INT = 23
SELECT DATEADD(
DAY,
(@week - 1) * 7
- (DATEPART(WEEKDAY, DATEFROMPARTS(@year, 1, 4)) + 5) % 7,
DATEFROMPARTS(@year, 1, 4)
) AS week_monday;
-- 2026-06-01
US-Style Week Number to Dates
If your week number came from a US-style system (Week 1 = contains January 1, weeks start Sunday or Monday), the formula is simpler because there's no year-boundary issue:
Week start (Sunday-based):
Week_start = DATE(Y, 1, 1) + (W - 1) × 7 - WEEKDAY(DATE(Y, 1, 1), 1)
where WEEKDAY returns 1 for Sunday through 7 for Saturday.
But US week numbers are far less common in scheduling and logistics than ISO. If someone hands you a week number without specifying the system, assume ISO — especially in international or European business contexts.
2026 Quick Reference: ISO Weeks 1–10 and 48–53
| ISO Week | Year | Monday | Sunday |
|---|---|---|---|
| W1 | 2026 | Dec 29, 2025 | Jan 4, 2026 |
| W2 | 2026 | Jan 5, 2026 | Jan 11, 2026 |
| W3 | 2026 | Jan 12, 2026 | Jan 18, 2026 |
| W4 | 2026 | Jan 19, 2026 | Jan 25, 2026 |
| W5 | 2026 | Jan 26, 2026 | Feb 1, 2026 |
| W6 | 2026 | Feb 2, 2026 | Feb 8, 2026 |
| W7 | 2026 | Feb 9, 2026 | Feb 15, 2026 |
| W8 | 2026 | Feb 16, 2026 | Feb 22, 2026 |
| W9 | 2026 | Feb 23, 2026 | Mar 1, 2026 |
| W10 | 2026 | Mar 2, 2026 | Mar 8, 2026 |
| ... | |||
| W48 | 2026 | Nov 23, 2026 | Nov 29, 2026 |
| W49 | 2026 | Nov 30, 2026 | Dec 6, 2026 |
| W50 | 2026 | Dec 7, 2026 | Dec 13, 2026 |
| W51 | 2026 | Dec 14, 2026 | Dec 20, 2026 |
| W52 | 2026 | Dec 21, 2026 | Dec 27, 2026 |
| W53 | 2026 | Dec 28, 2026 | Jan 3, 2027 |
Note W1 of 2026 starts December 29, 2025. Note W53 of 2026 ends January 3, 2027 — 2026 is a 53-week year.
Common Mistakes Summarised
Not including the year. "Week 8" is ambiguous. Always use the format 2026-W08 or equivalent.
Using calendar year instead of ISO week year. December 29, 2025 is in ISO Week 1 of 2026, not 2025. Storing it under 2025 puts it in the wrong bucket.
Assuming Week 1 starts January 1. It starts December 29, 30, or 31 in many years. If you need January 1 to always be in Week 1, you're using the US system, not ISO.
Off-by-one on the Monday formula. The Jan 4 anchor is important — not Jan 1 (which might be in the previous year's last week). Using Jan 1 as the anchor gives wrong results in years where Jan 1 falls late in the week.
Not testing year-boundary dates. Any date-handling code should be tested against December 28–31 and January 1–4. These four to seven days are where all the edge cases live.
Use the ISO Week Number Calculator to look up the date range for any week number, or check the current week number and today's ISO week date range.