WhatWeek

JavaScript Week Number

Safe ISO week helper

This dependency-free helper accepts a valid YYYY-MM-DD calendar date, with years 0001–9999. It returns the ISO week-year and week number separately and rejects impossible dates instead of silently rolling them forward.

function getIsoWeek(dateString) {
  if (typeof dateString !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
    throw new RangeError("Use a valid YYYY-MM-DD calendar date.");
  }
  const [year, month, day] = dateString.split("-").map(Number);
  const date = new Date(0);
  date.setUTCFullYear(year, month - 1, day);
  if (year < 1 || date.getUTCFullYear() !== year ||
      date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {
    throw new RangeError("Use a valid YYYY-MM-DD calendar date.");
  }

  // Thursday determines the ISO week-year, not the input's calendar year.
  const weekday = date.getUTCDay() || 7;
  date.setUTCDate(date.getUTCDate() + 4 - weekday);
  const weekYear = date.getUTCFullYear();
  const weekOne = new Date(0);
  weekOne.setUTCFullYear(weekYear, 0, 4);
  const weekOneDay = weekOne.getUTCDay() || 7;
  weekOne.setUTCDate(weekOne.getUTCDate() + 1 - weekOneDay);
  const weekNumber = Math.floor((date.getTime() - weekOne.getTime()) / 604800000) + 1;
  return { weekYear, weekNumber };
}
const result = getIsoWeek("2027-01-01");
console.log(result);
// { weekYear: 2026, weekNumber: 53 }
getIsoWeek("2027-01-04");
// { weekYear: 2027, weekNumber: 1 }
// getIsoWeek("2026-02-29") throws RangeError: 2026 is not a leap year.

Safe date parsing

Here the input is a calendar date, not an instant. The helper uses UTC setters and getters only as a timezone-neutral way to do calendar arithmetic; it does not convert your date into another timezone.

JavaScript parses a date-only string such as "2027-01-01" as UTC. Reading that result with local getters can produce the previous date in timezones west of UTC. Do not mix local getters with UTC parsing.

The validation round-trip also catches values such as 2026-02-29 that date constructors may normalize. setUTCFullYear preserves years below 100 without the 1900-based adjustment made by Date.UTC.

Timezone warning

For current-week features, calculate the user's local calendar date first, then calculate the week number from that date.

Edge-case test table

Expected ISO week dates and ranges for JavaScript test inputs
Input Expected ISO week date Monday–Sunday range
2024-02-29 2024-W09-4 2024-02-26 to 2024-03-03
2025-12-29 2026-W01-1 2025-12-29 to 2026-01-04
2026-12-28 2026-W53-1 2026-12-28 to 2027-01-03
2027-01-01 2026-W53-5 2026-12-28 to 2027-01-03
2027-01-03 2026-W53-7 2026-12-28 to 2027-01-03
2027-01-04 2027-W01-1 2027-01-04 to 2027-01-10

Download and run the boundary tests

The JSON fixture contains 17 leap-day and New Year examples, including every date in 2026-W53. Expected fields include the week-year, week number, ISO weekday (Monday = 1), full ISO notation, and inclusive Monday–Sunday range.

Download ISO boundary examples (JSON), save the helper and test below as verify-weeks.mjs, and run node verify-weeks.mjs from that folder.

// Save the JSON download beside this file as:
// whatweek-iso-week-boundary-examples.json
// Add the getIsoWeek helper above, then run: node verify-weeks.mjs
import { readFile } from "node:fs/promises";

const fixture = JSON.parse(await readFile(
  new URL("./whatweek-iso-week-boundary-examples.json", import.meta.url),
  "utf8"
));
for (const expected of fixture.cases) {
  const actual = getIsoWeek(expected.date);
  if (actual.weekYear !== expected.weekYear || actual.weekNumber !== expected.weekNumber) {
    throw new Error("ISO week mismatch for " + expected.date);
  }
}
console.log(fixture.cases.length + " ISO week examples passed.");

The sample runner checks the helper's two output fields. When testing a date-range implementation, also compare weekStarts and weekEnds against the fixture. The same dates are available as CSV and Excel formula examples.

API option

Use the WhatWeek API when you need stable JSON responses for applications or internal tools.

For the 2026–2027 transition, see Week 53, 2026 and the 2027 week-number calendar.

JavaScript date behavior: MDN Date reference and setUTCFullYear.