You can get the week number from a date in TypeScript with a short function: move the date to the Thursday of its week, then count 7-day blocks from January 1. That gives the ISO 8601 week, where weeks start on Monday:
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
const week = Math.ceil(((d.getTime() - Date.UTC(d.getUTCFullYear(), 0, 1)) / 86_400_000 + 1) / 7);
JavaScript’s Date has no built-in week method, so I wrote and compiled every example here in strict mode with TypeScript 7.0.2 and Node.js v22.22.2. The outputs come straight from my console.
Below you’ll find the ISO function, the year-end edge cases, a US Sunday-start version, the UTC trap and the date-fns shortcut.
Get the ISO week number from a date in TypeScript
ISO 8601 says week 1 is the week that holds the year’s first Thursday. Jumping to Thursday first means the year of that Thursday is also the week’s year:
function getISOWeek(date: Date): { year: number; week: number } {
// copy the calendar date into UTC so DST and time zones can't shift it
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const day = d.getUTCDay() || 7; // Monday = 1 ... Sunday = 7
d.setUTCDate(d.getUTCDate() + 4 - day); // jump to the Thursday of this week
const yearStart = Date.UTC(d.getUTCFullYear(), 0, 1);
const week = Math.ceil(((d.getTime() - yearStart) / 86_400_000 + 1) / 7);
return { year: d.getUTCFullYear(), week };
}
const dates: [string, Date][] = [
["New Year's Day", new Date(2026, 0, 1)],
["Tax Day", new Date(2026, 3, 15)],
["Independence Day", new Date(2026, 6, 4)],
["Columbus Day", new Date(2026, 9, 12)],
["Thanksgiving", new Date(2026, 10, 26)],
];
for (const [label, date] of dates) {
const { week } = getISOWeek(date);
console.log(`${label.padEnd(17)} ${date.toDateString()} week ${week}`);
}
Output:
New Year's Day Thu Jan 01 2026 week 1
Tax Day Wed Apr 15 2026 week 16
Independence Day Sat Jul 04 2026 week 27
Columbus Day Mon Oct 12 2026 week 42
Thanksgiving Thu Nov 26 2026 week 48

The function copies the date, so your original Date never changes. Building dates with month indexes is covered in converting a string to a date in TypeScript.
Why can January 1 be in week 53?
Days near New Year can belong to the neighboring ISO year. That’s why the function returns the week-year too, and you should store both together:
function getISOWeek(date: Date): { year: number; week: number } {
// copy the calendar date into UTC so DST and time zones can't shift it
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const day = d.getUTCDay() || 7; // Monday = 1 ... Sunday = 7
d.setUTCDate(d.getUTCDate() + 4 - day); // jump to the Thursday of this week
const yearStart = Date.UTC(d.getUTCFullYear(), 0, 1);
const week = Math.ceil(((d.getTime() - yearStart) / 86_400_000 + 1) / 7);
return { year: d.getUTCFullYear(), week };
}
const isoLabel = (d: Date): string => {
const { year, week } = getISOWeek(d);
return `${year}-W${String(week).padStart(2, "0")}`;
};
const tricky = [
new Date(2025, 11, 28), new Date(2025, 11, 29), new Date(2026, 0, 1),
new Date(2026, 11, 28), new Date(2026, 11, 31), new Date(2027, 0, 1),
new Date(2027, 0, 3), new Date(2027, 0, 4),
];
for (const d of tricky) {
console.log(`${d.toDateString()} -> ${isoLabel(d)}`);
}
Output:
Sun Dec 28 2025 -> 2025-W52
Mon Dec 29 2025 -> 2026-W01
Thu Jan 01 2026 -> 2026-W01
Mon Dec 28 2026 -> 2026-W53
Thu Dec 31 2026 -> 2026-W53
Fri Jan 01 2027 -> 2026-W53
Sun Jan 03 2027 -> 2026-W53
Mon Jan 04 2027 -> 2027-W01

