Skip to main content

date

ISO-8601 string parsing and duration-branded numbers.

import type {
  Year, Month, Day, TimeOf, IsLeapYear, DaysInMonth, DayOfWeek,
  Duration, Milliseconds, Seconds, Minutes, Hours, Days, Weeks, AnyDuration,
} from '@gentleduck/ttest/date'

ISO-8601 string types ('2026-04-23', '2026-04-23T12:34:56Z') plus branded duration scalars.

Year

type Year<S extends string>

Extract year from a date string.

type Y = Year<'2026-04-23'>  // 2026

Month

type Month<S extends string>

Extract month (1–12, leading zero stripped).

type M = Month<'2026-04-23'>  // 4

Day

type Day<S extends string>

Extract day of month.

type D = Day<'2026-04-23T12:00:00Z'>  // 23

TimeOf

type TimeOf<S extends string>

Extract HH:MM:SS from an ISO datetime; never if absent.

type T = TimeOf<'2026-04-23T12:34:56Z'>  // '12:34:56'

IsLeapYear

type IsLeapYear<Y extends number>

Gregorian leap year: divisible by 4, except centuries not divisible by 400. Implemented by string-suffix matching to avoid tuple arithmetic.

type a = IsLeapYear<2024>  // true
type b = IsLeapYear<2100>  // false
type c = IsLeapYear<2000>  // true

DaysInMonth

type DaysInMonth<Y extends number, M extends number>

Days in Month of Year. February returns 29 in leap years.

type a = DaysInMonth<2024, 2>  // 29
type b = DaysInMonth<2026, 2>  // 28
type c = DaysInMonth<2026, 4>  // 30

DayOfWeek

type DayOfWeek = 1 | 2 | 3 | 4 | 5 | 6 | 7

ISO-8601 day of week: Mon = 1 ... Sun = 7.

Duration brands

type Duration<U extends string> = number & { readonly [_UNIT]: U }

type Milliseconds = Duration<'ms'>
type Seconds      = Duration<'s'>
type Minutes      = Duration<'min'>
type Hours        = Duration<'h'>
type Days         = Duration<'d'>
type Weeks        = Duration<'w'>

type AnyDuration = Milliseconds | Seconds | Minutes | Hours | Days | Weeks

Branded numbers — runtime is still a number, but Milliseconds and Seconds are not assignable to each other.

function sleep(ms: Milliseconds) { /* ... */ }
sleep(500 as Milliseconds)
sleep(2 as Seconds)  // Error — Seconds is not Milliseconds.