date-limits
Version:
Check if a date is before a flexible limit.
73 lines (72 loc) • 3.54 kB
JavaScript
import { createUTCDate, isValidDate, standardizeDay } from './date-utils';
import { GeneralGenerator, } from './generators/general-generator';
import { makeYearGenerator } from './generators/year-generator';
export function getClosestDate(config, targetDate = new Date(), yearLimit = 1970) {
let currentYear = targetDate.getFullYear(), currentMonth = targetDate.getMonth() + 1, currentDay = targetDate.getDate();
if (currentYear < yearLimit) {
throw new Error(`Target date cannot be lower than the year limit.`);
}
const data = _getClosestDateHelper(targetDate, makeYearGenerator(config.year, currentYear, yearLimit), new GeneralGenerator(config.month, currentMonth, 12), new GeneralGenerator(config.day, currentDay, 31), currentYear, currentMonth, currentDay);
return data;
}
function _getClosestDateHelper(targetDate, yearGenerator, monthGenerator, dayGenerator, currentYear, currentMonth, currentDay, getNextYear = true, getNextMonth = true, getNextDay = true, shouldResetMonth = true, shouldResetDay = true) {
while (true) {
if (getNextYear) {
const oldYear = currentYear;
const nextYear = yearGenerator.next().value;
if (nextYear === null)
return null;
currentYear = nextYear;
getNextYear = false;
shouldResetMonth && (shouldResetMonth = oldYear > currentYear);
shouldResetDay || (shouldResetDay = shouldResetMonth);
}
if (getNextMonth) {
const oldMonth = currentMonth;
const nextMonth = monthGenerator.next(shouldResetMonth).value;
currentMonth = nextMonth.value;
getNextMonth = false;
if (currentMonth < 1 || currentMonth > 12) {
throw new Error('Month number must be within 1 and 12 inclusive');
}
shouldResetDay || (shouldResetDay = oldMonth > currentMonth);
if (nextMonth.looped) {
getNextYear = true;
continue;
}
}
if (getNextDay) {
const nextDay = dayGenerator.next(shouldResetDay).value;
currentDay = nextDay.value;
getNextDay = false;
if (currentDay === 0 || currentDay > 31) {
throw new Error('Day number must be less than or equal to 31 and cannot be 0');
}
if (nextDay.looped) {
getNextYear = false;
getNextMonth = true;
continue;
}
}
const actualDay = standardizeDay(currentYear, currentMonth, currentDay);
const date = createUTCDate(currentYear, currentMonth, actualDay);
if (!isValidDate(date, currentYear, currentMonth, actualDay) || date.valueOf() >= targetDate.valueOf()) {
if (date.getUTCFullYear() === targetDate.getUTCFullYear()) {
const resetMonth = date.getUTCMonth() > targetDate.getUTCMonth();
const resetDay = resetMonth || date.getUTCDate() >= targetDate.getUTCDate();
if (resetMonth) {
monthGenerator.skipTo();
}
if (resetDay) {
dayGenerator.skipTo(undefined, true);
}
}
getNextYear = false;
getNextMonth = false;
getNextDay = true;
shouldResetDay = false;
continue;
}
return date;
}
}