Short answer

API and embeddable week widget

Documented JSON endpoints and a tracker-free ISO week widget.

Short answer

The API validates every input and returns stable error codes; the widget uses no third-party fonts.

How it works

CORS is restrictive by default and the full contract is available as OpenAPI.

JavaScript: a calendar date without a timezone shift

This complete recipe accepts only YYYY-MM-DD in 1900–2100, rejects impossible days and uses UTC calendar arithmetic. Convert a timestamp to a date in your chosen IANA timezone first. 2027-01-01 returns { isoYear: 2026, isoWeek: 53, isoWeekday: 5 }.

Executed with Node.js 24.19.0, Python 3.14.3 and SQLite 3.53.3. The displayed recipes are checked against the calendar core for all 73,414 dates in 1900–2100 and eight invalid inputs.

function isoWeekDate(value) {
  if (typeof value !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(value))
    throw new RangeError("Use a date in YYYY-MM-DD format");
  const [year, month, day] = value.split("-").map(Number);
  if (year < 1900 || year > 2100) throw new RangeError("Supported years: 1900–2100");
  const date = new Date(Date.UTC(year, month - 1, day));
  if (date.toISOString().slice(0, 10) !== value) throw new RangeError("Invalid date");
  const isoWeekday = date.getUTCDay() || 7;
  date.setUTCDate(date.getUTCDate() + 4 - isoWeekday);
  const isoYear = date.getUTCFullYear();
  const isoWeek = Math.ceil(((date.getTime() - Date.UTC(isoYear, 0, 1)) / 86400000 + 1) / 7);
  return { isoYear, isoWeek, isoWeekday };
}
isoWeekDate("2027-01-01");

Python: date.isocalendar()

Python date.isocalendar() returns ISO year, week and weekday together. This recipe also checks the input shape and year range. Supply a calendar date, not a timestamp.

from datetime import date

def iso_week_date(value):
    day = date.fromisoformat(value)
    if day.isoformat() != value or not 1900 <= day.year <= 2100:
        raise ValueError("Use YYYY-MM-DD, years 1900–2100")
    year, week, weekday = day.isocalendar()
    return {"isoYear": year, "isoWeek": week, "isoWeekday": weekday}
print(iso_week_date("2027-01-01"))

Python: datetime.date ↗

SQLite: %G / %V / %u

SQLite: bind :date as a text parameter instead of concatenating SQL. Pair %G with %V; %Y and %W are not equivalent. The WHERE clause rejects invalid or non-normalized dates. Old SQLite versions without %G/%V are unsuitable.

SELECT CAST(strftime('%G', :date) AS INTEGER) AS isoYear,
       CAST(strftime('%V', :date) AS INTEGER) AS isoWeek,
       CAST(strftime('%u', :date) AS INTEGER) AS isoWeekday
WHERE length(:date) = 10
  AND :date GLOB '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
  AND substr(:date, 1, 4) BETWEEN '1900' AND '2100'
  AND date(:date, '+0 days') = :date;

SQLite: date and time functions ↗

Other SQL dialects need separate recipes

These three examples use vendor-documented functions but were not executed here in PostgreSQL, MySQL or SQL Server. Each should return ISO year 2026 and week 53 for 2027-01-01. Test your engine version before use. Establish a business timezone before grouping timestamps.

PostgreSQL: ISOYEAR + WEEK

SELECT EXTRACT(ISOYEAR FROM d)::int AS iso_year,
       EXTRACT(WEEK FROM d)::int AS iso_week
FROM (VALUES (DATE '2027-01-01')) AS dates(d);

PostgreSQL: date/time fields ↗

MySQL: YEARWEEK(date, 3)

SELECT YEARWEEK('2027-01-01', 3) DIV 100 AS iso_year,
       MOD(YEARWEEK('2027-01-01', 3), 100) AS iso_week;

MySQL: YEARWEEK ↗

SQL Server: iso_week

DECLARE @d date = DATEFROMPARTS(2027, 1, 1);
SELECT CASE
         WHEN MONTH(@d) = 1 AND DATEPART(iso_week, @d) >= 52 THEN YEAR(@d) - 1
         WHEN MONTH(@d) = 12 AND DATEPART(iso_week, @d) = 1 THEN YEAR(@d) + 1
         ELSE YEAR(@d)
       END AS iso_year,
       DATEPART(iso_week, @d) AS iso_week;

Microsoft: DATEPART ↗

REST API v1

CORS is restrictive by default and the full contract is available as OpenAPI.

OpenAPI 3.1 JSON Widget

fetch("https://kalenderwoche.info/api/v1/week-from-date?date=2026-08-05")
  .then(response => response.json())