/** * Date helpers for the calendar. * * No date library. Everything a month grid needs is arithmetic on `Date`, and * a dependency that ships a full timezone database to render seven columns is * a poor trade for a library whose whole runtime is three small packages. * * Two rules hold throughout: * * - **Days are compared at local midnight.** A `Date` carries a time, and two * values on the same day are not equal unless that time is stripped. Every * comparison here goes through `startOfDay`. * - **Month arithmetic is done with `setMonth`, not by adding days.** The * platform already knows that a month is 28, 29, 30 or 31 days long. * * Three more that are easy to lose and expensive to get back: * * - **Days are stepped with `setDate`, never with milliseconds.** Adding * `n * 86400000` is wrong by an hour on the two days a year the clocks move, * which is enough to land the wrong side of midnight and shift a whole grid. * - **A month is normalised to the 1st before months are added.** `setMonth` * on the 31st of a month whose neighbour is shorter overflows into the month * after next — January 31st plus one month is March 3rd. * - **Nothing is ever parsed back out of formatted text.** `Intl` is asked for * the *parts* and the numbers are read from those, because the order and the * separators belong to the locale and only the numbers are ours. */ /** Names of the weekdays and months, in the caller's locale. */ export type DateLocale = string | undefined; export declare function startOfDay(date: Date): Date; export declare function isSameDay(a: Date | null | undefined, b: Date | null | undefined): boolean; export declare function isSameMonth(a: Date, b: Date): boolean; export declare function startOfMonth(date: Date): Date; /** * Day 0 of the *next* month, which the platform resolves to the last day of * this one — so a leap February needs no special case. */ export declare function endOfMonth(date: Date): Date; export declare function addMonths(date: Date, months: number): Date; export declare function addDays(date: Date, days: number): Date; export declare function isBefore(a: Date, b: Date): boolean; export declare function isAfter(a: Date, b: Date): boolean; /** Inclusive at both ends, which is what a selected range means to a reader. */ export declare function isWithin(date: Date, from: Date, to: Date): boolean; /** * `date` pulled inside `min`..`max`, at day resolution. * * The bound is returned at its own start of day rather than as given, so a * `maxDate` that happens to carry a time of 17:30 does not hand back a value * that then compares as *after* the last selectable day. */ export declare function clampDate(date: Date, min?: Date, max?: Date): Date; /** * A first-day-of-week index made safe. * * `weekStartsOn` arrives from a caller and reaches an array index by way of * `(day + weekStartsOn) % 7`, where a negative or out-of-range value yields a * negative index and an `undefined` weekday name. Both directions wrap. */ export declare function normalizeWeekStart(weekStartsOn: number): number; /** * The day the week starts on where this locale is spoken, as `Date.getDay()` * counts it — 0 for Sunday. * * Sunday is a poor default outside North America and a handful of other * regions, but it is the one the platform gives us when it knows nothing. Where * `Intl` carries week data, ask it: `en-GB` and `fr-FR` start on Monday, and a * calendar that says otherwise is wrong in a way its reader notices immediately. */ export declare function localeWeekStart(locale: DateLocale): number; /** * The six-week grid for a month. * * Always six rows, and always starting on the chosen first day of the week, so * the calendar does not change height as the months are paged through. A grid * that grows a row in March and loses it again in April makes everything below * it jump, and the days themselves appear to move between months. * * The leading and trailing cells belong to the neighbouring months; whether * they are drawn or left blank is the caller's decision. * * `system` and `locale` are what make this work for a Hijri grid, where the * month it has to open on is not the Gregorian 1st. */ export declare function monthGrid(month: Date, weekStartsOn: number, system?: 'gregory' | 'islamic', locale?: DateLocale): Date[][]; /** * Which calendar the months and day numbers are counted in. * * `auto` takes whatever the locale resolves to, which on an Arabic device is * usually islamic. It is not the default: a grid whose month boundaries move * with the device's language is a surprise, and the caller who wants that can * ask for it. */ export type CalendarSystem = 'gregory' | 'islamic' | 'auto'; /** Year, month and day as the chosen calendar counts them. 1-based month. */ export interface CalendarParts { year: number; month: number; day: number; } /** What `auto` resolves to for a locale, falling back to the Gregorian. */ export declare function resolveCalendar(system: CalendarSystem, locale: DateLocale): 'gregory' | 'islamic'; /** * A date's year, month and day in the given calendar. * * `formatToParts` rather than a parsed string, because the order and the * separators are the locale's business and we only want the numbers. The * numbering system is pinned to Latin so the parts come back parseable * whatever language is on the device, and so the cells and the caption above * them end up in one set of digits. */ export declare function calendarParts(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): CalendarParts; export declare function isSameCalendarMonth(a: Date, b: Date, system: 'gregory' | 'islamic', locale: DateLocale): boolean; /** * The first day of the calendar month `date` falls in. * * Walked back a day at a time rather than computed. A Hijri month is 29 or 30 * days depending on the year, and the platform's own calendar data already * knows which — asking it is better than shipping a table that will disagree * with the device. * * The walk stops where the *month number changes*, not where the day number * reads 1. The observational Islamic calendars the platforms ship do not always * label a day 1: in 1450 AH, month 11 day 30 is followed directly by month 12 * day 2. Hunting for a day 1 that is never emitted walked the cursor off the * end of its budget and then paged the calendar to the same month forever. */ export declare function startOfCalendarMonth(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): Date; /** Days in the calendar month `date` falls in. */ export declare function daysInCalendarMonth(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): number; /** Page by whole calendar months, forwards or back. */ export declare function addCalendarMonths(date: Date, months: number, system: 'gregory' | 'islamic', locale: DateLocale): Date; /** The day-of-month a cell shows. */ export declare function calendarDayNumber(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): number; /** "Ramadan 1447" or "March 2026", in whichever calendar is in force. */ export declare function calendarMonthLabel(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): string; /** * The names of a calendar's months, in order, for the dropdown. * * Sampled from a real year in that calendar rather than from twelve Gregorian * firsts — the old code did the latter and got twelve arbitrary Hijri names in * whatever order the Gregorian 1sts happened to fall, then indexed them by * Gregorian month, which meant nothing at all. */ export declare function calendarMonthNames(reference: Date, system: 'gregory' | 'islamic', locale: DateLocale, style?: 'long' | 'short'): string[]; /** The whole date read out, in whichever calendar is in force. */ export declare function calendarLongDate(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): string; /** The compact form a trigger shows, in whichever calendar is in force. */ export declare function calendarShortDate(date: Date, system: 'gregory' | 'islamic', locale: DateLocale): string; /** Month names in order, for the caption and its dropdown. */ export declare function monthNames(locale: DateLocale, style?: 'long' | 'short'): string[]; /** Column headings, rotated so the first one is `weekStartsOn`. */ export declare function weekdayNames(locale: DateLocale, weekStartsOn: number, width?: 'short' | 'narrow'): string[]; /** "March 2026", for the caption. */ export declare function monthLabel(date: Date, locale: DateLocale): string; /** "12 March 2026" — the whole date, for a screen reader to read out. */ export declare function longDate(date: Date, locale: DateLocale): string; /** "12 Mar 2026" — the compact form a trigger shows. */ export declare function shortDate(date: Date, locale: DateLocale): string; //# sourceMappingURL=date.d.ts.map