How to Get Week Number from Date in TypeScript (ISO 8601)

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
Command Prompt output of a TypeScript getISOWeek function for US holidays in 2026
New Year’s Day 2026 falls in week 1, and Columbus Day (October 12) falls in week 42.

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
Command Prompt output of TypeScript ISO week labels for dates around New Year 2026 and 2027
Monday, December 29, 2025 is already 2026-W01, while January 1-3, 2027 still belong to 2026-W53.

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
Command Prompt output of TypeScript week numbers for a UTC date string read with local and UTC getters
Local getters return week 1, while UTC getters and a local-time parse give the correct 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}
Command Prompt output of date-fns getISOWeek, getWeek and Intl.Locale weekInfo in TypeScript
date-fns 4.4.0 gives week 53 of 2026 for January 1, 2027, and en-US week info starts on Sunday (7).

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

MethodWeek startsWeek 1 rule
Custom getISOWeek()MondayHolds the first Thursday
Custom getUSWeek()SundayHolds January 1
date-fns getISOWeek()MondayHolds 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.

Where is the Date object documented?

See