"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: all[name]
    });
}
_export(exports, {
    ISO8061_WITH_TIMEZONE: function() {
        return ISO8061_WITH_TIMEZONE;
    },
    ISO9075_DATETIME_FORMAT: function() {
        return ISO9075_DATETIME_FORMAT;
    },
    ISO9075_DATE_FORMAT: function() {
        return ISO9075_DATE_FORMAT;
    },
    ageInMonths: function() {
        return ageInMonths;
    },
    ageInWeeks: function() {
        return ageInWeeks;
    },
    ageInYears: function() {
        return ageInYears;
    },
    compareDateStrings: function() {
        return compareDateStrings;
    },
    convertISO9075toRFC3339: function() {
        return convertISO9075toRFC3339;
    },
    dateCustomValidation: function() {
        return dateCustomValidation;
    },
    datetimeCustomValidation: function() {
        return datetimeCustomValidation;
    },
    differenceInMilliseconds: function() {
        return differenceInMilliseconds;
    },
    doAgeRangesHaveGaps: function() {
        return doAgeRangesHaveGaps;
    },
    doAgeRangesOverlap: function() {
        return doAgeRangesOverlap;
    },
    eachDayInMonth: function() {
        return eachDayInMonth;
    },
    endpointsOfDay: function() {
        return endpointsOfDay;
    },
    format: function() {
        return format;
    },
    formatLong: function() {
        return formatLong;
    },
    formatShort: function() {
        return formatShort;
    },
    formatShortest: function() {
        return formatShortest;
    },
    formatTime: function() {
        return formatTime;
    },
    formatTimeWithSeconds: function() {
        return formatTimeWithSeconds;
    },
    formatWeekdayShort: function() {
        return formatWeekdayShort;
    },
    getCurrentDateString: function() {
        return getCurrentDateString;
    },
    getCurrentDateTimeString: function() {
        return getCurrentDateTimeString;
    },
    getCurrentISO8601DateString: function() {
        return getCurrentISO8601DateString;
    },
    getDateTimeSubtractedFromNow: function() {
        return getDateTimeSubtractedFromNow;
    },
    intlFormatDate: function() {
        return intlFormatDate;
    },
    isISOString: function() {
        return isISOString;
    },
    isIntervalWithinInterval: function() {
        return isIntervalWithinInterval;
    },
    isStartOfThisWeek: function() {
        return isStartOfThisWeek;
    },
    isWithinIntervalExcludingEnd: function() {
        return isWithinIntervalExcludingEnd;
    },
    locale: function() {
        return locale;
    },
    maxValidDate: function() {
        return maxValidDate;
    },
    minValidDate: function() {
        return minValidDate;
    },
    parseDate: function() {
        return parseDate;
    },
    timeCustomValidation: function() {
        return timeCustomValidation;
    },
    toDateString: function() {
        return toDateString;
    },
    toDateTimeString: function() {
        return toDateTimeString;
    }
});
const _datefns = require("date-fns");
const _zod = require("zod");
const _constants = require("@tamanu/constants");
const ISO9075_DATE_FORMAT = 'yyyy-MM-dd';
const ISO9075_DATETIME_FORMAT = 'yyyy-MM-dd HH:mm:ss';
const ISO8061_WITH_TIMEZONE = "yyyy-MM-dd'T'HH:mm:ssXXX";
const isISOString = (dateString)=>(0, _datefns.isMatch)(dateString, ISO9075_DATETIME_FORMAT) || (0, _datefns.isMatch)(dateString, ISO9075_DATE_FORMAT);
const parseDate = (date)=>{
    if (date == null) return null;
    // Handle empty strings
    if (typeof date === 'string' && date.trim() === '') return null;
    const dateObj = typeof date === 'string' ? isISOString(date) ? (0, _datefns.parseISO)(date) : new Date(date.replace(' ', 'T')) : date;
    if (!(0, _datefns.isValid)(dateObj)) throw new Error('Not a valid date');
    return dateObj;
};
const toDateTimeString = (date)=>{
    if (date == null) return null;
    const dateObj = parseDate(date);
    if (!dateObj) return null;
    return (0, _datefns.formatISO9075)(dateObj, {
        representation: 'complete'
    });
};
const toDateString = (date)=>{
    if (date == null) return null;
    const dateObj = parseDate(date);
    if (!dateObj) return null;
    return (0, _datefns.formatISO9075)(dateObj, {
        representation: 'date'
    });
};
const getCurrentDateTimeString = ()=>(0, _datefns.formatISO9075)(new Date());
const getDateTimeSubtractedFromNow = (daysToSubtract)=>{
    return toDateTimeString((0, _datefns.sub)(new Date(), {
        days: daysToSubtract
    }));
};
const getCurrentDateString = ()=>(0, _datefns.formatISO9075)(new Date(), {
        representation: 'date'
    });
