"use strict"; // Day-number kernel: Howard Hinnant, "chrono-Compatible Low-Level Date Algorithms", // https://howardhinnant.github.io/date_algorithms.html (days_from_civil). The weekday is // derived as the day-number modulo 7, calibrated against the known fact that 1970-01-01 // (day-number 0 in this kernel) was a Thursday, and cross-checked against 2000-01-01 (a // Saturday). No host clock, no Date.now(), no time zone database. function daysFromCivil(y, m, d) { y = m <= 2 ? y - 1 : y; const era = Math.floor((y >= 0 ? y : y - 399) / 400); const yoe = y - era * 400; const doy = Math.floor((153 * (m + (m > 2 ? -3 : 9)) + 2) / 5) + d - 1; const doe = yoe * 365 + Math.floor(yoe / 4) - Math.floor(yoe / 100) + doy; return era * 146097 + doe - 719468; } function isLeapGregorian(y) { return (y % 4 === 0 && y % 100 !== 0) || (y % 400 === 0); } function daysInMonth(y, m) { const dim = [31, isLeapGregorian(y) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; return dim[m - 1]; } function parseISODate(s, label) { const m = /^(-?\d{4})-(\d{2})-(\d{2})$/.exec(String(s).trim()); if (!m) throw new Error((label || "date") + " must be an ISO 8601 date YYYY-MM-DD, got: " + s); const year = parseInt(m[1], 10), month = parseInt(m[2], 10), day = parseInt(m[3], 10); if (month < 1 || month > 12) throw new Error((label || "date") + " month out of range 1-12"); if (day < 1 || day > daysInMonth(year, month)) throw new Error((label || "date") + " day out of range for that month"); return { year, month, day }; } const WEEKDAY_NAMES = ["Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday"]; function weekdayName(y, m, d) { const z = daysFromCivil(y, m, d); return WEEKDAY_NAMES[((z % 7) + 7) % 7]; } module.exports = { slug: "weekday-of-date", title: "Weekday of a date", deck_category: "dates", description: "Computes the day of the week for any proleptic Gregorian calendar date.", inputs: [ { name: "date", type: "string", format: "date", required: true, description: "ISO 8601 date, YYYY-MM-DD" } ], outputs: [ { name: "weekday", description: "Name of the day of the week" } ], steps: [ "Parse the date as a proleptic Gregorian civil date (year, month, day).", "Compute its day-number using the Hinnant days_from_civil algorithm (equivalent to a Julian Day Number offset), which counts whole days since 1970-01-01.", "Take the day-number modulo 7. 1970-01-01 has day-number 0 and was a Thursday, so the remainder indexes into the cycle starting at Thursday.", "Map the remainder to a weekday name using that calibrated cycle." ], constants: [ { name: "anchor_date", value: "1970-01-01", unit: "date", source: 0 }, { name: "anchor_weekday", value: "Thursday", unit: "weekday name", source: 0 } ], sources: [ { kind: "url", value: "https://howardhinnant.github.io/date_algorithms.html", title: "chrono-Compatible Low-Level Date Algorithms", publisher: "Howard Hinnant", retrieved_utc: "2026-09-30T19:41:35Z", note: "days_from_civil day-number kernel; 1970-01-01 is day-number 0 and is independently known to have been a Thursday" } ], disclaimer: null, questionText(inputs) { return "What day of the week is " + inputs.date + "?"; }, run(inputs) { const d = parseISODate(inputs.date, "date"); const weekday = weekdayName(d.year, d.month, d.day); return { answer: weekday, values: { weekday } }; }, examples: [ { name: "worked example", inputs: { date: "2000-01-01" }, expected: { answer: "Saturday" }, check: "2000-01-01 being a Saturday is a widely documented calendar fact" }, { name: "test vector: Unix epoch", inputs: { date: "1970-01-01" }, expected: { answer: "Thursday" }, check: "1970-01-01, the Unix epoch, is independently documented as a Thursday" }, { name: "test vector: recent date", inputs: { date: "2024-01-01" }, expected: { answer: "Monday" }, check: "2024-01-01 being a Monday is a widely documented calendar fact" } ] };