import { type Minutes, type DecisionFunction, type DateRelativeDirection, type Days, type Maybe } from '@dereekb/util'; import { type StepRoundDateTimeDown } from './date.round'; import { type DateCellScheduleDateFilterConfig, type DateCellScheduleDateFilterInput } from './date.cell.schedule'; import { type LimitDateTimeConfig, LimitDateTimeInstance } from './date.time.limit'; /** * Configuration for a {@link DateTimeMinuteInstance} that combines time limits, step intervals, and schedule filtering * to control which date/time values are considered valid. * * @example * ```ts * const config: DateTimeMinuteConfig = { * date: new Date('2024-01-15T10:00:00'), * step: 15, * limits: { isFuture: true }, * behavior: { capToMinLimit: true, capToMaxLimit: true }, * schedule: { w: '0111110' } // weekdays only * }; * * const instance = new DateTimeMinuteInstance(config); * ``` */ export interface DateTimeMinuteConfig extends LimitDateTimeConfig { /** * Default date to consider. Falls back to the current date/time if not provided. */ readonly date?: Date; /** * Minute interval for stepping and rounding. Defaults to 1. */ readonly step?: Minutes; /** * Controls clamping behavior when a date exceeds configured limits. */ readonly behavior?: { /** * When true, rounds/clamps values that fall below the minimum up to the minimum instead of leaving them out of range. Defaults to true. */ readonly capToMinLimit?: boolean; /** * When true, rounds/clamps values that exceed the maximum down to the maximum instead of leaving them out of range. Defaults to true. */ readonly capToMaxLimit?: boolean; }; /** * Optional schedule that restricts which days are considered valid. Useful for excluding weekends or specific dates. */ readonly schedule?: DateCellScheduleDateFilterConfig; } /** * Validation status snapshot for a date evaluated against a {@link DateTimeMinuteInstance}'s constraints. * Each field defaults to `true` when its corresponding constraint is not configured, * so only actively violated constraints will be `false`. */ export interface DateTimeMinuteDateStatus { /** * Whether the date is at or after the configured minimum limit. */ readonly isAfterMinimum: boolean; /** * Whether the date is at or before the configured maximum limit. */ readonly isBeforeMaximum: boolean; /** * Whether the date satisfies the `isFuture` constraint. */ readonly inFuture: boolean; /** * Whether the date satisfies the `minimumMinutesIntoFuture` constraint. */ readonly inFutureMinutes: boolean; /** * Whether the date satisfies the `isPast` constraint. */ readonly inPast: boolean; /** * Whether the date falls on a day included in the configured schedule. */ readonly isInSchedule: boolean; } /** * Rounding options for {@link DateTimeMinuteInstance.round} that extend step-based rounding * with optional clamping to configured min/max bounds. */ export interface RoundDateTimeMinute extends StepRoundDateTimeDown { /** * When true, clamps the rounded result to the configured min/max limits * so it never falls outside the valid range. */ readonly roundToBound?: boolean; } /** * Manages a mutable date/time value with step-based rounding, min/max limit enforcement, * and schedule-aware validation. Combines {@link LimitDateTimeInstance} constraints with * {@link DateCellScheduleDateFilter} to determine valid date/time values. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * date: new Date('2024-06-15T09:07:00'), * step: 15, * limits: { min: new Date('2024-06-01'), max: new Date('2024-12-31') }, * schedule: { w: '0111110' } * }); * * const rounded = instance.round({ roundToSteps: true }); * const clamped = instance.clamp(); * const status = instance.getStatus(); * ``` */ export declare class DateTimeMinuteInstance { private _config; private _date; private _step; private _limit; private _dateFilter; constructor(config?: DateTimeMinuteConfig, dateOverride?: Maybe); get config(): DateTimeMinuteConfig; get date(): Date; set date(date: Date); get step(): Minutes; set step(step: Minutes); /** * Returns the LimitDateTimeInstance. This does not take the schedule into consideration. * * @returns The underlying {@link LimitDateTimeInstance}. */ get limitInstance(): LimitDateTimeInstance; /** * Checks whether any moment within the given date's day could be valid, considering * both the schedule and the configured min/max limits. Useful for calendar UIs to * determine which days should be selectable. * * @param date - Moment whose surrounding day should be evaluated. * @returns Whether the day contains at least one valid date/time value. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { min: new Date('2024-06-15T14:00:00') }, * schedule: { w: '0111110' } * }); * * // true if June 15 is a weekday and overlaps the limit range * instance.dateDayContainsValidDateValue(new Date('2024-06-15')); * ``` */ dateDayContainsValidDateValue(date: Date): boolean; /** * Checks whether the date satisfies the min/max limits and falls on a scheduled day. * Unlike {@link isValid}, this does not check future/past constraints. * * @param date - Date to check; defaults to the instance's current date. * @returns `true` if the date is within the min/max limits and on a scheduled day. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { min: new Date('2024-01-01'), max: new Date('2024-12-31') }, * schedule: { w: '0111110' } * }); * * instance.isInValidRange(new Date('2024-06-15T10:00:00')); // true if a weekday * ``` */ isInValidRange(date?: Date): boolean; /** * Checks whether the date passes all configured constraints: min/max limits, * future/past requirements, minimum future minutes, and schedule. * * @param date - Date to check; defaults to the instance's current date. * @returns `true` if the date passes all configured constraints. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { isFuture: true, min: new Date('2024-01-01') }, * schedule: { w: '0111110' } * }); * * instance.isValid(new Date('2099-03-15T10:00:00')); // true if all constraints pass * ``` */ isValid(date?: Date): boolean; /** * Evaluates the date against all configured constraints and returns a detailed status. * Fields default to `true` when their corresponding constraint is not configured. * * @param date - Date to evaluate; defaults to the instance's current date. * @returns A {@link DateTimeMinuteDateStatus} snapshot for the given date. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { min: new Date('2024-01-01'), isFuture: true } * }); * * const status = instance.getStatus(new Date('2023-06-01')); * // status.isAfterMinimum === false (before min) * // status.inFuture === false (if date is in the past) * ``` */ getStatus(date?: Date): DateTimeMinuteDateStatus; /** * Checks whether the date falls on a day included in the configured schedule. * Always returns `true` if no schedule is configured. * * @param date - Date to check; defaults to the instance's current date. * @returns `true` if the date is on a scheduled day or no schedule is configured. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * schedule: { w: '0111110' } // weekdays only * }); * * instance.dateIsInSchedule(new Date('2024-06-15')); // true (Saturday = false) * ``` */ dateIsInSchedule(date?: Date): boolean; /** * Rounds the instance's current date down to the configured step interval, * optionally clamping the result to the min/max bounds. * * @param round - Rounding and clamping options. * @returns The rounded (and optionally clamped) date. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * date: new Date('2024-06-15T09:07:00'), * step: 15, * limits: { min: new Date('2024-06-15T09:00:00') } * }); * * instance.round({ roundToSteps: true }); // 2024-06-15T09:00:00 * instance.round({ roundToSteps: true, roundToBound: true }); // clamped to min if below * ``` */ round(round: RoundDateTimeMinute): Date; /** * Clamps the date to both the configured limits and the schedule by first applying * {@link clampToLimit}, then {@link clampToSchedule}. * * @param date - Date to clamp; defaults to the instance's current date. * @param maxClampDistance - Maximum number of days to search for a valid schedule day. * @returns Moment snapped to both the configured limits and schedule. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { min: new Date('2024-06-01') }, * schedule: { w: '0111110' } * }); * * instance.clamp(new Date('2024-05-25')); // clamped to min, then nearest weekday * ``` */ clamp(date?: Date, maxClampDistance?: Days): Date; /** * Clamps the date to the configured min/max limits without considering the schedule. * * @param date - Date to clamp; defaults to the instance's current date. * @returns Moment snapped inside the configured min/max limits. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * limits: { min: new Date('2024-06-01'), max: new Date('2024-12-31') } * }); * * instance.clampToLimit(new Date('2025-03-01')); // returns max (2024-12-31) * ``` */ clampToLimit(date?: Date): Date; /** * Finds the nearest valid schedule day for the given date. Searches forward first, * then backward, within the configured limits and max distance. Returns the input * date unchanged if no schedule is configured or the date is already on a valid day. * * @param date - Date to clamp; defaults to the instance's current date. * @param maxClampDistance - Maximum number of days to search in each direction; defaults to 370. * @returns The nearest valid scheduled date, or the input date if already valid or no schedule is configured. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * schedule: { w: '0111110' } // weekdays only * }); * * // If June 15, 2024 is a Saturday, returns the next Monday * instance.clampToSchedule(new Date('2024-06-15')); * ``` */ clampToSchedule(date?: Date, maxClampDistance?: Days): Date; /** * Searches for the next day in the configured schedule in the given direction, * excluding the input date itself. Returns `undefined` if no schedule is configured * or no matching day is found within the max distance. * * @param date - Starting date for the search. * @param direction - Whether to search forward ('future') or backward ('past') * @param maxDistance - Maximum number of days to search; defaults to 370. * @returns The next valid schedule date, or `undefined` if none found within the max distance. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * schedule: { w: '0111110' } // weekdays only * }); * * // Find the next weekday after a Saturday * instance.findNextAvailableDayInSchedule(new Date('2024-06-15'), 'future'); * ``` */ findNextAvailableDayInSchedule(date: DateCellScheduleDateFilterInput, direction: DateRelativeDirection, maxDistance?: Days): Maybe; /** * Checks whether the given date falls on a scheduled day. Always returns `true` if no schedule is configured. * Accepts any {@link DateCellScheduleDateFilterInput} value (Date, number, or LogicalDate). * * @param date - Date to check against the schedule. * @returns `true` if the date is on a scheduled day or no schedule is configured. * * @example * ```ts * const instance = new DateTimeMinuteInstance({ * schedule: { w: '0111110' } * }); * * instance.isInSchedule(new Date('2024-06-17')); // true (Monday) * instance.isInSchedule(new Date('2024-06-16')); // false (Sunday) * ``` */ isInSchedule(date: DateCellScheduleDateFilterInput): boolean; protected _takeBoundedDate(date?: Date): Date; protected _takeMinimumBoundedDate(date?: Date): Date; protected _takeMaximumBoundedDate(date?: Date): Date; } /** * Creates a {@link DecisionFunction} that evaluates whether a given date passes all * constraints defined in the config (limits, future/past, schedule). * Uses {@link DateTimeMinuteInstance.isValid} internally. * * @param config - Configuration defining the valid date constraints. * @returns A decision function that returns `true` for valid dates. * * @example * ```ts * const isValid = dateTimeMinuteDecisionFunction({ * limits: { isFuture: true, min: new Date('2024-01-01') }, * schedule: { w: '0111110' } * }); * * isValid(new Date('2024-06-17T10:00:00')); // true if future weekday after min * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function dateTimeMinuteDecisionFunction(config: DateTimeMinuteConfig): DecisionFunction; /** * Creates a {@link DecisionFunction} that evaluates an entire day rather than a specific instant. * Useful for calendar UIs where you need to enable/disable entire days. * * When `startAndEndOfDayMustBeValid` is true, both the start and end of the day must pass * {@link DateTimeMinuteInstance.isValid}. When false (default), uses * {@link DateTimeMinuteInstance.dateDayContainsValidDateValue} to check if any moment * in the day could be valid. * * @param config - Configuration defining the valid date constraints. * @param startAndEndOfDayMustBeValid - When true, requires the entire day to be valid rather than just part of it. * @returns A decision function that returns `true` for valid days. * * @example * ```ts * const isDayValid = dateTimeMinuteWholeDayDecisionFunction({ * limits: { min: new Date('2024-06-15T14:00:00') }, * schedule: { w: '0111110' } * }); * * // true if any part of June 15 is valid and it's a weekday * isDayValid(new Date('2024-06-15')); * * const isFullDayValid = dateTimeMinuteWholeDayDecisionFunction(config, true); * // true only if both 00:00 and 23:59 on June 15 pass all constraints * isFullDayValid(new Date('2024-06-15')); * ``` * * @__NO_SIDE_EFFECTS__ */ export declare function dateTimeMinuteWholeDayDecisionFunction(config: DateTimeMinuteConfig, startAndEndOfDayMustBeValid?: boolean): DecisionFunction;