chronos-ts
Version:
A comprehensive TypeScript package for handling time periods, intervals, and date-related operations.
375 lines (374 loc) • 15 kB
JavaScript
"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);
}