2026 starts on a Thursday, so it has 53 ISO weeks. Use the returned year, not getFullYear(), when you print labels like 2026-W53, and sort or compare dates in TypeScript by that pair.
If you only need the calendar year from a date, see extracting the year from a date in TypeScript.
Sunday-start week numbers for US calendars
Many US calendars and reports count weeks differently: Sunday starts the week and week 1 is whichever week holds January 1. Here’s that rule next to ISO:
function getISOWeek(date: Date): { year: number; week: number } {
// copy the calendar date into UTC so DST and time zones can't shift it
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
const day = d.getUTCDay() || 7; // Monday = 1 ... Sunday = 7
d.setUTCDate(d.getUTCDate() + 4 - day); // jump to the Thursday of this week
const yearStart = Date.UTC(d.getUTCFullYear(), 0, 1);
const week = Math.ceil(((d.getTime() - yearStart) / 86_400_000 + 1) / 7);
return { year: d.getUTCFullYear(), week };
}
// US style: weeks start on Sunday and week 1 is the week that holds January 1
function getUSWeek(date: Date): number {
const y = date.getFullYear();
const jan1Day = new Date(y, 0, 1).getDay(); // 0 = Sunday
const dayOfYear = (Date.UTC(y, date.getMonth(), date.getDate()) - Date.UTC(y, 0, 1)) / 86_400_000;
return Math.floor((dayOfYear + jan1Day) / 7) + 1;
}
const days = [
new Date(2026, 0, 1), new Date(2026, 0, 3), new Date(2026, 0, 4),
new Date(2026, 9, 11), new Date(2026, 9, 12), new Date(2026, 11, 31),
];
console.log("date US ISO");
for (const d of days) {
console.log(`${d.toDateString()} ${String(getUSWeek(d)).padStart(2)} ${String(getISOWeek(d).week).padStart(3)}`);
}
Output:
date US ISO
Thu Jan 01 2026 1 1
Sat Jan 03 2026 1 1
Sun Jan 04 2026 2 1
Sun Oct 11 2026 42 41
Mon Oct 12 2026 42 42
Thu Dec 31 2026 53 53
The two systems split on Sundays. Sunday, October 11, 2026 is US week 42 but ISO week 41, and January 4, 2026 is US week 2 but ISO week 1.
Pick one scheme per report and label it, because a dashboard mixing them drifts by a week. For day math, I use calculating days between dates in TypeScript.
Avoid UTC vs local time bugs
A date-only string such as "2026-01-05" is parsed as UTC midnight. On a machine in Chicago, local getters then see Sunday, January 4:
declare const process: { env: Record<string, string | undefined> };
process.env.TZ = "America/Chicago"; // simulate a server in Chicago
function weekLocal(date: Date): number {
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
return Math.ceil(((d.getTime() - Date.UTC(d.getUTCFullYear(), 0, 1)) / 86_400_000 + 1) / 7);
}
function weekUTC(date: Date): number {
const d = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));
d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));
return Math.ceil(((d.getTime() - Date.UTC(d.getUTCFullYear(), 0, 1)) / 86_400_000 + 1) / 7);
}
const fromApi = new Date("2026-01-05"); // date-only string = UTC midnight
console.log("Parsed as: ", fromApi.toString());
console.log("Local getters: week", weekLocal(fromApi));
console.log("UTC getters: week", weekUTC(fromApi));
console.log("Local parse fix: week", weekLocal(new Date("2026-01-05T00:00:00")));
Output:
Parsed as: Sun Jan 04 2026 18:00:00 GMT-0600 (Central Standard Time)
Local getters: week 1
UTC getters: week 2
Local parse fix: week 2

Use UTC getters for dates that arrive as YYYY-MM-DD, or add a time so the string parses as local. More on this in converting dates to UTC in TypeScript.
Bad input such as "2026-13-01" gives an Invalid Date and a NaN week, so guard it first with a TypeScript invalid date check.
Get the week number with date-fns or Intl.Locale
If date-fns is already in your project, getISOWeek() and getISOWeekYear() do the same job. Plain getWeek() uses Sunday-start weeks unless you pass options:
import { getISOWeek, getISOWeekYear, getWeek } from "date-fns";
const newYear = new Date(2027, 0, 1);
console.log("getISOWeek: ", getISOWeek(newYear), "of", getISOWeekYear(newYear));
console.log("getWeek (US): ", getWeek(newYear));
console.log("getWeek Dec 31:", getWeek(new Date(2026, 11, 31)));
console.log("getWeek ISO opts:", getWeek(newYear, { weekStartsOn: 1, firstWeekContainsDate: 4 }));
type WeekInfo = { firstDay: number; weekend: number[]; minimalDays: number };
for (const tag of ["en-US", "en-GB"]) {
const loc = new Intl.Locale(tag) as Intl.Locale & { weekInfo?: WeekInfo; getWeekInfo?: () => WeekInfo };
const info = loc.getWeekInfo?.() ?? loc.weekInfo;
console.log(tag, JSON.stringify(info));
}
Output:
getISOWeek: 53 of 2026
getWeek (US): 1
getWeek Dec 31: 1
getWeek ISO opts: 53
en-US {"firstDay":7,"weekend":[6,7],"minimalDays":1}
en-GB {"firstDay":1,"weekend":[6,7],"minimalDays":4}

Note that getWeek() calls December 31, 2026 week 1, unlike my US function. Intl.Locale doesn’t compute week numbers; it only reports the locale’s first day and minimal days.
On Node.js 22, getWeekInfo() isn’t available, so the code falls back to the older weekInfo property. To list the seven days of a week, step from its Monday with adding days to a date in TypeScript.
Week number methods compared
| Method | Week starts | Week 1 rule |
|---|---|---|
Custom getISOWeek() | Monday | Holds the first Thursday |
Custom getUSWeek() | Sunday | Holds January 1 |
date-fns getISOWeek() | Monday | Holds the first Thursday |
date-fns getWeek() | Sunday (default) | Holds January 1 |
Showing the result to users? Formatting dates in TypeScript helps you print week labels and date ranges.
Week numbers rarely travel alone, so these TypeScript date guides cover the jobs that usually come next:
Frequently asked questions
Does TypeScript have a built-in getWeek() method?
No. The Date object has no week method, so you write a small function or use a library such as date-fns.
What is an ISO 8601 week number?
It’s a week from 1 to 53 that starts on Monday. Week 1 is the week containing the year’s first Thursday, which is also the week containing January 4.
How do I get the current week number?
Pass new Date() to the getISOWeek() function. It reads today’s date on the machine running the code.
Why does my week number change between time zones?
Date-only strings parse as UTC midnight, which is the previous day in US time zones. Use UTC getters or parse with a time.
Which years have 53 ISO weeks?
Years that start on a Thursday, plus leap years that start on a Wednesday. 2026 starts on a Thursday, so it has 53 weeks.