/** * DateTime utilities module based on Luxon * * @module datetime * * @example * Import datetime utilities: * ```typescript * import { * toLuxonDateTime, * calcWorkdays, * addWorkdays, * isWorkday, * TimeZones * } from '@vvlad1973/utils'; * ``` */ import { DateTime, Interval } from 'luxon'; /** * Russian timezone mappings */ export declare const TimeZones: { readonly 'MSK-1': "Europe/Kaliningrad"; readonly MSK: "Europe/Moscow"; readonly 'MSK+1': "Europe/Astrakhan"; readonly 'MSK+2': "Asia/Yekaterinburg"; readonly 'MSK+3': "Asia/Omsk"; readonly 'MSK+4': "Asia/Krasnoyarsk"; readonly 'MSK+5': "Asia/Irkutsk"; readonly 'MSK+6': "Asia/Chita"; readonly 'MSK+7': "Asia/Vladivostok"; readonly 'MSK+8': "Asia/Magadan"; readonly 'MSK+9': "Asia/Kamchatka"; }; /** * Options for converting to Luxon DateTime */ export interface ToLuxonOptions { zone?: string; setZone?: boolean; format?: string; type?: 'seconds' | 'milliseconds'; } /** * Holiday period definition */ export interface HolidayPeriod { from: string | Date | DateTime | number; to: string | Date | DateTime | number; } /** * Calendar entry - can represent a period, a single date, or a yearly recurring date * Can mark dates as holidays or as working days (for transferred weekends) * * @remarks * This interface supports three types of calendar entries: * 1. **Period** - specify both `from` and `to` for a date range * 2. **Single date** - specify `date` for a one-time specific date * 3. **Yearly recurring** - specify `monthDay` or `month_day` in "MM-DD" format (e.g., "01-01" for New Year) * * **Property naming:** * - Supports both camelCase and snake_case variants * - camelCase takes precedence: `monthDay` over `month_day`, `isWorkday` over `is_workday` * * **Timezone:** * - If `zone` is specified, this entry uses its own timezone * - Otherwise inherits timezone from `isWorkday()` options or system default * * @example * ```typescript * // Holiday period * { from: '2024-01-01', to: '2024-01-08' } * * // Single working Saturday (transferred weekend) * { date: '2024-12-28', isWorkday: true } * * // Yearly recurring holiday (New Year) * { monthDay: '01-01', isWorkday: false } * * // With specific timezone * { date: '2024-01-01', zone: 'America/New_York', isWorkday: false } * * // Snake_case variant * { month_day: '05-01', is_workday: false } * ``` */ export interface CalendarEntry { /** * Start date for period entry * Can be DateTime, Date, ISO string, or timestamp */ from?: string | Date | DateTime | number; /** * End date for period entry * Can be DateTime, Date, ISO string, or timestamp */ to?: string | Date | DateTime | number; /** * Specific date for one-time entry * Can be DateTime, Date, ISO string, or timestamp */ date?: string | Date | DateTime | number; /** * Month and day in "MM-DD" format for yearly recurring dates (camelCase) * @example "01-01" for January 1st, "12-25" for December 25th */ monthDay?: string; /** * Month and day in "MM-DD" format for yearly recurring dates (snake_case) * Alternative to monthDay. If both are present, monthDay takes precedence * @example "01-01" for January 1st, "12-25" for December 25th */ month_day?: string; /** * Working day flag (camelCase) * - true: This is a working day (even if it's normally a weekend) * - false/undefined: This is a holiday/weekend */ isWorkday?: boolean; /** * Working day flag (snake_case) * Alternative to isWorkday. If both are present, isWorkday takes precedence * - true: This is a working day (even if it's normally a weekend) * - false/undefined: This is a holiday/weekend */ is_workday?: boolean; /** * Timezone for this specific entry (IANA format) * @example "Europe/Moscow", "America/New_York", "UTC" * If not specified, inherits from options or uses system local timezone */ zone?: string; } /** * Work calendar - single entry or collection of calendar entries * * @example * ```typescript * // Single entry * const calendar: WorkCalendar = { from: '2024-01-01', to: '2024-01-08' }; * * // Multiple entries * const calendar: WorkCalendar = [ * { monthDay: '01-01', isWorkday: false }, // New Year * { monthDay: '05-01', isWorkday: false }, // May 1st * { date: '2024-12-28', isWorkday: true } // Working Saturday * ]; * ``` */ export type WorkCalendar = CalendarEntry | CalendarEntry[]; /** * Work interval definition */ export interface WorkInterval { from: string; to: string; } /** * Options for date calculations */ export interface DateOptions { zone?: string; keepLocalTime?: boolean; keepZone?: boolean; fromStartOfDay?: boolean; } /** * Corrects timezone shorthand to IANA timezone name * * @param timeZone - Timezone string (e.g., 'MSK', 'MSK+1') * @returns IANA timezone name * * @example * ```typescript * correctTimeZone('MSK'); // 'Europe/Moscow' * correctTimeZone('America/New_York'); // 'America/New_York' * ``` */ export declare function correctTimeZone(timeZone?: string): string; /** * Converts various date/time formats to Luxon DateTime * * @param dateTime - Date/time value to convert * @param options - Conversion options * @returns Luxon DateTime object or undefined * * @example * ```typescript * toLuxonDateTime('2023-01-15'); * toLuxonDateTime(new Date()); * toLuxonDateTime(1673740800, { type: 'seconds' }); * ``` */ export declare function toLuxonDateTime(dateTime: DateTime | Date | string | number | undefined, options?: ToLuxonOptions): DateTime | undefined; /** * Creates an Interval between two dates * * @param startDate - Start date * @param endDate - End date * @param options - Conversion options * @returns Luxon Interval or undefined * * @example * ```typescript * const interval = createInterval('2023-01-01', '2023-01-31'); * ``` */ export declare function createInterval(startDate: DateTime | Date | string | number, endDate: DateTime | Date | string | number, options?: ToLuxonOptions): Interval | undefined; /** * Calculates number of workdays between two dates * * @param startDate - Start date * @param endDate - End date * @param options - Date options * @returns Number of workdays * * @example * ```typescript * const days = calcWorkdays('2023-01-02', '2023-01-13'); * // Calculates workdays excluding weekends * ``` */ export declare function calcWorkdays(startDate: DateTime | Date | string | number, endDate: DateTime | Date | string | number, options?: DateOptions): number; /** * Calculates workdays excluding holidays * * @param startDate - Start date * @param endDate - End date * @param options - Date options * @param holidays - Holiday period(s) * @returns Number of workdays excluding holidays * * @example * ```typescript * const days = calcWorkdaysWithHolidays( * '2023-01-01', * '2023-01-31', * {}, * [{ from: '2023-01-01', to: '2023-01-08' }] * ); * ``` */ export declare function calcWorkdaysWithHolidays(startDate: DateTime | Date | string | number, endDate: DateTime | Date | string | number, options?: DateOptions, holidays?: HolidayPeriod | HolidayPeriod[]): number; /** * Adds workdays to a date * * @param date - Starting date * @param addDays - Number of workdays to add * @param options - Date options * @param holidays - Holiday period(s) * @returns DateTime after adding workdays * * @example * ```typescript * const futureDate = addWorkdays('2023-01-02', 10); * // Returns date 10 workdays from Jan 2, 2023 * ``` */ export declare function addWorkdays(date: DateTime | Date | string | number, addDays: number, options?: DateOptions, holidays?: HolidayPeriod | HolidayPeriod[]): DateTime; /** * Calculates work speed (amount per workday) * * @param amount - Total amount * @param startDate - Start date * @param endDate - End date * @param options - Date options * @param holidays - Holiday period(s) * @returns Speed (amount per workday) * * @example * ```typescript * const speed = calcSpeed(100, '2023-01-02', '2023-01-13'); * // Returns amount per workday * ``` */ export declare function calcSpeed(amount: number, startDate?: DateTime | Date | string | number, endDate?: DateTime | Date | string | number, options?: DateOptions, holidays?: HolidayPeriod | HolidayPeriod[]): number; /** * Checks if current time is within work hours * * @param dateTime - DateTime to check (defaults to now) * @param workInterval - Work hours interval * @returns True if within work hours * * @example * ```typescript * const isDuringWork = isWorkTime(DateTime.now(), { from: '9:00', to: '18:00' }); * ``` */ export declare function isWorkTime(dateTime?: DateTime, workInterval?: WorkInterval): boolean; /** * Checks if a date is a workday * * Supports flexible calendar configuration with: * - Holiday periods (from/to dates) * - Specific dates (single days that are holidays or working days) * - Yearly recurring holidays (month-day format like "01-01" for New Year) * - Transferred weekends (mark Saturday as working day or Monday as holiday) * - Per-entry timezones (different timezone for each calendar entry) * - Both camelCase and snake_case property names * * Priority system: First matching calendar entry wins. * Order of checks: monthDay/month_day → date → from/to period * * @param date - Date to check (DateTime, Date, ISO string, or timestamp) * @param calendar - Holiday period(s) or work calendar entries. Supports: * - HolidayPeriod (legacy format): `{ from: Date, to: Date }` * - CalendarEntry: `{ date?, monthDay?, month_day?, from?, to?, isWorkday?, is_workday?, zone? }` * - Array of either type * @param options - Date conversion options * - zone: Timezone (IANA format like 'Europe/Moscow' or 'UTC'). Defaults to system local timezone * - keepLocalTime: Keep local time when converting to different zone * - keepZone: Keep the original timezone * @returns True if the date is a workday (Monday-Friday), false for weekends and holidays * * @remarks * **Timezone behavior:** * - If `options.zone` is not specified → uses **system local timezone** (e.g., Europe/Moscow, America/New_York) * - If `options.zone` is specified → uses the specified timezone for all dates * - If `CalendarEntry.zone` is specified → uses entry-specific timezone (overrides options.zone) * - Date comparison ignores time (compares calendar dates only) * * **Property naming:** * - Supports both camelCase (`monthDay`, `isWorkday`) and snake_case (`month_day`, `is_workday`) * - camelCase takes precedence if both variants are present * * **CalendarEntry fields:** * - `monthDay` / `month_day`: "MM-DD" format for yearly recurring dates (e.g., "01-01", "12-25") * - `date`: Full date for one-time specific dates * - `from` / `to`: Date range for holiday/working periods * - `isWorkday` / `is_workday`: true = working day (even if weekend), false/undefined = holiday * - `zone`: Timezone for this specific entry (IANA format) * * @example * Basic usage (system timezone): * ```typescript * const isWork = isWorkday('2023-01-02'); // true (Monday) * const isWeekend = isWorkday('2023-01-01'); // false (Sunday) * ``` * * @example * With holiday periods (backward compatible): * ```typescript * const holidays = { from: '2024-01-01', to: '2024-01-08' }; * isWorkday('2024-01-05', holidays); // false * ``` * * @example * With transferred weekends and special dates: * ```typescript * const calendar = [ * { from: '2024-01-01', to: '2024-01-08' }, // holiday period * { date: '2024-12-28', isWorkday: true }, // working Saturday * { date: '2024-12-30', isWorkday: false } // holiday Monday * ]; * isWorkday('2024-12-28', calendar); // true (Saturday, but working) * isWorkday('2024-12-30', calendar); // false (Monday, but holiday) * ``` * * @example * With yearly recurring holidays (month-day format): * ```typescript * const calendar = [ * { monthDay: '01-01', isWorkday: false }, // New Year (every year) - camelCase * { month_day: '05-01', is_workday: false }, // May 1st (every year) - snake_case * { monthDay: '12-25', isWorkday: false } // Christmas (every year) * ]; * isWorkday('2024-01-01', calendar); // false * isWorkday('2025-01-01', calendar); // false (works for any year) * ``` * * @example * With specific timezone: * ```typescript * // Check if it's a workday in UTC timezone * isWorkday('2024-01-15T23:00:00', [], { zone: 'UTC' }); * * // Check with calendar entry having its own timezone * const calendar = [ * { date: '2024-01-01', zone: 'America/New_York', isWorkday: false } * ]; * isWorkday('2024-01-01', calendar); // Uses America/New_York for this entry * ``` * * @example * Priority system (first match wins): * ```typescript * const calendar = [ * { monthDay: '01-15', isWorkday: false }, // First: yearly recurring (checked first) * { date: '2024-01-15', isWorkday: true } // Second: specific date (ignored) * ]; * isWorkday('2024-01-15', calendar); // false (monthDay matched first) * ``` */ export declare function isWorkday(date: DateTime | Date | string | number, calendar?: HolidayPeriod | HolidayPeriod[] | WorkCalendar, options?: DateOptions): boolean; /** * Checks if a date is within an interval * * @param date - Date to check * @param from - Interval start * @param to - Interval end * @param options - Date options * @returns True if date is within interval * * @example * ```typescript * const inRange = isDateTimeInInterval('2023-01-15', '2023-01-01', '2023-01-31'); * // true * ``` */ export declare function isDateTimeInInterval(date: DateTime | Date | string | number, from: DateTime | Date | string | number, to: DateTime | Date | string | number, options?: DateOptions): boolean;