const getCurrentISO8601DateString = ()=>new Date().toISOString();
const convertISO9075toRFC3339 = (dateString)=>{
    const parsedDate = dateString == null ? new Date() : (0, _datefns.parseISO)(dateString);
    return (0, _datefns.format)(parsedDate, "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
};
const ageInWeeks = (dob)=>{
    return (0, _datefns.differenceInWeeks)(new Date(), (0, _datefns.parseISO)(dob));
};
const ageInMonths = (dob)=>{
    return (0, _datefns.differenceInMonths)(new Date(), (0, _datefns.parseISO)(dob));
};
const ageInYears = (dob)=>{
    return (0, _datefns.differenceInYears)(new Date(), (0, _datefns.parseISO)(dob));
};
const compareDateStrings = (key = 'desc')=>{
    return (a, b)=>{
        switch(key){
            case 'asc':
            case 'ASC':
                return (0, _datefns.parseISO)(a.date).getTime() - (0, _datefns.parseISO)(b.date).getTime();
            case 'desc':
            case 'DESC':
                return (0, _datefns.parseISO)(b.date).getTime() - (0, _datefns.parseISO)(a.date).getTime();
            default:
                return 0;
        }
    };
};
const getAgeRangeInMinutes = ({ ageMin = -Infinity, ageMax = Infinity, ageUnit })=>{
    const timeUnit = _constants.TIME_UNIT_OPTIONS.find((option)=>option.unit === ageUnit);
    if (!timeUnit) return null;
    const conversionValue = timeUnit.minutes;
    return {
        ageMin: ageMin * conversionValue,
        ageMax: ageMax * conversionValue,
        previousAgeUnit: ageUnit
    };
};
const doAgeRangesHaveGaps = (rangesArray)=>{
    const conversions = {
        weeks: {
            months: (a, b)=>{
                const weeks = a.ageMax / 60 / 24 / 7;
                const months = b.ageMin / 60 / 24 / 30;
                return weeks / 4 !== months;
            },
            years: (a, b)=>{
                const weeks = a.ageMax / 60 / 24 / 7;
                const years = b.ageMin / 60 / 24 / 365;
                return weeks / 52 !== years;
            }
        },
        months: {
            years: (a, b)=>{
                const months = a.ageMax / 60 / 24 / 30;
                const years = b.ageMin / 60 / 24 / 365;
                return months / 12 !== years;
            }
        }
    };
    // Get all values into same time unit and sort by ageMin low to high
    const normalized = rangesArray.map(getAgeRangeInMinutes).filter((range)=>range !== null);
    normalized.sort((a, b)=>a.ageMin - b.ageMin);
    return normalized.some((rangeA, i)=>{
        const rangeB = normalized[i + 1];
        // This means we reached the last item, nothing more to compare
        if (!rangeB) return false;
        if (rangeA.previousAgeUnit !== rangeB.previousAgeUnit) {
            // No conversion means that minute comparison is good
            const conversion = conversions[rangeA.previousAgeUnit]?.[rangeB.previousAgeUnit];
            if (conversion) return conversion(rangeA, rangeB);
        }
        // These have to forcefully match, otherwise a gap exists
        return rangeA.ageMax !== rangeB.ageMin;
    });
};
const doAgeRangesOverlap = (rangesArray)=>{
    return rangesArray.some((rangeA, aIndex)=>{
        return rangesArray.some((rangeB, bIndex)=>{
            // Only compare once between two ranges
            if (aIndex >= bIndex) return false;
            // Get both values into same time unit
            const aInMinutes = getAgeRangeInMinutes(rangeA);
            const bInMinutes = getAgeRangeInMinutes(rangeB);
            if (!aInMinutes || !bInMinutes) return false;
            // Figure out the lowest min range
            const lowestMin = aInMinutes.ageMin < bInMinutes.ageMin ? aInMinutes : bInMinutes;
            const highestMin = aInMinutes.ageMin < bInMinutes.ageMin ? bInMinutes : aInMinutes;
            const lowestAgeMax = lowestMin.ageMax;
            const highestAgeMin = highestMin.ageMin;
            // Min inclusive - max exclusive: only overlaps if its less than
            return highestAgeMin < lowestAgeMax;
        });
    });
};
const format = (date, format)=>{
    if (date == null) return null;
    const dateObj = parseDate(date);
    if (!dateObj) return null;
    return (0, _datefns.format)(dateObj, format);
};
const differenceInMilliseconds = (a, b)=>(0, _datefns.differenceInMilliseconds)(new Date(a), new Date(b));
const locale = globalThis.navigator?.language ?? 'default';
const intlFormatDate = (date, formatOptions, fallback = 'Unknown')=>{
    if (!date) return fallback;
    const dateObj = parseDate(date);
    if (!dateObj) return fallback;
    return dateObj.toLocaleString(locale, formatOptions);
};
const formatShortest = (date)=>intlFormatDate(date, {
        month: '2-digit',
        day: '2-digit',
        year: '2-digit'
    }, '--/--'); // 12/04/20
const formatShort = (date)=>intlFormatDate(date, {
        day: '2-digit',
        month: '2-digit',
        year: 'numeric'
    }, '--/--/----'); // 12/04/2020
const formatTime = (date)=>{
    const result = intlFormatDate(date, {
        hour: 'numeric',
        minute: '2-digit',
        hour12: true
    }, '__:__');
    return result.replace(' ', '').toLowerCase();
};
const formatTimeWithSeconds = (date)=>intlFormatDate(date, {
        timeStyle: 'medium',
        hour12: true
    }, '__:__:__'); // 12:30:00 am
const formatLong = (date)=>intlFormatDate(date, {
        timeStyle: 'short',
        dateStyle: 'full',
        hour12: true
    }, 'Date information not available'); // "Thursday, 14 July 2022, 03:44 pm"
const formatWeekdayShort = (date)=>intlFormatDate(date, {
        weekday: 'short'
    });
const isStartOfThisWeek = (date)=>{
    const startOfThisWeek = (0, _datefns.startOfWeek)(new Date(), {
        weekStartsOn: 1
    });
    return (0, _datefns.isSameDay)(date, startOfThisWeek);
};
const dateCustomValidation = _zod.z.string().refine((val)=>{
    const regex = /^\d{4}-\d{2}-\d{2}$/;
    if (!regex.test(val)) return false;
    const date = new Date(val);
    return (0, _datefns.isValid)(date);
}, {
    message: 'Invalid date format, expected YYYY-MM-DD'
}).describe('__dateCustomValidation__');
const timeCustomValidation = _zod.z.string().refine((val)=>{
    const regex = /^\d{2}:\d{2}:\d{2}$/;
    if (!regex.test(val)) return false;
    return true;
}, {
    message: 'Invalid time format, expected HH:MM:SS'
});
const datetimeCustomValidation = _zod.z.string().refine((val)=>{
    const regex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
    if (!regex.test(val)) return false;
    const date = new Date(val);
    return (0, _datefns.isValid)(date);
}, {
    message: 'Invalid datetime format, expected YYYY-MM-DD HH:MM:SS'
}).describe('__datetimeCustomValidation__');
const endpointsOfDay = (date)=>[
        (0, _datefns.startOfDay)(date),
        (0, _datefns.endOfDay)(date)
    ];
const isIntervalWithinInterval = (interval1, interval2)=>{
    const { start, end } = interval1;
    return (0, _datefns.isWithinInterval)(start, interval2) && (0, _datefns.isWithinInterval)(end, interval2);
};
const isWithinIntervalExcludingEnd = (date, interval)=>(0, _datefns.isBefore)(date, interval.end) && (0, _datefns.isWithinInterval)(date, interval);
const maxValidDate = (dates)=>{
    const validDates = dates.filter(_datefns.isValid);
    return validDates.length === 0 ? null : (0, _datefns.max)(validDates);
};
const minValidDate = (dates)=>{
    const validDates = dates.filter(_datefns.isValid);
    return validDates.length === 0 ? null : (0, _datefns.min)(validDates);
};
const eachDayInMonth = (date)=>(0, _datefns.eachDayOfInterval)({
        start: (0, _datefns.startOfMonth)(date),
        end: (0, _datefns.endOfMonth)(date)
    });

//# sourceMappingURL=dateTime.js.map