UNPKG

chronos-ts

Version:

A comprehensive TypeScript package for handling time periods, intervals, and date-related operations.

375 lines (374 loc) 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getDatesWithInterval = getDatesWithInterval; exports.getWeeksWithInterval = getWeeksWithInterval; exports.getDaysWithInterval = getDaysWithInterval; exports.getHoursWithInterval = getHoursWithInterval; exports.getMinutesWithInterval = getMinutesWithInterval; exports.getMonthsWithInterval = getMonthsWithInterval; exports.getYearsWithInterval = getYearsWithInterval; exports.addToDate = addToDate; exports.subtractFromDate = subtractFromDate; exports.isSameDay = isSameDay; exports.getWeekNumber = getWeekNumber; exports.getQuarter = getQuarter; exports.isLeapYear = isLeapYear; exports.getDaysInMonth = getDaysInMonth; exports.formatDate = formatDate; exports.parseDate = parseDate; exports.range = range; const precision_1 = require("./precision"); /** * Generates an array of dates between the given start and end dates, * with a specified interval between each date. * * @param start - The start date. * @param end - The end date. * @param interval - An object representing the interval between dates. * @returns An array of dates between the start and end dates, inclusive, * with the specified interval. */ function getDatesWithInterval(start, end, interval) { const dates = []; const current = new Date(start); while (current <= end) { dates.push(new Date(current)); current.setMinutes(current.getMinutes() + interval.getMinutesInterval()); } return dates; } /** * Generates an array of dates representing the start of each week within a given interval. * * @param start - The start date of the interval. * @param end - The end date of the interval. * @param interval - An object representing the interval in minutes. * @returns An array of dates, each representing the start of a week within the interval. */ function getWeeksWithInterval(start, end, interval) { const weeks = []; const current = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), start.getUTCDate())); // Move to the start of the week (Sunday) current.setUTCDate(current.getUTCDate() - current.getUTCDay()); const weekIncrement = Math.max(1, Math.round(interval.getMinutesInterval() / (7 * 24 * 60))); while (current <= end) { weeks.push(new Date(current)); // Add weeks based on the interval current.setUTCDate(current.getUTCDate() + weekIncrement * 7); } return weeks; } /** * Generates an array of dates between the start and end dates, inclusive, * with a specified interval. * * @param start - The start date. * @param end - The end date. * @param interval - The interval object that provides the interval in minutes. * @returns An array of dates with the specified interval. */ function getDaysWithInterval(start, end, interval) { const days = []; const current = new Date(start); current.setUTCHours(0, 0, 0, 0); const dayIncrement = Math.max(1, Math.round(interval.getMinutesInterval() / (24 * 60))); while (current <= end) { days.push(new Date(current)); current.setUTCDate(current.getUTCDate() + dayIncrement); } return days; } /** * Generates an array of Date objects representing hours between the start and end dates, * incremented by a specified interval. * * @param start - The start date and time. * @param end - The end date and time. * @param interval - An object that provides the interval in minutes. * @returns An array of Date objects representing the hours within the specified interval. */ function getHoursWithInterval(start, end, interval) { const hours = []; const current = new Date(start); current.setMinutes(0, 0, 0); const hourIncrement = Math.max(1, Math.round(interval.getMinutesInterval() / 60)); while (current <= end) { hours.push(new Date(current)); current.setHours(current.getHours() + hourIncrement); } return hours; } /** * Generates an array of Date objects representing each minute within a specified interval * between a start and end date. * * @param start - The start date and time. * @param end - The end date and time. * @param interval - An object that provides the interval in minutes. * @returns An array of Date objects, each representing a minute within the specified interval. */ function getMinutesWithInterval(start, end, interval) { const minutes = []; const current = new Date(start); current.setSeconds(0, 0); const minuteIncrement = Math.max(1, interval.getMinutesInterval()); while (current <= end) { minutes.push(new Date(current)); current.setMinutes(current.getMinutes() + minuteIncrement); } return minutes; } /** * Generates an array of Date objects representing the start of each month * within the specified interval between the start and end dates. * * @param start - The start date of the interval. * @param end - The end date of the interval. * @param interval - An object representing the interval in minutes. * @returns An array of Date objects, each representing the start of a month within the interval. */ function getMonthsWithInterval(start, end, interval) { const months = []; const current = new Date(Date.UTC(start.getUTCFullYear(), start.getUTCMonth(), 1)); // Use approximation of 30 days per month for interval calculation const monthIncrement = Math.max(1, Math.round(interval.getMinutesInterval() / (30 * 24 * 60))); while (current <= end) { months.push(new Date(current)); current.setUTCMonth(current.getUTCMonth() + monthIncrement); } return months; } /** * Generates an array of Date objects representing the start of each year * within the specified interval between the start and end dates. * * @param start - The start date. * @param end - The end date. * @param interval - An Interval object that determines the interval in minutes. * @returns An array of Date objects representing the start of each year within the interval. */ function getYearsWithInterval(start, end, interval) { const years = []; const current = new Date(Date.UTC(start.getUTCFullYear(), 0, 1)); // Calculate the number of years to add based on the interval const yearsToAdd = Math.max(1, Math.round(interval.getMinutesInterval() / 525600)); // 525600 minutes in a year while (current <= end) { years.push(new Date(current)); current.setUTCFullYear(current.getUTCFullYear() + yearsToAdd); } return years; } /** * Adds a specified amount of time to a given date based on the provided precision unit. * * @param date - The original date to which the amount will be added. * @param amount - The amount of time to add. Can be positive or negative. * @param unit - The unit of time to add (e.g., minute, hour, day, week, month, year). * * @returns A new `Date` object with the specified amount of time added. * * @example * ```typescript * const originalDate = new Date(Date.UTC(2023, 0, 1)); * const newDate = addToDate(originalDate, 5, Precision.DAY); * console.log(newDate); // Outputs: 2023-01-06T00:00:00.000Z * ``` */ function addToDate(date, amount, unit) { const newDate = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds())); switch (unit) { case precision_1.Precision.MINUTE: newDate.setUTCMinutes(newDate.getUTCMinutes() + amount); break; case precision_1.Precision.HOUR: newDate.setUTCHours(newDate.getUTCHours() + amount); break; case precision_1.Precision.DAY: newDate.setUTCDate(newDate.getUTCDate() + amount); break; case precision_1.Precision.WEEK: newDate.setUTCDate(newDate.getUTCDate() + amount * 7); break; case precision_1.Precision.MONTH: newDate.setUTCMonth(newDate.getUTCMonth() + amount); // Handle month overflow for dates that don't exist in the target month if (newDate.getUTCDate() !== date.getUTCDate()) { newDate.setUTCDate(0); // Set to last day of previous month } break; case precision_1.Precision.YEAR: newDate.setUTCFullYear(newDate.getUTCFullYear() + amount); // Handle leap year edge case (Feb 29 -> Feb 28) if (newDate.getUTCMonth() !== date.getUTCMonth()) { newDate.setUTCDate(0); // Set to last day of previous month } break; default: throw new Error(`Unsupported precision unit: ${unit}`); } return newDate; } /** * Subtracts a specified amount of time from a given date. * * @param date - The original date from which to subtract. * @param amount - The amount of time to subtract. * @param unit - The unit of time to subtract (e.g., days, months, years). * @returns A new Date object with the specified amount of time subtracted. */ function subtractFromDate(date, amount, unit) { return addToDate(date, -amount, unit); } /** * Checks if two dates are on the same calendar day. * * @param date1 - The first date to compare. * @param date2 - The second date to compare. * @returns `true` if both dates are on the same day, otherwise `false`. */ function isSameDay(date1, date2) { return (date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate()); } /** * Calculates the ISO week number for a given date. * * The ISO week date system is a leap week calendar system that is part of the ISO 8601 date and time standard. * It assigns a week number to each week of the year, where the first week of the year is the week that contains * the first Thursday of the year. * * @param date - The date object for which to calculate the week number. * @returns The ISO week number of the given date. */ function getWeekNumber(date) { const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())); const dayNum = d.getUTCDay() || 7; d.setUTCDate(d.getUTCDate() + 4 - dayNum); const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1)); return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7); } /** * Returns the quarter of the year for a given date. * * @param date - The date object for which to determine the quarter. * @returns The quarter of the year (1, 2, 3, or 4). */ function getQuarter(date) { return Math.floor(date.getMonth() / 3) + 1; } /** * Determines whether a given year is a leap year. * * A leap year is exactly divisible by 4 except for end-of-century years, which must be divisible by 400. * This means that the year 2000 was a leap year, although 1900 was not. * * @param year - The year to be checked. * @returns `true` if the year is a leap year, otherwise `false`. */ function isLeapYear(year) { return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } /** * Returns the number of days in a given month of a specific year. * * @param year - The year for which to get the number of days in the month. * @param month - The month (0-indexed, where 0 = January, 11 = December) for which to get the number of days. * @returns The number of days in the specified month of the given year. */ function getDaysInMonth(year, month) { return new Date(year, month + 1, 0).getDate(); } /** * Formats a given date according to the specified format string. * * The format string can contain the following placeholders: * - `YYYY`: Full year (e.g., 2023) * - `MM`: Month (01-12) * - `DD`: Day of the month (01-31) * - `HH`: Hours (00-23) * - `mm`: Minutes (00-59) * - `ss`: Seconds (00-59) * * Example usage: * ```typescript * const date = new Date(2023, 0, 1, 12, 30, 45); * const formattedDate = formatDate(date, 'YYYY-MM-DD HH:mm:ss'); * console.log(formattedDate); // Output: "2023-01-01 12:30:45" * ``` * * @param date - The date object to format. * @param format - The format string. * @returns The formatted date string. */ function formatDate(date, format) { const pad = (n) => { const str = n.toString(); return str.length < 2 ? '0' + str : str; }; const map = { YYYY: date.getFullYear().toString(), MM: pad(date.getMonth() + 1), DD: pad(date.getDate()), HH: pad(date.getHours()), mm: pad(date.getMinutes()), ss: pad(date.getSeconds()), }; return format.replace(/YYYY|MM|DD|HH|mm|ss/gi, (matched) => map[matched]); } /** * Parses a date string according to the specified format and returns a Date object. * * @param dateString - The date string to parse. * @param format - The format of the date string. Supported format parts are YYYY, MM, DD, HH, mm, ss. * @returns A Date object representing the parsed date. * @throws {Error} If the date string doesn't match the specified format. * * @example * ```typescript * const date = parseDate('2023-10-05 14:30:00', 'YYYY-MM-DD HH:mm:ss'); * console.log(date); // Outputs: Thu Oct 05 2023 14:30:00 GMT+0000 (Coordinated Universal Time) * ``` */ function parseDate(dateString, format) { const formatParts = format.match(/YYYY|MM|DD|HH|mm|ss/gi) || []; const dateParts = dateString.match(/\d+/g) || []; if (formatParts.length !== dateParts.length) { throw new Error(`Date string "${dateString}" does not match the specified format "${format}"`); } const map = {}; formatParts.forEach((part, index) => { map[part] = parseInt(dateParts[index], 10); }); const year = map['YYYY'] || 0; const month = (map['MM'] || 1) - 1; // JavaScript months are 0-indexed const day = map['DD'] || 1; const hour = map['HH'] || 0; const minute = map['mm'] || 0; const second = map['ss'] || 0; const result = new Date(year, month, day, hour, minute, second); // Validate the resulting date if (isNaN(result.getTime())) { throw new Error(`Invalid date components parsed from "${dateString}"`); } return result; } /** * Generates an array of numbers within a specified range. * * @param start - The starting number of the range. * @param end - The ending number of the range. * @param step - The step between each number in the range. Defaults to 1. * @returns An array of numbers from start to end, incremented by step. * @throws {Error} If step is zero or has the wrong sign. */ function range(start, end, step = 1) { if (step === 0) { throw new Error('Step cannot be zero'); } if ((end > start && step < 0) || (end < start && step > 0)) { throw new Error('Step direction must match the range direction'); } const length = Math.floor(Math.abs(end - start) / Math.abs(step)) + 1; return Array.from({ length }, (_, i) => start + i * step); }