Functional Weave
Code in TypeScript

dates.day-of-week

The ISO 8601 day of the week for a date: 1 is Monday through 7 is Sunday.

1.0.0 · published 2026-10-03 by charlie · Anterra

Pinned by 20 tests, run in TypeScript, Python and Rust.

What it does

ISO numbering, 1 = Monday to 7 = Sunday. The alternatives are all off by something: JavaScript's getDay() is 0 = Sunday, Python's weekday() is 0 = Monday and isoweekday() is 1 = Monday. Fixing one convention across the three languages is the point, and it makes a weekend test read as day >= 6 everywhere.

It depends on dates.add-days rather than re-deriving days-from-civil: the calendar kernel has one home in the registry, so a fix to it is a fix everywhere.

For example

  • dayOfWeek(1970-01-01) → 4 the epoch itself, 1 January 1970, was a Thursday
  • dayOfWeek(2026-09-16) → 3 an ordinary Wednesday
  • dayOfWeek(2026-09-19) → 6 Saturday is 6

The function

The same function in TypeScript, Python and Rust, pinned by the same tests. Pick your language; the choice follows you around the registry.

export function dayOfWeek(iso: string): number
isodateISO date, YYYY-MM-DD
returnsint1 = Monday ... 7 = Sunday

Your code names it in one line, in the file that uses it

import { dayOfWeek } from "#fune/dates.day-of-week@^1";
impl/typescript.ts · 35 lines · open · raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { epochDayFromIso } from "./dates_add_days.ts";  ← from dates.add-days ^1.0.0 · built alongside by fune

/**
 * The ISO 8601 day of the week: 1 = Monday through 7 = Sunday.
 *
 * ISO numbering rather than the 0 = Sunday that JavaScript's
 * Date.getDay() uses, because ISO is what the rest of the business world
 * means by "day 1" and because a weekend test becomes `day >= 6` instead of
 * `day === 0 || day === 6`.
 */
export function dayOfWeek(iso: string): number {
  // 1970-01-01, epoch day 0, was a Thursday. Shifting by 3 moves the origin of
  // the cycle to Monday so that the remainder is already ISO numbering.
  const epochDay = epochDayFromIso(iso);
  return ((((epochDay + 3) % 7) + 7) % 7) + 1;
}

/** True for Saturday and Sunday. */
export function isWeekend(iso: string): boolean {
  return dayOfWeek(iso) >= 6;
}

/** True for Monday to Friday. Says nothing about public holidays. */
export function isWeekday(iso: string): boolean {
  return dayOfWeek(iso) <= 5;
}

const NAMES = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];

/** The English name, for logs and labels. Not localised, deliberately: a
 * capability that needed locale data would need a locale argument and a data
 * file to pin it. */
export function dayName(iso: string): string {
  return NAMES[dayOfWeek(iso) - 1];
}

Install

fune build

With that line in your source, in a TypeScript project (language typescript in fune.project), fune build resolves it and its 1 dependency, pins them in fune.lock, downloads only the TypeScript package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. Or pin a range in fune.project and build in one step:

fune add dates.day-of-week
Download for TypeScript dates.day-of-week-1.0.0-typescript.fune · 5,788 bytes sha256 c15aa52a6db2fe4d222c0cdbe6e8b8c376e6a4e782a09173b0b6f1af8ff86178

The manifest, vectors and README with only the TypeScript implementation. Install it without the registry with fune add ./dates.day-of-week-1.0.0-typescript.fune, or fetch it from a terminal with fune pull dates.day-of-week@1.0.0:typescript.

The whole function, every language, is one file too: dates.day-of-week-1.0.0.fune, 8,714 bytes, sha256 976f7dbb98c070afdfb65de0f361d7b00c14159b37a0ee2615f23fc535081d4a. It installs into a project of any language.

Customise it in your app

The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.

before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.

// fune: before dates.day-of-week

after — your function gets the result and the arguments, and returns the final result.

// fune: after dates.day-of-week

replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.

// fune: replace dates.add-days in dates.day-of-week

step — your function runs at a numbered point inside the function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show dates.day-of-week --steps.

// fune: step dates.day-of-week after <n|label>

Tests

A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.

CaseArgumentsExpected
the epoch itself, 1 January 1970, was a Thursday 1970-01-01 → 4
an ordinary Wednesday 2026-09-16 → 3
Saturday is 6 2026-09-19 → 6
Sunday is 7, not 0 2026-09-20 → 7
Monday is 1 2026-09-21 → 1
1 January 2000 was a Saturday 2000-01-01 → 6
31 December 1999 was a Friday 1999-12-31 → 5
1 January 1900 was a Monday, well before the epoch 1900-01-01 → 1
the 2024 leap day was a Thursday 2024-02-29 → 4
1 March 1900 was a Thursday because 1900 had no leap day 1900-03-01 → 4
Show the other 10 tests
CaseArgumentsExpected
1 March 2000 was a Wednesday because 2000 did have one 2000-03-01 → 3
the first supported date, 1 January 0001, is a Monday 0001-01-01 → 1
the last supported date, 31 December 9999, is a Friday 9999-12-31 → 5
a slash-separated date is an error, not a guess 16/09/2026 → error: is not an ISO date
an unpadded month is an error 2026-9-16 → error: is not an ISO date
an empty string is an error → error: is not an ISO date
30 February is not a real date 2026-02-30 → error: is not a real calendar date
29 February in a non-leap year is rejected 2026-02-29 → error: is not a real calendar date
month 00 is rejected 2026-00-10 → error: is not a real calendar date
day 00 is rejected 2026-09-00 → error: is not a real calendar date

More from the author

The day number comes from the epoch day, not from a table, so it is correct for dates before 1970 (where the day number is negative) as well as after. Getting the sign right matters: a plain remainder in Rust or TypeScript keeps the sign of the dividend and would return a negative weekday for 1900 dates, so both use a floored remainder.

It says nothing about public holidays. Working days are dates.business-days-between, which takes the holiday list as an argument because no library knows your company's.

Files

PathBytes
README.md995
impl/python.py1,264
impl/rust.rs1,493
impl/typescript.ts1,293
vectors.json1,977