fix output

This commit is contained in:
2026-01-27 16:47:33 +03:30
parent c122b00647
commit a99c6aa051
4582 changed files with 389930 additions and 2514 deletions
+5
View File
@@ -0,0 +1,5 @@
export function addLeadingZeros(number, targetLength) {
const sign = number < 0 ? "-" : "";
const output = Math.abs(number).toString().padStart(targetLength, "0");
return sign + output;
}
+1
View File
@@ -0,0 +1 @@
export { enUS as defaultLocale } from "../locale/en-US.js";
+9
View File
@@ -0,0 +1,9 @@
let defaultOptions = {};
export function getDefaultOptions() {
return defaultOptions;
}
export function setDefaultOptions(newOptions) {
defaultOptions = newOptions;
}
+776
View File
@@ -0,0 +1,776 @@
import { getDayOfYear } from "../../getDayOfYear.js";
import { getISOWeek } from "../../getISOWeek.js";
import { getISOWeekYear } from "../../getISOWeekYear.js";
import { getWeek } from "../../getWeek.js";
import { getWeekYear } from "../../getWeekYear.js";
import { addLeadingZeros } from "../addLeadingZeros.js";
import { lightFormatters } from "./lightFormatters.js";
const dayPeriodEnum = {
am: "am",
pm: "pm",
midnight: "midnight",
noon: "noon",
morning: "morning",
afternoon: "afternoon",
evening: "evening",
night: "night",
};
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | Milliseconds in day |
* | b | AM, PM, noon, midnight | B | Flexible day period |
* | c | Stand-alone local day of week | C* | Localized hour w/ day period |
* | d | Day of month | D | Day of year |
* | e | Local day of week | E | Day of week |
* | f | | F* | Day of week in month |
* | g* | Modified Julian day | G | Era |
* | h | Hour [1-12] | H | Hour [0-23] |
* | i! | ISO day of week | I! | ISO week of year |
* | j* | Localized hour w/ day period | J* | Localized hour w/o day period |
* | k | Hour [1-24] | K | Hour [0-11] |
* | l* | (deprecated) | L | Stand-alone month |
* | m | Minute | M | Month |
* | n | | N | |
* | o! | Ordinal number modifier | O | Timezone (GMT) |
* | p! | Long localized time | P! | Long localized date |
* | q | Stand-alone quarter | Q | Quarter |
* | r* | Related Gregorian year | R! | ISO week-numbering year |
* | s | Second | S | Fraction of second |
* | t! | Seconds timestamp | T! | Milliseconds timestamp |
* | u | Extended year | U* | Cyclic year |
* | v* | Timezone (generic non-locat.) | V* | Timezone (location) |
* | w | Local week of year | W* | Week of month |
* | x | Timezone (ISO-8601 w/o Z) | X | Timezone (ISO-8601) |
* | y | Year (abs) | Y | Local week-numbering year |
* | z | Timezone (specific non-locat.) | Z* | Timezone (aliases) |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*
* Letters marked by ! are non-standard, but implemented by date-fns:
* - `o` modifies the previous token to turn it into an ordinal (see `format` docs)
* - `i` is ISO day of week. For `i` and `ii` is returns numeric ISO week days,
* i.e. 7 for Sunday, 1 for Monday, etc.
* - `I` is ISO week of year, as opposed to `w` which is local week of year.
* - `R` is ISO week-numbering year, as opposed to `Y` which is local week-numbering year.
* `R` is supposed to be used in conjunction with `I` and `i`
* for universal ISO week-numbering date, whereas
* `Y` is supposed to be used in conjunction with `w` and `e`
* for week-numbering date specific to the locale.
* - `P` is long localized date format
* - `p` is long localized time format
*/
export const formatters = {
// Era
G: function (date, token, localize) {
const era = date.getFullYear() > 0 ? 1 : 0;
switch (token) {
// AD, BC
case "G":
case "GG":
case "GGG":
return localize.era(era, { width: "abbreviated" });
// A, B
case "GGGGG":
return localize.era(era, { width: "narrow" });
// Anno Domini, Before Christ
case "GGGG":
default:
return localize.era(era, { width: "wide" });
}
},
// Year
y: function (date, token, localize) {
// Ordinal number
if (token === "yo") {
const signedYear = date.getFullYear();
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const year = signedYear > 0 ? signedYear : 1 - signedYear;
return localize.ordinalNumber(year, { unit: "year" });
}
return lightFormatters.y(date, token);
},
// Local week-numbering year
Y: function (date, token, localize, options) {
const signedWeekYear = getWeekYear(date, options);
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const weekYear = signedWeekYear > 0 ? signedWeekYear : 1 - signedWeekYear;
// Two digit year
if (token === "YY") {
const twoDigitYear = weekYear % 100;
return addLeadingZeros(twoDigitYear, 2);
}
// Ordinal number
if (token === "Yo") {
return localize.ordinalNumber(weekYear, { unit: "year" });
}
// Padding
return addLeadingZeros(weekYear, token.length);
},
// ISO week-numbering year
R: function (date, token) {
const isoWeekYear = getISOWeekYear(date);
// Padding
return addLeadingZeros(isoWeekYear, token.length);
},
// Extended year. This is a single number designating the year of this calendar system.
// The main difference between `y` and `u` localizers are B.C. years:
// | Year | `y` | `u` |
// |------|-----|-----|
// | AC 1 | 1 | 1 |
// | BC 1 | 1 | 0 |
// | BC 2 | 2 | -1 |
// Also `yy` always returns the last two digits of a year,
// while `uu` pads single digit years to 2 characters and returns other years unchanged.
u: function (date, token) {
const year = date.getFullYear();
return addLeadingZeros(year, token.length);
},
// Quarter
Q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "Q":
return String(quarter);
// 01, 02, 03, 04
case "QQ":
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "Qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "QQQ":
return localize.quarter(quarter, {
width: "abbreviated",
context: "formatting",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "QQQQQ":
return localize.quarter(quarter, {
width: "narrow",
context: "formatting",
});
// 1st quarter, 2nd quarter, ...
case "QQQQ":
default:
return localize.quarter(quarter, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone quarter
q: function (date, token, localize) {
const quarter = Math.ceil((date.getMonth() + 1) / 3);
switch (token) {
// 1, 2, 3, 4
case "q":
return String(quarter);
// 01, 02, 03, 04
case "qq":
return addLeadingZeros(quarter, 2);
// 1st, 2nd, 3rd, 4th
case "qo":
return localize.ordinalNumber(quarter, { unit: "quarter" });
// Q1, Q2, Q3, Q4
case "qqq":
return localize.quarter(quarter, {
width: "abbreviated",
context: "standalone",
});
// 1, 2, 3, 4 (narrow quarter; could be not numerical)
case "qqqqq":
return localize.quarter(quarter, {
width: "narrow",
context: "standalone",
});
// 1st quarter, 2nd quarter, ...
case "qqqq":
default:
return localize.quarter(quarter, {
width: "wide",
context: "standalone",
});
}
},
// Month
M: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
case "M":
case "MM":
return lightFormatters.M(date, token);
// 1st, 2nd, ..., 12th
case "Mo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "MMM":
return localize.month(month, {
width: "abbreviated",
context: "formatting",
});
// J, F, ..., D
case "MMMMM":
return localize.month(month, {
width: "narrow",
context: "formatting",
});
// January, February, ..., December
case "MMMM":
default:
return localize.month(month, { width: "wide", context: "formatting" });
}
},
// Stand-alone month
L: function (date, token, localize) {
const month = date.getMonth();
switch (token) {
// 1, 2, ..., 12
case "L":
return String(month + 1);
// 01, 02, ..., 12
case "LL":
return addLeadingZeros(month + 1, 2);
// 1st, 2nd, ..., 12th
case "Lo":
return localize.ordinalNumber(month + 1, { unit: "month" });
// Jan, Feb, ..., Dec
case "LLL":
return localize.month(month, {
width: "abbreviated",
context: "standalone",
});
// J, F, ..., D
case "LLLLL":
return localize.month(month, {
width: "narrow",
context: "standalone",
});
// January, February, ..., December
case "LLLL":
default:
return localize.month(month, { width: "wide", context: "standalone" });
}
},
// Local week of year
w: function (date, token, localize, options) {
const week = getWeek(date, options);
if (token === "wo") {
return localize.ordinalNumber(week, { unit: "week" });
}
return addLeadingZeros(week, token.length);
},
// ISO week of year
I: function (date, token, localize) {
const isoWeek = getISOWeek(date);
if (token === "Io") {
return localize.ordinalNumber(isoWeek, { unit: "week" });
}
return addLeadingZeros(isoWeek, token.length);
},
// Day of the month
d: function (date, token, localize) {
if (token === "do") {
return localize.ordinalNumber(date.getDate(), { unit: "date" });
}
return lightFormatters.d(date, token);
},
// Day of year
D: function (date, token, localize) {
const dayOfYear = getDayOfYear(date);
if (token === "Do") {
return localize.ordinalNumber(dayOfYear, { unit: "dayOfYear" });
}
return addLeadingZeros(dayOfYear, token.length);
},
// Day of week
E: function (date, token, localize) {
const dayOfWeek = date.getDay();
switch (token) {
// Tue
case "E":
case "EE":
case "EEE":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "EEEEE":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "EEEEEE":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "EEEE":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Local day of week
e: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (Nth day of week with current locale or weekStartsOn)
case "e":
return String(localDayOfWeek);
// Padded numerical value
case "ee":
return addLeadingZeros(localDayOfWeek, 2);
// 1st, 2nd, ..., 7th
case "eo":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "eee":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "eeeee":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "eeeeee":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "eeee":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// Stand-alone local day of week
c: function (date, token, localize, options) {
const dayOfWeek = date.getDay();
const localDayOfWeek = (dayOfWeek - options.weekStartsOn + 8) % 7 || 7;
switch (token) {
// Numerical value (same as in `e`)
case "c":
return String(localDayOfWeek);
// Padded numerical value
case "cc":
return addLeadingZeros(localDayOfWeek, token.length);
// 1st, 2nd, ..., 7th
case "co":
return localize.ordinalNumber(localDayOfWeek, { unit: "day" });
case "ccc":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "standalone",
});
// T
case "ccccc":
return localize.day(dayOfWeek, {
width: "narrow",
context: "standalone",
});
// Tu
case "cccccc":
return localize.day(dayOfWeek, {
width: "short",
context: "standalone",
});
// Tuesday
case "cccc":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "standalone",
});
}
},
// ISO day of week
i: function (date, token, localize) {
const dayOfWeek = date.getDay();
const isoDayOfWeek = dayOfWeek === 0 ? 7 : dayOfWeek;
switch (token) {
// 2
case "i":
return String(isoDayOfWeek);
// 02
case "ii":
return addLeadingZeros(isoDayOfWeek, token.length);
// 2nd
case "io":
return localize.ordinalNumber(isoDayOfWeek, { unit: "day" });
// Tue
case "iii":
return localize.day(dayOfWeek, {
width: "abbreviated",
context: "formatting",
});
// T
case "iiiii":
return localize.day(dayOfWeek, {
width: "narrow",
context: "formatting",
});
// Tu
case "iiiiii":
return localize.day(dayOfWeek, {
width: "short",
context: "formatting",
});
// Tuesday
case "iiii":
default:
return localize.day(dayOfWeek, {
width: "wide",
context: "formatting",
});
}
},
// AM or PM
a: function (date, token, localize) {
const hours = date.getHours();
const dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
switch (token) {
case "a":
case "aa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "aaa":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "aaaaa":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "aaaa":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// AM, PM, midnight, noon
b: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours === 12) {
dayPeriodEnumValue = dayPeriodEnum.noon;
} else if (hours === 0) {
dayPeriodEnumValue = dayPeriodEnum.midnight;
} else {
dayPeriodEnumValue = hours / 12 >= 1 ? "pm" : "am";
}
switch (token) {
case "b":
case "bb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "bbb":
return localize
.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
})
.toLowerCase();
case "bbbbb":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "bbbb":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// in the morning, in the afternoon, in the evening, at night
B: function (date, token, localize) {
const hours = date.getHours();
let dayPeriodEnumValue;
if (hours >= 17) {
dayPeriodEnumValue = dayPeriodEnum.evening;
} else if (hours >= 12) {
dayPeriodEnumValue = dayPeriodEnum.afternoon;
} else if (hours >= 4) {
dayPeriodEnumValue = dayPeriodEnum.morning;
} else {
dayPeriodEnumValue = dayPeriodEnum.night;
}
switch (token) {
case "B":
case "BB":
case "BBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "abbreviated",
context: "formatting",
});
case "BBBBB":
return localize.dayPeriod(dayPeriodEnumValue, {
width: "narrow",
context: "formatting",
});
case "BBBB":
default:
return localize.dayPeriod(dayPeriodEnumValue, {
width: "wide",
context: "formatting",
});
}
},
// Hour [1-12]
h: function (date, token, localize) {
if (token === "ho") {
let hours = date.getHours() % 12;
if (hours === 0) hours = 12;
return localize.ordinalNumber(hours, { unit: "hour" });
}
return lightFormatters.h(date, token);
},
// Hour [0-23]
H: function (date, token, localize) {
if (token === "Ho") {
return localize.ordinalNumber(date.getHours(), { unit: "hour" });
}
return lightFormatters.H(date, token);
},
// Hour [0-11]
K: function (date, token, localize) {
const hours = date.getHours() % 12;
if (token === "Ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return addLeadingZeros(hours, token.length);
},
// Hour [1-24]
k: function (date, token, localize) {
let hours = date.getHours();
if (hours === 0) hours = 24;
if (token === "ko") {
return localize.ordinalNumber(hours, { unit: "hour" });
}
return addLeadingZeros(hours, token.length);
},
// Minute
m: function (date, token, localize) {
if (token === "mo") {
return localize.ordinalNumber(date.getMinutes(), { unit: "minute" });
}
return lightFormatters.m(date, token);
},
// Second
s: function (date, token, localize) {
if (token === "so") {
return localize.ordinalNumber(date.getSeconds(), { unit: "second" });
}
return lightFormatters.s(date, token);
},
// Fraction of second
S: function (date, token) {
return lightFormatters.S(date, token);
},
// Timezone (ISO-8601. If offset is 0, output is always `'Z'`)
X: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
if (timezoneOffset === 0) {
return "Z";
}
switch (token) {
// Hours and optional minutes
case "X":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XX`
case "XXXX":
case "XX": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `XXX`
case "XXXXX":
case "XXX": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (ISO-8601. If offset is 0, output is `'+00:00'` or equivalent)
x: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Hours and optional minutes
case "x":
return formatTimezoneWithOptionalMinutes(timezoneOffset);
// Hours, minutes and optional seconds without `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xx`
case "xxxx":
case "xx": // Hours and minutes without `:` delimiter
return formatTimezone(timezoneOffset);
// Hours, minutes and optional seconds with `:` delimiter
// Note: neither ISO-8601 nor JavaScript supports seconds in timezone offsets
// so this token always has the same output as `xxx`
case "xxxxx":
case "xxx": // Hours and minutes with `:` delimiter
default:
return formatTimezone(timezoneOffset, ":");
}
},
// Timezone (GMT)
O: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "O":
case "OO":
case "OOO":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "OOOO":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Timezone (specific non-location)
z: function (date, token, _localize) {
const timezoneOffset = date.getTimezoneOffset();
switch (token) {
// Short
case "z":
case "zz":
case "zzz":
return "GMT" + formatTimezoneShort(timezoneOffset, ":");
// Long
case "zzzz":
default:
return "GMT" + formatTimezone(timezoneOffset, ":");
}
},
// Seconds timestamp
t: function (date, token, _localize) {
const timestamp = Math.trunc(+date / 1000);
return addLeadingZeros(timestamp, token.length);
},
// Milliseconds timestamp
T: function (date, token, _localize) {
return addLeadingZeros(+date, token.length);
},
};
function formatTimezoneShort(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = Math.trunc(absOffset / 60);
const minutes = absOffset % 60;
if (minutes === 0) {
return sign + String(hours);
}
return sign + String(hours) + delimiter + addLeadingZeros(minutes, 2);
}
function formatTimezoneWithOptionalMinutes(offset, delimiter) {
if (offset % 60 === 0) {
const sign = offset > 0 ? "-" : "+";
return sign + addLeadingZeros(Math.abs(offset) / 60, 2);
}
return formatTimezone(offset, delimiter);
}
function formatTimezone(offset, delimiter = "") {
const sign = offset > 0 ? "-" : "+";
const absOffset = Math.abs(offset);
const hours = addLeadingZeros(Math.trunc(absOffset / 60), 2);
const minutes = addLeadingZeros(absOffset % 60, 2);
return sign + hours + delimiter + minutes;
}
+92
View File
@@ -0,0 +1,92 @@
import { addLeadingZeros } from "../addLeadingZeros.js";
/*
* | | Unit | | Unit |
* |-----|--------------------------------|-----|--------------------------------|
* | a | AM, PM | A* | |
* | d | Day of month | D | |
* | h | Hour [1-12] | H | Hour [0-23] |
* | m | Minute | M | Month |
* | s | Second | S | Fraction of second |
* | y | Year (abs) | Y | |
*
* Letters marked by * are not implemented but reserved by Unicode standard.
*/
export const lightFormatters = {
// Year
y(date, token) {
// From http://www.unicode.org/reports/tr35/tr35-31/tr35-dates.html#Date_Format_tokens
// | Year | y | yy | yyy | yyyy | yyyyy |
// |----------|-------|----|-------|-------|-------|
// | AD 1 | 1 | 01 | 001 | 0001 | 00001 |
// | AD 12 | 12 | 12 | 012 | 0012 | 00012 |
// | AD 123 | 123 | 23 | 123 | 0123 | 00123 |
// | AD 1234 | 1234 | 34 | 1234 | 1234 | 01234 |
// | AD 12345 | 12345 | 45 | 12345 | 12345 | 12345 |
const signedYear = date.getFullYear();
// Returns 1 for 1 BC (which is year 0 in JavaScript)
const year = signedYear > 0 ? signedYear : 1 - signedYear;
return addLeadingZeros(token === "yy" ? year % 100 : year, token.length);
},
// Month
M(date, token) {
const month = date.getMonth();
return token === "M" ? String(month + 1) : addLeadingZeros(month + 1, 2);
},
// Day of the month
d(date, token) {
return addLeadingZeros(date.getDate(), token.length);
},
// AM or PM
a(date, token) {
const dayPeriodEnumValue = date.getHours() / 12 >= 1 ? "pm" : "am";
switch (token) {
case "a":
case "aa":
return dayPeriodEnumValue.toUpperCase();
case "aaa":
return dayPeriodEnumValue;
case "aaaaa":
return dayPeriodEnumValue[0];
case "aaaa":
default:
return dayPeriodEnumValue === "am" ? "a.m." : "p.m.";
}
},
// Hour [1-12]
h(date, token) {
return addLeadingZeros(date.getHours() % 12 || 12, token.length);
},
// Hour [0-23]
H(date, token) {
return addLeadingZeros(date.getHours(), token.length);
},
// Minute
m(date, token) {
return addLeadingZeros(date.getMinutes(), token.length);
},
// Second
s(date, token) {
return addLeadingZeros(date.getSeconds(), token.length);
},
// Fraction of second
S(date, token) {
const numberOfDigits = token.length;
const milliseconds = date.getMilliseconds();
const fractionalSeconds = Math.trunc(
milliseconds * Math.pow(10, numberOfDigits - 3),
);
return addLeadingZeros(fractionalSeconds, token.length);
},
};
+64
View File
@@ -0,0 +1,64 @@
const dateLongFormatter = (pattern, formatLong) => {
switch (pattern) {
case "P":
return formatLong.date({ width: "short" });
case "PP":
return formatLong.date({ width: "medium" });
case "PPP":
return formatLong.date({ width: "long" });
case "PPPP":
default:
return formatLong.date({ width: "full" });
}
};
const timeLongFormatter = (pattern, formatLong) => {
switch (pattern) {
case "p":
return formatLong.time({ width: "short" });
case "pp":
return formatLong.time({ width: "medium" });
case "ppp":
return formatLong.time({ width: "long" });
case "pppp":
default:
return formatLong.time({ width: "full" });
}
};
const dateTimeLongFormatter = (pattern, formatLong) => {
const matchResult = pattern.match(/(P+)(p+)?/) || [];
const datePattern = matchResult[1];
const timePattern = matchResult[2];
if (!timePattern) {
return dateLongFormatter(pattern, formatLong);
}
let dateTimeFormat;
switch (datePattern) {
case "P":
dateTimeFormat = formatLong.dateTime({ width: "short" });
break;
case "PP":
dateTimeFormat = formatLong.dateTime({ width: "medium" });
break;
case "PPP":
dateTimeFormat = formatLong.dateTime({ width: "long" });
break;
case "PPPP":
default:
dateTimeFormat = formatLong.dateTime({ width: "full" });
break;
}
return dateTimeFormat
.replace("{{date}}", dateLongFormatter(datePattern, formatLong))
.replace("{{time}}", timeLongFormatter(timePattern, formatLong));
};
export const longFormatters = {
p: timeLongFormatter,
P: dateTimeLongFormatter,
};
+8
View File
@@ -0,0 +1,8 @@
export function getRoundingMethod(method) {
return (number) => {
const round = method ? Math[method] : Math.trunc;
const result = round(number);
// Prevent negative zero
return result === 0 ? 0 : result;
};
}
@@ -0,0 +1,29 @@
import { toDate } from "../toDate.js";
/**
* Google Chrome as of 67.0.3396.87 introduced timezones with offset that includes seconds.
* They usually appear for dates that denote time before the timezones were introduced
* (e.g. for 'Europe/Prague' timezone the offset is GMT+00:57:44 before 1 October 1891
* and GMT+01:00:00 after that date)
*
* Date#getTimezoneOffset returns the offset in minutes and would return 57 for the example above,
* which would lead to incorrect calculations.
*
* This function returns the timezone offset in milliseconds that takes seconds in account.
*/
export function getTimezoneOffsetInMilliseconds(date) {
const _date = toDate(date);
const utcDate = new Date(
Date.UTC(
_date.getFullYear(),
_date.getMonth(),
_date.getDate(),
_date.getHours(),
_date.getMinutes(),
_date.getSeconds(),
_date.getMilliseconds(),
),
);
utcDate.setUTCFullYear(_date.getFullYear());
return +date - +utcDate;
}
+9
View File
@@ -0,0 +1,9 @@
import { constructFrom } from "../constructFrom.js";
export function normalizeDates(context, ...dates) {
const normalize = constructFrom.bind(
null,
context || dates.find((date) => typeof date === "object"),
);
return dates.map(normalize);
}
+6
View File
@@ -0,0 +1,6 @@
import { normalizeDates } from "./normalizeDates.js";
export function normalizeInterval(context, interval) {
const [start, end] = normalizeDates(context, interval.start, interval.end);
return { start, end };
}
+23
View File
@@ -0,0 +1,23 @@
const dayOfYearTokenRE = /^D+$/;
const weekYearTokenRE = /^Y+$/;
const throwTokens = ["D", "DD", "YY", "YYYY"];
export function isProtectedDayOfYearToken(token) {
return dayOfYearTokenRE.test(token);
}
export function isProtectedWeekYearToken(token) {
return weekYearTokenRE.test(token);
}
export function warnOrThrowProtectedError(token, format, input) {
const _message = message(token, format, input);
console.warn(_message);
if (throwTokens.includes(token)) throw new RangeError(_message);
}
function message(token, format, input) {
const subject = token[0] === "Y" ? "years" : "days of the month";
return `Use \`${token.toLowerCase()}\` instead of \`${token}\` (in \`${format}\`) for formatting ${subject} to the input \`${input}\`; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md`;
}
+69
View File
@@ -0,0 +1,69 @@
import { addDays } from "./addDays.js";
import { addMonths } from "./addMonths.js";
import { constructFrom } from "./constructFrom.js";
import { toDate } from "./toDate.js";
/**
* The {@link add} function options.
*/
/**
* @name add
* @category Common Helpers
* @summary Add the specified years, months, weeks, days, hours, minutes, and seconds to the given date.
*
* @description
* Add the specified years, months, weeks, days, hours, minutes, and seconds to the given date.
*
* @typeParam DateType - The `Date` type the function operates on. Gets inferred from passed arguments. Allows using extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param duration - The object with years, months, weeks, days, hours, minutes, and seconds to be added.
* @param options - An object with options
*
* @returns The new date with the seconds added
*
* @example
* // Add the following duration to 1 September 2014, 10:19:50
* const result = add(new Date(2014, 8, 1, 10, 19, 50), {
* years: 2,
* months: 9,
* weeks: 1,
* days: 7,
* hours: 5,
* minutes: 9,
* seconds: 30,
* })
* //=> Thu Jun 15 2017 15:29:20
*/
export function add(date, duration, options) {
const {
years = 0,
months = 0,
weeks = 0,
days = 0,
hours = 0,
minutes = 0,
seconds = 0,
} = duration;
// Add years and months
const _date = toDate(date, options?.in);
const dateWithMonths =
months || years ? addMonths(_date, months + years * 12) : _date;
// Add weeks and days
const dateWithDays =
days || weeks ? addDays(dateWithMonths, days + weeks * 7) : dateWithMonths;
// Add days, hours, minutes, and seconds
const minutesToAdd = minutes + hours * 60;
const secondsToAdd = seconds + minutesToAdd * 60;
const msToAdd = secondsToAdd * 1000;
return constructFrom(options?.in || date, +dateWithDays + msToAdd);
}
// Fallback for modularized imports:
export default add;
+73
View File
@@ -0,0 +1,73 @@
import { constructFrom } from "./constructFrom.js";
import { isSaturday } from "./isSaturday.js";
import { isSunday } from "./isSunday.js";
import { isWeekend } from "./isWeekend.js";
import { toDate } from "./toDate.js";
/**
* The {@link addBusinessDays} function options.
*/
/**
* @name addBusinessDays
* @category Day Helpers
* @summary Add the specified number of business days (mon - fri) to the given date.
*
* @description
* Add the specified number of business days (mon - fri) to the given date, ignoring weekends.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of business days to be added.
* @param options - An object with options
*
* @returns The new date with the business days added
*
* @example
* // Add 10 business days to 1 September 2014:
* const result = addBusinessDays(new Date(2014, 8, 1), 10)
* //=> Mon Sep 15 2014 00:00:00 (skipped weekend days)
*/
export function addBusinessDays(date, amount, options) {
const _date = toDate(date, options?.in);
const startedOnWeekend = isWeekend(_date, options);
if (isNaN(amount)) return constructFrom(options?.in, NaN);
const hours = _date.getHours();
const sign = amount < 0 ? -1 : 1;
const fullWeeks = Math.trunc(amount / 5);
_date.setDate(_date.getDate() + fullWeeks * 7);
// Get remaining days not part of a full week
let restDays = Math.abs(amount % 5);
// Loops over remaining days
while (restDays > 0) {
_date.setDate(_date.getDate() + sign);
if (!isWeekend(_date, options)) restDays -= 1;
}
// If the date is a weekend day and we reduce a dividable of
// 5 from it, we land on a weekend date.
// To counter this, we add days accordingly to land on the next business day
if (startedOnWeekend && isWeekend(_date, options) && amount !== 0) {
// If we're reducing days, we want to add days until we land on a weekday
// If we're adding days we want to reduce days until we land on a weekday
if (isSaturday(_date, options))
_date.setDate(_date.getDate() + (sign < 0 ? 2 : -1));
if (isSunday(_date, options))
_date.setDate(_date.getDate() + (sign < 0 ? 1 : -2));
}
// Restore hours to avoid DST lag
_date.setHours(hours);
return _date;
}
// Fallback for modularized imports:
export default addBusinessDays;
+42
View File
@@ -0,0 +1,42 @@
import { constructFrom } from "./constructFrom.js";
import { toDate } from "./toDate.js";
/**
* The {@link addDays} function options.
*/
/**
* @name addDays
* @category Day Helpers
* @summary Add the specified number of days to the given date.
*
* @description
* Add the specified number of days to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of days to be added.
* @param options - An object with options
*
* @returns The new date with the days added
*
* @example
* // Add 10 days to 1 September 2014:
* const result = addDays(new Date(2014, 8, 1), 10)
* //=> Thu Sep 11 2014 00:00:00
*/
export function addDays(date, amount, options) {
const _date = toDate(date, options?.in);
if (isNaN(amount)) return constructFrom(options?.in || date, NaN);
// If 0 days, no-op to avoid changing times in the hour before end of DST
if (!amount) return _date;
_date.setDate(_date.getDate() + amount);
return _date;
}
// Fallback for modularized imports:
export default addDays;
+35
View File
@@ -0,0 +1,35 @@
import { addMilliseconds } from "./addMilliseconds.js";
import { millisecondsInHour } from "./constants.js";
/**
* The {@link addHours} function options.
*/
/**
* @name addHours
* @category Hour Helpers
* @summary Add the specified number of hours to the given date.
*
* @description
* Add the specified number of hours to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of hours to be added
* @param options - An object with options
*
* @returns The new date with the hours added
*
* @example
* // Add 2 hours to 10 July 2014 23:00:00:
* const result = addHours(new Date(2014, 6, 10, 23, 0), 2)
* //=> Fri Jul 11 2014 01:00:00
*/
export function addHours(date, amount, options) {
return addMilliseconds(date, amount * millisecondsInHour, options);
}
// Fallback for modularized imports:
export default addHours;
+36
View File
@@ -0,0 +1,36 @@
import { getISOWeekYear } from "./getISOWeekYear.js";
import { setISOWeekYear } from "./setISOWeekYear.js";
/**
* The {@link addISOWeekYears} function options.
*/
/**
* @name addISOWeekYears
* @category ISO Week-Numbering Year Helpers
* @summary Add the specified number of ISO week-numbering years to the given date.
*
* @description
* Add the specified number of ISO week-numbering years to the given date.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
*
* @param date - The date to be changed
* @param amount - The amount of ISO week-numbering years to be added.
* @param options - An object with options
*
* @returns The new date with the ISO week-numbering years added
*
* @example
* // Add 5 ISO week-numbering years to 2 July 2010:
* const result = addISOWeekYears(new Date(2010, 6, 2), 5)
* //=> Fri Jun 26 2015 00:00:00
*/
export function addISOWeekYears(date, amount, options) {
return setISOWeekYear(date, getISOWeekYear(date, options) + amount, options);
}
// Fallback for modularized imports:
export default addISOWeekYears;
+35
View File
@@ -0,0 +1,35 @@
import { constructFrom } from "./constructFrom.js";
import { toDate } from "./toDate.js";
/**
* The {@link addMilliseconds} function options.
*/
/**
* @name addMilliseconds
* @category Millisecond Helpers
* @summary Add the specified number of milliseconds to the given date.
*
* @description
* Add the specified number of milliseconds to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of milliseconds to be added.
* @param options - The options object
*
* @returns The new date with the milliseconds added
*
* @example
* // Add 750 milliseconds to 10 July 2014 12:45:30.000:
* const result = addMilliseconds(new Date(2014, 6, 10, 12, 45, 30, 0), 750)
* //=> Thu Jul 10 2014 12:45:30.750
*/
export function addMilliseconds(date, amount, options) {
return constructFrom(options?.in || date, +toDate(date) + amount);
}
// Fallback for modularized imports:
export default addMilliseconds;
+37
View File
@@ -0,0 +1,37 @@
import { millisecondsInMinute } from "./constants.js";
import { toDate } from "./toDate.js";
/**
* The {@link addMinutes} function options.
*/
/**
* @name addMinutes
* @category Minute Helpers
* @summary Add the specified number of minutes to the given date.
*
* @description
* Add the specified number of minutes to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of minutes to be added.
* @param options - An object with options
*
* @returns The new date with the minutes added
*
* @example
* // Add 30 minutes to 10 July 2014 12:00:00:
* const result = addMinutes(new Date(2014, 6, 10, 12, 0), 30)
* //=> Thu Jul 10 2014 12:30:00
*/
export function addMinutes(date, amount, options) {
const _date = toDate(date, options?.in);
_date.setTime(_date.getTime() + amount * millisecondsInMinute);
return _date;
}
// Fallback for modularized imports:
export default addMinutes;
+76
View File
@@ -0,0 +1,76 @@
import { constructFrom } from "./constructFrom.js";
import { toDate } from "./toDate.js";
/**
* The {@link addMonths} function options.
*/
/**
* @name addMonths
* @category Month Helpers
* @summary Add the specified number of months to the given date.
*
* @description
* Add the specified number of months to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of months to be added.
* @param options - The options object
*
* @returns The new date with the months added
*
* @example
* // Add 5 months to 1 September 2014:
* const result = addMonths(new Date(2014, 8, 1), 5)
* //=> Sun Feb 01 2015 00:00:00
*
* // Add one month to 30 January 2023:
* const result = addMonths(new Date(2023, 0, 30), 1)
* //=> Tue Feb 28 2023 00:00:00
*/
export function addMonths(date, amount, options) {
const _date = toDate(date, options?.in);
if (isNaN(amount)) return constructFrom(options?.in || date, NaN);
if (!amount) {
// If 0 months, no-op to avoid changing times in the hour before end of DST
return _date;
}
const dayOfMonth = _date.getDate();
// The JS Date object supports date math by accepting out-of-bounds values for
// month, day, etc. For example, new Date(2020, 0, 0) returns 31 Dec 2019 and
// new Date(2020, 13, 1) returns 1 Feb 2021. This is *almost* the behavior we
// want except that dates will wrap around the end of a month, meaning that
// new Date(2020, 13, 31) will return 3 Mar 2021 not 28 Feb 2021 as desired. So
// we'll default to the end of the desired month by adding 1 to the desired
// month and using a date of 0 to back up one day to the end of the desired
// month.
const endOfDesiredMonth = constructFrom(options?.in || date, _date.getTime());
endOfDesiredMonth.setMonth(_date.getMonth() + amount + 1, 0);
const daysInMonth = endOfDesiredMonth.getDate();
if (dayOfMonth >= daysInMonth) {
// If we're already at the end of the month, then this is the correct date
// and we're done.
return endOfDesiredMonth;
} else {
// Otherwise, we now know that setting the original day-of-month value won't
// cause an overflow, so set the desired day-of-month. Note that we can't
// just set the date of `endOfDesiredMonth` because that object may have had
// its time changed in the unusual case where where a DST transition was on
// the last day of the month and its local time was in the hour skipped or
// repeated next to a DST transition. So we use `date` instead which is
// guaranteed to still have the original time.
_date.setFullYear(
endOfDesiredMonth.getFullYear(),
endOfDesiredMonth.getMonth(),
dayOfMonth,
);
return _date;
}
}
// Fallback for modularized imports:
export default addMonths;
+34
View File
@@ -0,0 +1,34 @@
import { addMonths } from "./addMonths.js";
/**
* The {@link addQuarters} function options.
*/
/**
* @name addQuarters
* @category Quarter Helpers
* @summary Add the specified number of year quarters to the given date.
*
* @description
* Add the specified number of year quarters to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of quarters to be added.
* @param options - An object with options
*
* @returns The new date with the quarters added
*
* @example
* // Add 1 quarter to 1 September 2014:
* const result = addQuarters(new Date(2014, 8, 1), 1)
* //=; Mon Dec 01 2014 00:00:00
*/
export function addQuarters(date, amount, options) {
return addMonths(date, amount * 3, options);
}
// Fallback for modularized imports:
export default addQuarters;
+34
View File
@@ -0,0 +1,34 @@
import { addMilliseconds } from "./addMilliseconds.js";
/**
* The {@link addSeconds} function options.
*/
/**
* @name addSeconds
* @category Second Helpers
* @summary Add the specified number of seconds to the given date.
*
* @description
* Add the specified number of seconds to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of seconds to be added.
* @param options - An object with options
*
* @returns The new date with the seconds added
*
* @example
* // Add 30 seconds to 10 July 2014 12:45:00:
* const result = addSeconds(new Date(2014, 6, 10, 12, 45, 0), 30)
* //=> Thu Jul 10 2014 12:45:30
*/
export function addSeconds(date, amount, options) {
return addMilliseconds(date, amount * 1000, options);
}
// Fallback for modularized imports:
export default addSeconds;
+34
View File
@@ -0,0 +1,34 @@
import { addDays } from "./addDays.js";
/**
* The {@link addWeeks} function options.
*/
/**
* @name addWeeks
* @category Week Helpers
* @summary Add the specified number of weeks to the given date.
*
* @description
* Add the specified number of weeks to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The date to be changed
* @param amount - The amount of weeks to be added.
* @param options - An object with options
*
* @returns The new date with the weeks added
*
* @example
* // Add 4 weeks to 1 September 2014:
* const result = addWeeks(new Date(2014, 8, 1), 4)
* //=> Mon Sep 29 2014 00:00:00
*/
export function addWeeks(date, amount, options) {
return addDays(date, amount * 7, options);
}
// Fallback for modularized imports:
export default addWeeks;
+34
View File
@@ -0,0 +1,34 @@
import { addMonths } from "./addMonths.js";
/**
* The {@link addYears} function options.
*/
/**
* @name addYears
* @category Year Helpers
* @summary Add the specified number of years to the given date.
*
* @description
* Add the specified number of years to the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type.
*
* @param date - The date to be changed
* @param amount - The amount of years to be added.
* @param options - The options
*
* @returns The new date with the years added
*
* @example
* // Add 5 years to 1 September 2014:
* const result = addYears(new Date(2014, 8, 1), 5)
* //=> Sun Sep 01 2019 00:00:00
*/
export function addYears(date, amount, options) {
return addMonths(date, amount * 12, options);
}
// Fallback for modularized imports:
export default addYears;
+71
View File
@@ -0,0 +1,71 @@
import { toDate } from "./toDate.js";
/**
* The {@link areIntervalsOverlapping} function options.
*/
/**
* @name areIntervalsOverlapping
* @category Interval Helpers
* @summary Is the given time interval overlapping with another time interval?
*
* @description
* Is the given time interval overlapping with another time interval? Adjacent intervals do not count as overlapping unless `inclusive` is set to `true`.
*
* @param intervalLeft - The first interval to compare.
* @param intervalRight - The second interval to compare.
* @param options - The object with options
*
* @returns Whether the time intervals are overlapping
*
* @example
* // For overlapping time intervals:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 17), end: new Date(2014, 0, 21) }
* )
* //=> true
*
* @example
* // For non-overlapping time intervals:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 21), end: new Date(2014, 0, 22) }
* )
* //=> false
*
* @example
* // For adjacent time intervals:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 20), end: new Date(2014, 0, 30) }
* )
* //=> false
*
* @example
* // Using the inclusive option:
* areIntervalsOverlapping(
* { start: new Date(2014, 0, 10), end: new Date(2014, 0, 20) },
* { start: new Date(2014, 0, 20), end: new Date(2014, 0, 24) },
* { inclusive: true }
* )
* //=> true
*/
export function areIntervalsOverlapping(intervalLeft, intervalRight, options) {
const [leftStartTime, leftEndTime] = [
+toDate(intervalLeft.start, options?.in),
+toDate(intervalLeft.end, options?.in),
].sort((a, b) => a - b);
const [rightStartTime, rightEndTime] = [
+toDate(intervalRight.start, options?.in),
+toDate(intervalRight.end, options?.in),
].sort((a, b) => a - b);
if (options?.inclusive)
return leftStartTime <= rightEndTime && rightStartTime <= leftEndTime;
return leftStartTime < rightEndTime && rightStartTime < leftEndTime;
}
// Fallback for modularized imports:
export default areIntervalsOverlapping;
+59
View File
@@ -0,0 +1,59 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { max } from "./max.js";
import { min } from "./min.js";
/**
* The {@link clamp} function options.
*/
/**
* The {@link clamp} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name clamp
* @category Interval Helpers
* @summary Return a date bounded by the start and the end of the given interval.
*
* @description
* Clamps a date to the lower bound with the start of the interval and the upper
* bound with the end of the interval.
*
* - When the date is less than the start of the interval, the start is returned.
* - When the date is greater than the end of the interval, the end is returned.
* - Otherwise the date is returned.
*
* @typeParam DateType - Date argument type.
* @typeParam IntervalType - Interval argument type.
* @typeParam Options - Options type.
*
* @param date - The date to be bounded
* @param interval - The interval to bound to
* @param options - An object with options
*
* @returns The date bounded by the start and the end of the interval
*
* @example
* // What is Mar 21, 2021 bounded to an interval starting at Mar 22, 2021 and ending at Apr 01, 2021
* const result = clamp(new Date(2021, 2, 21), {
* start: new Date(2021, 2, 22),
* end: new Date(2021, 3, 1),
* })
* //=> Mon Mar 22 2021 00:00:00
*/
export function clamp(date, interval, options) {
const [date_, start, end] = normalizeDates(
options?.in,
date,
interval.start,
interval.end,
);
return min([max([date_, start], options), end], options);
}
// Fallback for modularized imports:
export default clamp;
+57
View File
@@ -0,0 +1,57 @@
import { toDate } from "./toDate.js";
/**
* @name closestIndexTo
* @category Common Helpers
* @summary Return an index of the closest date from the array comparing to the given date.
*
* @description
* Return an index of the closest date from the array comparing to the given date.
*
* @param dateToCompare - The date to compare with
* @param dates - The array to search
*
* @returns An index of the date closest to the given date or undefined if no valid value is given
*
* @example
* // Which date is closer to 6 September 2015?
* const dateToCompare = new Date(2015, 8, 6)
* const datesArray = [
* new Date(2015, 0, 1),
* new Date(2016, 0, 1),
* new Date(2017, 0, 1)
* ]
* const result = closestIndexTo(dateToCompare, datesArray)
* //=> 1
*/
export function closestIndexTo(dateToCompare, dates) {
// [TODO] It would be better to return -1 here rather than undefined, as this
// is how JS behaves, but it would be a breaking change, so we need
// to consider it for v4.
const timeToCompare = +toDate(dateToCompare);
if (isNaN(timeToCompare)) return NaN;
let result;
let minDistance;
dates.forEach((date, index) => {
const date_ = toDate(date);
if (isNaN(+date_)) {
result = NaN;
minDistance = NaN;
return;
}
const distance = Math.abs(timeToCompare - +date_);
if (result == null || distance < minDistance) {
result = index;
minDistance = distance;
}
});
return result;
}
// Fallback for modularized imports:
export default closestIndexTo;
+58
View File
@@ -0,0 +1,58 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { closestIndexTo } from "./closestIndexTo.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link closestTo} function options.
*/
/**
* The {@link closestTo} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name closestTo
* @category Common Helpers
* @summary Return a date from the array closest to the given date.
*
* @description
* Return a date from the array closest to the given date.
*
* @typeParam DateToCompare - Date to compare argument type.
* @typeParam DatesType - Dates array argument type.
* @typeParam Options - Options type.
*
* @param dateToCompare - The date to compare with
* @param dates - The array to search
*
* @returns The date from the array closest to the given date or undefined if no valid value is given
*
* @example
* // Which date is closer to 6 September 2015: 1 January 2000 or 1 January 2030?
* const dateToCompare = new Date(2015, 8, 6)
* const result = closestTo(dateToCompare, [
* new Date(2000, 0, 1),
* new Date(2030, 0, 1)
* ])
* //=> Tue Jan 01 2030 00:00:00
*/
export function closestTo(dateToCompare, dates, options) {
const [dateToCompare_, ...dates_] = normalizeDates(
options?.in,
dateToCompare,
...dates,
);
const index = closestIndexTo(dateToCompare_, dates_);
if (typeof index === "number" && isNaN(index))
return constructFrom(dateToCompare_, NaN);
if (index !== undefined) return dates_[index];
}
// Fallback for modularized imports:
export default closestTo;
+46
View File
@@ -0,0 +1,46 @@
import { toDate } from "./toDate.js";
/**
* @name compareAsc
* @category Common Helpers
* @summary Compare the two dates and return -1, 0 or 1.
*
* @description
* Compare the two dates and return 1 if the first date is after the second,
* -1 if the first date is before the second or 0 if dates are equal.
*
* @param dateLeft - The first date to compare
* @param dateRight - The second date to compare
*
* @returns The result of the comparison
*
* @example
* // Compare 11 February 1987 and 10 July 1989:
* const result = compareAsc(new Date(1987, 1, 11), new Date(1989, 6, 10))
* //=> -1
*
* @example
* // Sort the array of dates:
* const result = [
* new Date(1995, 6, 2),
* new Date(1987, 1, 11),
* new Date(1989, 6, 10)
* ].sort(compareAsc)
* //=> [
* // Wed Feb 11 1987 00:00:00,
* // Mon Jul 10 1989 00:00:00,
* // Sun Jul 02 1995 00:00:00
* // ]
*/
export function compareAsc(dateLeft, dateRight) {
const diff = +toDate(dateLeft) - +toDate(dateRight);
if (diff < 0) return -1;
else if (diff > 0) return 1;
// Return 0 if diff is 0; return NaN if diff is NaN
return diff;
}
// Fallback for modularized imports:
export default compareAsc;
+46
View File
@@ -0,0 +1,46 @@
import { toDate } from "./toDate.js";
/**
* @name compareDesc
* @category Common Helpers
* @summary Compare the two dates reverse chronologically and return -1, 0 or 1.
*
* @description
* Compare the two dates and return -1 if the first date is after the second,
* 1 if the first date is before the second or 0 if dates are equal.
*
* @param dateLeft - The first date to compare
* @param dateRight - The second date to compare
*
* @returns The result of the comparison
*
* @example
* // Compare 11 February 1987 and 10 July 1989 reverse chronologically:
* const result = compareDesc(new Date(1987, 1, 11), new Date(1989, 6, 10))
* //=> 1
*
* @example
* // Sort the array of dates in reverse chronological order:
* const result = [
* new Date(1995, 6, 2),
* new Date(1987, 1, 11),
* new Date(1989, 6, 10)
* ].sort(compareDesc)
* //=> [
* // Sun Jul 02 1995 00:00:00,
* // Mon Jul 10 1989 00:00:00,
* // Wed Feb 11 1987 00:00:00
* // ]
*/
export function compareDesc(dateLeft, dateRight) {
const diff = +toDate(dateLeft) - +toDate(dateRight);
if (diff > 0) return -1;
else if (diff < 0) return 1;
// Return 0 if diff is 0; return NaN if diff is NaN
return diff;
}
// Fallback for modularized imports:
export default compareDesc;
+216
View File
@@ -0,0 +1,216 @@
/**
* @module constants
* @summary Useful constants
* @description
* Collection of useful date constants.
*
* The constants could be imported from `date-fns/constants`:
*
* ```ts
* import { maxTime, minTime } from "./constants/date-fns/constants";
*
* function isAllowedTime(time) {
* return time <= maxTime && time >= minTime;
* }
* ```
*/
/**
* @constant
* @name daysInWeek
* @summary Days in 1 week.
*/
export const daysInWeek = 7;
/**
* @constant
* @name daysInYear
* @summary Days in 1 year.
*
* @description
* How many days in a year.
*
* One years equals 365.2425 days according to the formula:
*
* > Leap year occurs every 4 years, except for years that are divisible by 100 and not divisible by 400.
* > 1 mean year = (365+1/4-1/100+1/400) days = 365.2425 days
*/
export const daysInYear = 365.2425;
/**
* @constant
* @name maxTime
* @summary Maximum allowed time.
*
* @example
* import { maxTime } from "./constants/date-fns/constants";
*
* const isValid = 8640000000000001 <= maxTime;
* //=> false
*
* new Date(8640000000000001);
* //=> Invalid Date
*/
export const maxTime = Math.pow(10, 8) * 24 * 60 * 60 * 1000;
/**
* @constant
* @name minTime
* @summary Minimum allowed time.
*
* @example
* import { minTime } from "./constants/date-fns/constants";
*
* const isValid = -8640000000000001 >= minTime;
* //=> false
*
* new Date(-8640000000000001)
* //=> Invalid Date
*/
export const minTime = -maxTime;
/**
* @constant
* @name millisecondsInWeek
* @summary Milliseconds in 1 week.
*/
export const millisecondsInWeek = 604800000;
/**
* @constant
* @name millisecondsInDay
* @summary Milliseconds in 1 day.
*/
export const millisecondsInDay = 86400000;
/**
* @constant
* @name millisecondsInMinute
* @summary Milliseconds in 1 minute
*/
export const millisecondsInMinute = 60000;
/**
* @constant
* @name millisecondsInHour
* @summary Milliseconds in 1 hour
*/
export const millisecondsInHour = 3600000;
/**
* @constant
* @name millisecondsInSecond
* @summary Milliseconds in 1 second
*/
export const millisecondsInSecond = 1000;
/**
* @constant
* @name minutesInYear
* @summary Minutes in 1 year.
*/
export const minutesInYear = 525600;
/**
* @constant
* @name minutesInMonth
* @summary Minutes in 1 month.
*/
export const minutesInMonth = 43200;
/**
* @constant
* @name minutesInDay
* @summary Minutes in 1 day.
*/
export const minutesInDay = 1440;
/**
* @constant
* @name minutesInHour
* @summary Minutes in 1 hour.
*/
export const minutesInHour = 60;
/**
* @constant
* @name monthsInQuarter
* @summary Months in 1 quarter.
*/
export const monthsInQuarter = 3;
/**
* @constant
* @name monthsInYear
* @summary Months in 1 year.
*/
export const monthsInYear = 12;
/**
* @constant
* @name quartersInYear
* @summary Quarters in 1 year
*/
export const quartersInYear = 4;
/**
* @constant
* @name secondsInHour
* @summary Seconds in 1 hour.
*/
export const secondsInHour = 3600;
/**
* @constant
* @name secondsInMinute
* @summary Seconds in 1 minute.
*/
export const secondsInMinute = 60;
/**
* @constant
* @name secondsInDay
* @summary Seconds in 1 day.
*/
export const secondsInDay = secondsInHour * 24;
/**
* @constant
* @name secondsInWeek
* @summary Seconds in 1 week.
*/
export const secondsInWeek = secondsInDay * 7;
/**
* @constant
* @name secondsInYear
* @summary Seconds in 1 year.
*/
export const secondsInYear = secondsInDay * daysInYear;
/**
* @constant
* @name secondsInMonth
* @summary Seconds in 1 month
*/
export const secondsInMonth = secondsInYear / 12;
/**
* @constant
* @name secondsInQuarter
* @summary Seconds in 1 quarter.
*/
export const secondsInQuarter = secondsInMonth * 3;
/**
* @constant
* @name constructFromSymbol
* @summary Symbol enabling Date extensions to inherit properties from the reference date.
*
* The symbol is used to enable the `constructFrom` function to construct a date
* using a reference date and a value. It allows to transfer extra properties
* from the reference date to the new date. It's useful for extensions like
* [`TZDate`](https://github.com/date-fns/tz) that accept a time zone as
* a constructor argument.
*/
export const constructFromSymbol = Symbol.for("constructDateFrom");
+50
View File
@@ -0,0 +1,50 @@
import { constructFromSymbol } from "./constants.js";
/**
* @name constructFrom
* @category Generic Helpers
* @summary Constructs a date using the reference date and the value
*
* @description
* The function constructs a new date using the constructor from the reference
* date and the given value. It helps to build generic functions that accept
* date extensions.
*
* It defaults to `Date` if the passed reference date is a number or a string.
*
* Starting from v3.7.0, it allows to construct a date using `[Symbol.for("constructDateFrom")]`
* enabling to transfer extra properties from the reference date to the new date.
* It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
* that accept a time zone as a constructor argument.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
*
* @param date - The reference date to take constructor from
* @param value - The value to create the date
*
* @returns Date initialized using the given date and value
*
* @example
* import { constructFrom } from "./constructFrom/date-fns";
*
* // A function that clones a date preserving the original type
* function cloneDate<DateType extends Date>(date: DateType): DateType {
* return constructFrom(
* date, // Use constructor from the given date
* date.getTime() // Use the date value to create a new date
* );
* }
*/
export function constructFrom(date, value) {
if (typeof date === "function") return date(value);
if (date && typeof date === "object" && constructFromSymbol in date)
return date[constructFromSymbol](value);
if (date instanceof Date) return new date.constructor(value);
return new Date(value);
}
// Fallback for modularized imports:
export default constructFrom;
+36
View File
@@ -0,0 +1,36 @@
import { constructFrom } from "./constructFrom.js";
/**
* @name constructNow
* @category Generic Helpers
* @summary Constructs a new current date using the passed value constructor.
* @pure false
*
* @description
* The function constructs a new current date using the constructor from
* the reference date. It helps to build generic functions that accept date
* extensions and use the current date.
*
* It defaults to `Date` if the passed reference date is a number or a string.
*
* @param date - The reference date to take constructor from
*
* @returns Current date initialized using the given date constructor
*
* @example
* import { constructNow, isSameDay } from 'date-fns'
*
* function isToday<DateType extends Date>(
* date: DateArg<DateType>,
* ): boolean {
* // If we were to use `new Date()` directly, the function would behave
* // differently in different timezones and return false for the same date.
* return isSameDay(date, constructNow(date));
* }
*/
export function constructNow(date) {
return constructFrom(date, Date.now());
}
// Fallback for modularized imports:
export default constructNow;
+32
View File
@@ -0,0 +1,32 @@
import { daysInWeek } from "./constants.js";
/**
* @name daysToWeeks
* @category Conversion Helpers
* @summary Convert days to weeks.
*
* @description
* Convert a number of days to a full number of weeks.
*
* @param days - The number of days to be converted
*
* @returns The number of days converted in weeks
*
* @example
* // Convert 14 days to weeks:
* const result = daysToWeeks(14)
* //=> 2
*
* @example
* // It uses trunc rounding:
* const result = daysToWeeks(13)
* //=> 1
*/
export function daysToWeeks(days) {
const result = Math.trunc(days / daysInWeek);
// Prevent negative zero
return result === 0 ? 0 : result;
}
// Fallback for modularized imports:
export default daysToWeeks;
+90
View File
@@ -0,0 +1,90 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { addDays } from "./addDays.js";
import { differenceInCalendarDays } from "./differenceInCalendarDays.js";
import { isSameDay } from "./isSameDay.js";
import { isValid } from "./isValid.js";
import { isWeekend } from "./isWeekend.js";
/**
* The {@link differenceInBusinessDays} function options.
*/
/**
* @name differenceInBusinessDays
* @category Day Helpers
* @summary Get the number of business days between the given dates.
*
* @description
* Get the number of business day periods between the given dates.
* Business days being days that aren't in the weekend.
* Like `differenceInCalendarDays`, the function removes the times from
* the dates before calculating the difference.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of business days
*
* @example
* // How many business days are between
* // 10 January 2014 and 20 July 2014?
* const result = differenceInBusinessDays(
* new Date(2014, 6, 20),
* new Date(2014, 0, 10)
* )
* //=> 136
*
* // How many business days are between
* // 30 November 2021 and 1 November 2021?
* const result = differenceInBusinessDays(
* new Date(2021, 10, 30),
* new Date(2021, 10, 1)
* )
* //=> 21
*
* // How many business days are between
* // 1 November 2021 and 1 December 2021?
* const result = differenceInBusinessDays(
* new Date(2021, 10, 1),
* new Date(2021, 11, 1)
* )
* //=> -22
*
* // How many business days are between
* // 1 November 2021 and 1 November 2021 ?
* const result = differenceInBusinessDays(
* new Date(2021, 10, 1),
* new Date(2021, 10, 1)
* )
* //=> 0
*/
export function differenceInBusinessDays(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
if (!isValid(laterDate_) || !isValid(earlierDate_)) return NaN;
const diff = differenceInCalendarDays(laterDate_, earlierDate_);
const sign = diff < 0 ? -1 : 1;
const weeks = Math.trunc(diff / 7);
let result = weeks * 5;
let movingDate = addDays(earlierDate_, weeks * 7);
// the loop below will run at most 6 times to account for the remaining days that don't makeup a full week
while (!isSameDay(laterDate_, movingDate)) {
// sign is used to account for both negative and positive differences
result += isWeekend(movingDate, options) ? 0 : sign;
movingDate = addDays(movingDate, sign);
}
// Prevent negative zero
return result === 0 ? 0 : result;
}
// Fallback for modularized imports:
export default differenceInBusinessDays;
+63
View File
@@ -0,0 +1,63 @@
import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { millisecondsInDay } from "./constants.js";
import { startOfDay } from "./startOfDay.js";
/**
* The {@link differenceInCalendarDays} function options.
*/
/**
* @name differenceInCalendarDays
* @category Day Helpers
* @summary Get the number of calendar days between the given dates.
*
* @description
* Get the number of calendar days between the given dates. This means that the times are removed
* from the dates and then the difference in days is calculated.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - The options object
*
* @returns The number of calendar days
*
* @example
* // How many calendar days are between
* // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?
* const result = differenceInCalendarDays(
* new Date(2012, 6, 2, 0, 0),
* new Date(2011, 6, 2, 23, 0)
* )
* //=> 366
* // How many calendar days are between
* // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?
* const result = differenceInCalendarDays(
* new Date(2011, 6, 3, 0, 1),
* new Date(2011, 6, 2, 23, 59)
* )
* //=> 1
*/
export function differenceInCalendarDays(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const laterStartOfDay = startOfDay(laterDate_);
const earlierStartOfDay = startOfDay(earlierDate_);
const laterTimestamp =
+laterStartOfDay - getTimezoneOffsetInMilliseconds(laterStartOfDay);
const earlierTimestamp =
+earlierStartOfDay - getTimezoneOffsetInMilliseconds(earlierStartOfDay);
// Round the number of days to the nearest integer because the number of
// milliseconds in a day is not constant (e.g. it's different in the week of
// the daylight saving time clock shift).
return Math.round((laterTimestamp - earlierTimestamp) / millisecondsInDay);
}
// Fallback for modularized imports:
export default differenceInCalendarDays;
@@ -0,0 +1,48 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { getISOWeekYear } from "./getISOWeekYear.js";
/**
* The {@link differenceInCalendarISOWeekYears} function options.
*/
/**
* @name differenceInCalendarISOWeekYears
* @category ISO Week-Numbering Year Helpers
* @summary Get the number of calendar ISO week-numbering years between the given dates.
*
* @description
* Get the number of calendar ISO week-numbering years between the given dates.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of calendar ISO week-numbering years
*
* @example
* // How many calendar ISO week-numbering years are 1 January 2010 and 1 January 2012?
* const result = differenceInCalendarISOWeekYears(
* new Date(2012, 0, 1),
* new Date(2010, 0, 1)
* )
* //=> 2
*/
export function differenceInCalendarISOWeekYears(
laterDate,
earlierDate,
options,
) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
return (
getISOWeekYear(laterDate_, options) - getISOWeekYear(earlierDate_, options)
);
}
// Fallback for modularized imports:
export default differenceInCalendarISOWeekYears;
+56
View File
@@ -0,0 +1,56 @@
import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { millisecondsInWeek } from "./constants.js";
import { startOfISOWeek } from "./startOfISOWeek.js";
/**
* The {@link differenceInCalendarISOWeeks} function options.
*/
/**
* @name differenceInCalendarISOWeeks
* @category ISO Week Helpers
* @summary Get the number of calendar ISO weeks between the given dates.
*
* @description
* Get the number of calendar ISO weeks between the given dates.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of calendar ISO weeks
*
* @example
* // How many calendar ISO weeks are between 6 July 2014 and 21 July 2014?
* const result = differenceInCalendarISOWeeks(
* new Date(2014, 6, 21),
* new Date(2014, 6, 6),
* );
* //=> 3
*/
export function differenceInCalendarISOWeeks(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const startOfISOWeekLeft = startOfISOWeek(laterDate_);
const startOfISOWeekRight = startOfISOWeek(earlierDate_);
const timestampLeft =
+startOfISOWeekLeft - getTimezoneOffsetInMilliseconds(startOfISOWeekLeft);
const timestampRight =
+startOfISOWeekRight - getTimezoneOffsetInMilliseconds(startOfISOWeekRight);
// Round the number of weeks to the nearest integer because the number of
// milliseconds in a week is not constant (e.g. it's different in the week of
// the daylight saving time clock shift).
return Math.round((timestampLeft - timestampRight) / millisecondsInWeek);
}
// Fallback for modularized imports:
export default differenceInCalendarISOWeeks;
+43
View File
@@ -0,0 +1,43 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
/**
* The {@link differenceInCalendarMonths} function options.
*/
/**
* @name differenceInCalendarMonths
* @category Month Helpers
* @summary Get the number of calendar months between the given dates.
*
* @description
* Get the number of calendar months between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of calendar months
*
* @example
* // How many calendar months are between 31 January 2014 and 1 September 2014?
* const result = differenceInCalendarMonths(
* new Date(2014, 8, 1),
* new Date(2014, 0, 31)
* )
* //=> 8
*/
export function differenceInCalendarMonths(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const yearsDiff = laterDate_.getFullYear() - earlierDate_.getFullYear();
const monthsDiff = laterDate_.getMonth() - earlierDate_.getMonth();
return yearsDiff * 12 + monthsDiff;
}
// Fallback for modularized imports:
export default differenceInCalendarMonths;
+44
View File
@@ -0,0 +1,44 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { getQuarter } from "./getQuarter.js";
/**
* The {@link differenceInCalendarQuarters} function options.
*/
/**
* @name differenceInCalendarQuarters
* @category Quarter Helpers
* @summary Get the number of calendar quarters between the given dates.
*
* @description
* Get the number of calendar quarters between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of calendar quarters
*
* @example
* // How many calendar quarters are between 31 December 2013 and 2 July 2014?
* const result = differenceInCalendarQuarters(
* new Date(2014, 6, 2),
* new Date(2013, 11, 31)
* )
* //=> 3
*/
export function differenceInCalendarQuarters(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const yearsDiff = laterDate_.getFullYear() - earlierDate_.getFullYear();
const quartersDiff = getQuarter(laterDate_) - getQuarter(earlierDate_);
return yearsDiff * 4 + quartersDiff;
}
// Fallback for modularized imports:
export default differenceInCalendarQuarters;
+61
View File
@@ -0,0 +1,61 @@
import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { millisecondsInWeek } from "./constants.js";
import { startOfWeek } from "./startOfWeek.js";
/**
* The {@link differenceInCalendarWeeks} function options.
*/
/**
* @name differenceInCalendarWeeks
* @category Week Helpers
* @summary Get the number of calendar weeks between the given dates.
*
* @description
* Get the number of calendar weeks between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options.
*
* @returns The number of calendar weeks
*
* @example
* // How many calendar weeks are between 5 July 2014 and 20 July 2014?
* const result = differenceInCalendarWeeks(
* new Date(2014, 6, 20),
* new Date(2014, 6, 5)
* )
* //=> 3
*
* @example
* // If the week starts on Monday,
* // how many calendar weeks are between 5 July 2014 and 20 July 2014?
* const result = differenceInCalendarWeeks(
* new Date(2014, 6, 20),
* new Date(2014, 6, 5),
* { weekStartsOn: 1 }
* )
* //=> 2
*/
export function differenceInCalendarWeeks(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const laterStartOfWeek = startOfWeek(laterDate_, options);
const earlierStartOfWeek = startOfWeek(earlierDate_, options);
const laterTimestamp =
+laterStartOfWeek - getTimezoneOffsetInMilliseconds(laterStartOfWeek);
const earlierTimestamp =
+earlierStartOfWeek - getTimezoneOffsetInMilliseconds(earlierStartOfWeek);
return Math.round((laterTimestamp - earlierTimestamp) / millisecondsInWeek);
}
// Fallback for modularized imports:
export default differenceInCalendarWeeks;
+39
View File
@@ -0,0 +1,39 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
/**
* The {@link differenceInCalendarYears} function options.
*/
/**
* @name differenceInCalendarYears
* @category Year Helpers
* @summary Get the number of calendar years between the given dates.
*
* @description
* Get the number of calendar years between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
* @returns The number of calendar years
*
* @example
* // How many calendar years are between 31 December 2013 and 11 February 2015?
* const result = differenceInCalendarYears(
* new Date(2015, 1, 11),
* new Date(2013, 11, 31)
* );
* //=> 2
*/
export function differenceInCalendarYears(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
return laterDate_.getFullYear() - earlierDate_.getFullYear();
}
// Fallback for modularized imports:
export default differenceInCalendarYears;
+108
View File
@@ -0,0 +1,108 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { differenceInCalendarDays } from "./differenceInCalendarDays.js";
/**
* The {@link differenceInDays} function options.
*/
/**
* @name differenceInDays
* @category Day Helpers
* @summary Get the number of full days between the given dates.
*
* @description
* Get the number of full day periods between two dates. Fractional days are
* truncated towards zero.
*
* One "full day" is the distance between a local time in one day to the same
* local time on the next or previous day. A full day can sometimes be less than
* or more than 24 hours if a daylight savings change happens between two dates.
*
* To ignore DST and only measure exact 24-hour periods, use this instead:
* `Math.trunc(differenceInHours(dateLeft, dateRight)/24)|0`.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of full days according to the local timezone
*
* @example
* // How many full days are between
* // 2 July 2011 23:00:00 and 2 July 2012 00:00:00?
* const result = differenceInDays(
* new Date(2012, 6, 2, 0, 0),
* new Date(2011, 6, 2, 23, 0)
* )
* //=> 365
*
* @example
* // How many full days are between
* // 2 July 2011 23:59:00 and 3 July 2011 00:01:00?
* const result = differenceInDays(
* new Date(2011, 6, 3, 0, 1),
* new Date(2011, 6, 2, 23, 59)
* )
* //=> 0
*
* @example
* // How many full days are between
* // 1 March 2020 0:00 and 1 June 2020 0:00 ?
* // Note: because local time is used, the
* // result will always be 92 days, even in
* // time zones where DST starts and the
* // period has only 92*24-1 hours.
* const result = differenceInDays(
* new Date(2020, 5, 1),
* new Date(2020, 2, 1)
* )
* //=> 92
*/
export function differenceInDays(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const sign = compareLocalAsc(laterDate_, earlierDate_);
const difference = Math.abs(
differenceInCalendarDays(laterDate_, earlierDate_),
);
laterDate_.setDate(laterDate_.getDate() - sign * difference);
// Math.abs(diff in full days - diff in calendar days) === 1 if last calendar day is not full
// If so, result must be decreased by 1 in absolute value
const isLastDayNotFull = Number(
compareLocalAsc(laterDate_, earlierDate_) === -sign,
);
const result = sign * (difference - isLastDayNotFull);
// Prevent negative zero
return result === 0 ? 0 : result;
}
// Like `compareAsc` but uses local time not UTC, which is needed
// for accurate equality comparisons of UTC timestamps that end up
// having the same representation in local time, e.g. one hour before
// DST ends vs. the instant that DST ends.
function compareLocalAsc(laterDate, earlierDate) {
const diff =
laterDate.getFullYear() - earlierDate.getFullYear() ||
laterDate.getMonth() - earlierDate.getMonth() ||
laterDate.getDate() - earlierDate.getDate() ||
laterDate.getHours() - earlierDate.getHours() ||
laterDate.getMinutes() - earlierDate.getMinutes() ||
laterDate.getSeconds() - earlierDate.getSeconds() ||
laterDate.getMilliseconds() - earlierDate.getMilliseconds();
if (diff < 0) return -1;
if (diff > 0) return 1;
// Return 0 if diff is 0; return NaN if diff is NaN
return diff;
}
// Fallback for modularized imports:
export default differenceInDays;
+42
View File
@@ -0,0 +1,42 @@
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { millisecondsInHour } from "./constants.js";
/**
* The {@link differenceInHours} function options.
*/
/**
* @name differenceInHours
* @category Hour Helpers
* @summary Get the number of hours between the given dates.
*
* @description
* Get the number of hours between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options.
*
* @returns The number of hours
*
* @example
* // How many hours are between 2 July 2014 06:50:00 and 2 July 2014 19:00:00?
* const result = differenceInHours(
* new Date(2014, 6, 2, 19, 0),
* new Date(2014, 6, 2, 6, 50)
* )
* //=> 12
*/
export function differenceInHours(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const diff = (+laterDate_ - +earlierDate_) / millisecondsInHour;
return getRoundingMethod(options?.roundingMethod)(diff);
}
// Fallback for modularized imports:
export default differenceInHours;
+58
View File
@@ -0,0 +1,58 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { compareAsc } from "./compareAsc.js";
import { differenceInCalendarISOWeekYears } from "./differenceInCalendarISOWeekYears.js";
import { subISOWeekYears } from "./subISOWeekYears.js";
/**
* The {@link differenceInISOWeekYears} function options.
*/
/**
* @name differenceInISOWeekYears
* @category ISO Week-Numbering Year Helpers
* @summary Get the number of full ISO week-numbering years between the given dates.
*
* @description
* Get the number of full ISO week-numbering years between the given dates.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - The options
*
* @returns The number of full ISO week-numbering years
*
* @example
* // How many full ISO week-numbering years are between 1 January 2010 and 1 January 2012?
* const result = differenceInISOWeekYears(
* new Date(2012, 0, 1),
* new Date(2010, 0, 1)
* )
* // => 1
*/
export function differenceInISOWeekYears(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
const sign = compareAsc(laterDate_, earlierDate_);
const diff = Math.abs(
differenceInCalendarISOWeekYears(laterDate_, earlierDate_, options),
);
const adjustedDate = subISOWeekYears(laterDate_, sign * diff, options);
const isLastISOWeekYearNotFull = Number(
compareAsc(adjustedDate, earlierDate_) === -sign,
);
const result = sign * (diff - isLastISOWeekYearNotFull);
// Prevent negative zero
return result === 0 ? 0 : result;
}
// Fallback for modularized imports:
export default differenceInISOWeekYears;
+30
View File
@@ -0,0 +1,30 @@
import { toDate } from "./toDate.js";
/**
* @name differenceInMilliseconds
* @category Millisecond Helpers
* @summary Get the number of milliseconds between the given dates.
*
* @description
* Get the number of milliseconds between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
*
* @returns The number of milliseconds
*
* @example
* // How many milliseconds are between
* // 2 July 2014 12:30:20.600 and 2 July 2014 12:30:21.700?
* const result = differenceInMilliseconds(
* new Date(2014, 6, 2, 12, 30, 21, 700),
* new Date(2014, 6, 2, 12, 30, 20, 600)
* )
* //=> 1100
*/
export function differenceInMilliseconds(laterDate, earlierDate) {
return +toDate(laterDate) - +toDate(earlierDate);
}
// Fallback for modularized imports:
export default differenceInMilliseconds;
+46
View File
@@ -0,0 +1,46 @@
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { millisecondsInMinute } from "./constants.js";
import { differenceInMilliseconds } from "./differenceInMilliseconds.js";
/**
* The {@link differenceInMinutes} function options.
*/
/**
* @name differenceInMinutes
* @category Minute Helpers
* @summary Get the number of minutes between the given dates.
*
* @description
* Get the signed number of full (rounded towards 0) minutes between the given dates.
*
* @param dateLeft - The later date
* @param dateRight - The earlier date
* @param options - An object with options.
*
* @returns The number of minutes
*
* @example
* // How many minutes are between 2 July 2014 12:07:59 and 2 July 2014 12:20:00?
* const result = differenceInMinutes(
* new Date(2014, 6, 2, 12, 20, 0),
* new Date(2014, 6, 2, 12, 7, 59)
* )
* //=> 12
*
* @example
* // How many minutes are between 10:01:59 and 10:00:00
* const result = differenceInMinutes(
* new Date(2000, 0, 1, 10, 0, 0),
* new Date(2000, 0, 1, 10, 1, 59)
* )
* //=> -1
*/
export function differenceInMinutes(dateLeft, dateRight, options) {
const diff =
differenceInMilliseconds(dateLeft, dateRight) / millisecondsInMinute;
return getRoundingMethod(options?.roundingMethod)(diff);
}
// Fallback for modularized imports:
export default differenceInMinutes;
+61
View File
@@ -0,0 +1,61 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { compareAsc } from "./compareAsc.js";
import { differenceInCalendarMonths } from "./differenceInCalendarMonths.js";
import { isLastDayOfMonth } from "./isLastDayOfMonth.js";
/**
* The {@link differenceInMonths} function options.
*/
/**
* @name differenceInMonths
* @category Month Helpers
* @summary Get the number of full months between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of full months
*
* @example
* // How many full months are between 31 January 2014 and 1 September 2014?
* const result = differenceInMonths(new Date(2014, 8, 1), new Date(2014, 0, 31))
* //=> 7
*/
export function differenceInMonths(laterDate, earlierDate, options) {
const [laterDate_, workingLaterDate, earlierDate_] = normalizeDates(
options?.in,
laterDate,
laterDate,
earlierDate,
);
const sign = compareAsc(workingLaterDate, earlierDate_);
const difference = Math.abs(
differenceInCalendarMonths(workingLaterDate, earlierDate_),
);
if (difference < 1) return 0;
if (workingLaterDate.getMonth() === 1 && workingLaterDate.getDate() > 27)
workingLaterDate.setDate(30);
workingLaterDate.setMonth(workingLaterDate.getMonth() - sign * difference);
let isLastMonthNotFull = compareAsc(workingLaterDate, earlierDate_) === -sign;
if (
isLastDayOfMonth(laterDate_) &&
difference === 1 &&
compareAsc(laterDate_, earlierDate_) === 1
) {
isLastMonthNotFull = false;
}
const result = sign * (difference - +isLastMonthNotFull);
return result === 0 ? 0 : result;
}
// Fallback for modularized imports:
export default differenceInMonths;
+33
View File
@@ -0,0 +1,33 @@
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { differenceInMonths } from "./differenceInMonths.js";
/**
* The {@link differenceInQuarters} function options.
*/
/**
* @name differenceInQuarters
* @category Quarter Helpers
* @summary Get the number of quarters between the given dates.
*
* @description
* Get the number of quarters between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options.
*
* @returns The number of full quarters
*
* @example
* // How many full quarters are between 31 December 2013 and 2 July 2014?
* const result = differenceInQuarters(new Date(2014, 6, 2), new Date(2013, 11, 31))
* //=> 2
*/
export function differenceInQuarters(laterDate, earlierDate, options) {
const diff = differenceInMonths(laterDate, earlierDate, options) / 3;
return getRoundingMethod(options?.roundingMethod)(diff);
}
// Fallback for modularized imports:
export default differenceInQuarters;
+37
View File
@@ -0,0 +1,37 @@
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { differenceInMilliseconds } from "./differenceInMilliseconds.js";
/**
* The {@link differenceInSeconds} function options.
*/
/**
* @name differenceInSeconds
* @category Second Helpers
* @summary Get the number of seconds between the given dates.
*
* @description
* Get the number of seconds between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options.
*
* @returns The number of seconds
*
* @example
* // How many seconds are between
* // 2 July 2014 12:30:07.999 and 2 July 2014 12:30:20.000?
* const result = differenceInSeconds(
* new Date(2014, 6, 2, 12, 30, 20, 0),
* new Date(2014, 6, 2, 12, 30, 7, 999)
* )
* //=> 12
*/
export function differenceInSeconds(laterDate, earlierDate, options) {
const diff = differenceInMilliseconds(laterDate, earlierDate) / 1000;
return getRoundingMethod(options?.roundingMethod)(diff);
}
// Fallback for modularized imports:
export default differenceInSeconds;
+54
View File
@@ -0,0 +1,54 @@
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { differenceInDays } from "./differenceInDays.js";
/**
* The {@link differenceInWeeks} function options.
*/
/**
* @name differenceInWeeks
* @category Week Helpers
* @summary Get the number of full weeks between the given dates.
*
* @description
* Get the number of full weeks between two dates. Fractional weeks are
* truncated towards zero by default.
*
* One "full week" is the distance between a local time in one day to the same
* local time 7 days earlier or later. A full week can sometimes be less than
* or more than 7*24 hours if a daylight savings change happens between two dates.
*
* To ignore DST and only measure exact 7*24-hour periods, use this instead:
* `Math.trunc(differenceInHours(dateLeft, dateRight)/(7*24))|0`.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of full weeks
*
* @example
* // How many full weeks are between 5 July 2014 and 20 July 2014?
* const result = differenceInWeeks(new Date(2014, 6, 20), new Date(2014, 6, 5))
* //=> 2
*
* @example
* // How many full weeks are between
* // 1 March 2020 0:00 and 6 June 2020 0:00 ?
* // Note: because local time is used, the
* // result will always be 8 weeks (54 days),
* // even if DST starts and the period has
* // only 54*24-1 hours.
* const result = differenceInWeeks(
* new Date(2020, 5, 1),
* new Date(2020, 2, 6)
* )
* //=> 8
*/
export function differenceInWeeks(laterDate, earlierDate, options) {
const diff = differenceInDays(laterDate, earlierDate, options) / 7;
return getRoundingMethod(options?.roundingMethod)(diff);
}
// Fallback for modularized imports:
export default differenceInWeeks;
+63
View File
@@ -0,0 +1,63 @@
import { normalizeDates } from "./_lib/normalizeDates.js";
import { compareAsc } from "./compareAsc.js";
import { differenceInCalendarYears } from "./differenceInCalendarYears.js";
/**
* The {@link differenceInYears} function options.
*/
/**
* @name differenceInYears
* @category Year Helpers
* @summary Get the number of full years between the given dates.
*
* @description
* Get the number of full years between the given dates.
*
* @param laterDate - The later date
* @param earlierDate - The earlier date
* @param options - An object with options
*
* @returns The number of full years
*
* @example
* // How many full years are between 31 December 2013 and 11 February 2015?
* const result = differenceInYears(new Date(2015, 1, 11), new Date(2013, 11, 31))
* //=> 1
*/
export function differenceInYears(laterDate, earlierDate, options) {
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
laterDate,
earlierDate,
);
// -1 if the left date is earlier than the right date
// 2023-12-31 - 2024-01-01 = -1
const sign = compareAsc(laterDate_, earlierDate_);
// First calculate the difference in calendar years
// 2024-01-01 - 2023-12-31 = 1 year
const diff = Math.abs(differenceInCalendarYears(laterDate_, earlierDate_));
// Now we need to calculate if the difference is full. To do that we set
// both dates to the same year and check if the both date's month and day
// form a full year.
laterDate_.setFullYear(1584);
earlierDate_.setFullYear(1584);
// For it to be true, when the later date is indeed later than the earlier date
// (2026-02-01 - 2023-12-10 = 3 years), the difference is full if
// the normalized later date is also later than the normalized earlier date.
// In our example, 1584-02-01 is earlier than 1584-12-10, so the difference
// is partial, hence we need to subtract 1 from the difference 3 - 1 = 2.
const partial = compareAsc(laterDate_, earlierDate_) === -sign;
const result = sign * (diff - +partial);
// Prevent negative zero
return result === 0 ? 0 : result;
}
// Fallback for modularized imports:
export default differenceInYears;
+72
View File
@@ -0,0 +1,72 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link eachDayOfInterval} function options.
*/
/**
* The {@link eachDayOfInterval} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name eachDayOfInterval
* @category Interval Helpers
* @summary Return the array of dates within the specified time interval.
*
* @description
* Return the array of dates within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of days from the day of the interval start to the day of the interval end
*
* @example
* // Each day between 6 October 2014 and 10 October 2014:
* const result = eachDayOfInterval({
* start: new Date(2014, 9, 6),
* end: new Date(2014, 9, 10)
* })
* //=> [
* // Mon Oct 06 2014 00:00:00,
* // Tue Oct 07 2014 00:00:00,
* // Wed Oct 08 2014 00:00:00,
* // Thu Oct 09 2014 00:00:00,
* // Fri Oct 10 2014 00:00:00
* // ]
*/
export function eachDayOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const endTime = reversed ? +start : +end;
const date = reversed ? end : start;
date.setHours(0, 0, 0, 0);
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date.setDate(date.getDate() + step);
date.setHours(0, 0, 0, 0);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachDayOfInterval;
+68
View File
@@ -0,0 +1,68 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link eachHourOfInterval} function options.
*/
/**
* The {@link eachHourOfInterval} function result type.
* Resolves to the appropriate date type based on inputs.
*/
/**
* @name eachHourOfInterval
* @category Interval Helpers
* @summary Return the array of hours within the specified time interval.
*
* @description
* Return the array of hours within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of hours from the hour of the interval start to the hour of the interval end
*
* @example
* // Each hour between 6 October 2014, 12:00 and 6 October 2014, 15:00
* const result = eachHourOfInterval({
* start: new Date(2014, 9, 6, 12),
* end: new Date(2014, 9, 6, 15)
* });
* //=> [
* // Mon Oct 06 2014 12:00:00,
* // Mon Oct 06 2014 13:00:00,
* // Mon Oct 06 2014 14:00:00,
* // Mon Oct 06 2014 15:00:00
* // ]
*/
export function eachHourOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const endTime = reversed ? +start : +end;
const date = reversed ? end : start;
date.setMinutes(0, 0, 0);
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date.setHours(date.getHours() + step);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachHourOfInterval;
+72
View File
@@ -0,0 +1,72 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { addMinutes } from "./addMinutes.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link eachMinuteOfInterval} function options.
*/
/**
* The {@link eachMinuteOfInterval} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name eachMinuteOfInterval
* @category Interval Helpers
* @summary Return the array of minutes within the specified time interval.
*
* @description
* Returns the array of minutes within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of minutes from the minute of the interval start to the minute of the interval end
*
* @example
* // Each minute between 14 October 2020, 13:00 and 14 October 2020, 13:03
* const result = eachMinuteOfInterval({
* start: new Date(2014, 9, 14, 13),
* end: new Date(2014, 9, 14, 13, 3)
* })
* //=> [
* // Wed Oct 14 2014 13:00:00,
* // Wed Oct 14 2014 13:01:00,
* // Wed Oct 14 2014 13:02:00,
* // Wed Oct 14 2014 13:03:00
* // ]
*/
export function eachMinuteOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
// Set to the start of the minute
start.setSeconds(0, 0);
let reversed = +start > +end;
const endTime = reversed ? +start : +end;
let date = reversed ? end : start;
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date = addMinutes(date, step);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachMinuteOfInterval;
+71
View File
@@ -0,0 +1,71 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link eachMonthOfInterval} function options.
*/
/**
* The {@link eachMonthOfInterval} function result type. It resolves the proper data type.
*/
/**
* @name eachMonthOfInterval
* @category Interval Helpers
* @summary Return the array of months within the specified time interval.
*
* @description
* Return the array of months within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of months from the month of the interval start to the month of the interval end
*
* @example
* // Each month between 6 February 2014 and 10 August 2014:
* const result = eachMonthOfInterval({
* start: new Date(2014, 1, 6),
* end: new Date(2014, 7, 10)
* })
* //=> [
* // Sat Feb 01 2014 00:00:00,
* // Sat Mar 01 2014 00:00:00,
* // Tue Apr 01 2014 00:00:00,
* // Thu May 01 2014 00:00:00,
* // Sun Jun 01 2014 00:00:00,
* // Tue Jul 01 2014 00:00:00,
* // Fri Aug 01 2014 00:00:00
* // ]
*/
export function eachMonthOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const endTime = reversed ? +start : +end;
const date = reversed ? end : start;
date.setHours(0, 0, 0, 0);
date.setDate(1);
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date.setMonth(date.getMonth() + step);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachMonthOfInterval;
+70
View File
@@ -0,0 +1,70 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { addQuarters } from "./addQuarters.js";
import { constructFrom } from "./constructFrom.js";
import { startOfQuarter } from "./startOfQuarter.js";
/**
* The {@link eachQuarterOfInterval} function options.
*/
/**
* The {@link eachQuarterOfInterval} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name eachQuarterOfInterval
* @category Interval Helpers
* @summary Return the array of quarters within the specified time interval.
*
* @description
* Return the array of quarters within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval
* @param options - An object with options
*
* @returns The array with starts of quarters from the quarter of the interval start to the quarter of the interval end
*
* @example
* // Each quarter within interval 6 February 2014 - 10 August 2014:
* const result = eachQuarterOfInterval({
* start: new Date(2014, 1, 6),
* end: new Date(2014, 7, 10),
* })
* //=> [
* // Wed Jan 01 2014 00:00:00,
* // Tue Apr 01 2014 00:00:00,
* // Tue Jul 01 2014 00:00:00,
* // ]
*/
export function eachQuarterOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const endTime = reversed ? +startOfQuarter(start) : +startOfQuarter(end);
let date = reversed ? startOfQuarter(end) : startOfQuarter(start);
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date = addQuarters(date, step);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachQuarterOfInterval;
+83
View File
@@ -0,0 +1,83 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { addWeeks } from "./addWeeks.js";
import { constructFrom } from "./constructFrom.js";
import { startOfWeek } from "./startOfWeek.js";
/**
* The {@link eachWeekOfInterval} function options.
*/
/**
* The {@link eachWeekOfInterval} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the interval start date,
* then the end interval date. If a context function is passed, it uses the context function return type.
*/
/**
* @name eachWeekOfInterval
* @category Interval Helpers
* @summary Return the array of weeks within the specified time interval.
*
* @description
* Return the array of weeks within the specified time interval.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of weeks from the week of the interval start to the week of the interval end
*
* @example
* // Each week within interval 6 October 2014 - 23 November 2014:
* const result = eachWeekOfInterval({
* start: new Date(2014, 9, 6),
* end: new Date(2014, 10, 23)
* })
* //=> [
* // Sun Oct 05 2014 00:00:00,
* // Sun Oct 12 2014 00:00:00,
* // Sun Oct 19 2014 00:00:00,
* // Sun Oct 26 2014 00:00:00,
* // Sun Nov 02 2014 00:00:00,
* // Sun Nov 09 2014 00:00:00,
* // Sun Nov 16 2014 00:00:00,
* // Sun Nov 23 2014 00:00:00
* // ]
*/
export function eachWeekOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const startDateWeek = reversed
? startOfWeek(end, options)
: startOfWeek(start, options);
const endDateWeek = reversed
? startOfWeek(start, options)
: startOfWeek(end, options);
startDateWeek.setHours(15);
endDateWeek.setHours(15);
const endTime = +endDateWeek.getTime();
let currentDate = startDateWeek;
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+currentDate <= endTime) {
currentDate.setHours(0);
dates.push(constructFrom(start, currentDate));
currentDate = addWeeks(currentDate, step);
currentDate.setHours(15);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachWeekOfInterval;
+56
View File
@@ -0,0 +1,56 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { constructFrom } from "./constructFrom.js";
import { eachDayOfInterval } from "./eachDayOfInterval.js";
import { isWeekend } from "./isWeekend.js";
/**
* The {@link eachWeekendOfInterval} function options.
*/
/**
* The {@link eachWeekendOfInterval} function result type.
*/
/**
* @name eachWeekendOfInterval
* @category Interval Helpers
* @summary List all the Saturdays and Sundays in the given date interval.
*
* @description
* Get all the Saturdays and Sundays in the given date interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The given interval
* @param options - An object with options
*
* @returns An array containing all the Saturdays and Sundays
*
* @example
* // Lists all Saturdays and Sundays in the given date interval
* const result = eachWeekendOfInterval({
* start: new Date(2018, 8, 17),
* end: new Date(2018, 8, 30)
* })
* //=> [
* // Sat Sep 22 2018 00:00:00,
* // Sun Sep 23 2018 00:00:00,
* // Sat Sep 29 2018 00:00:00,
* // Sun Sep 30 2018 00:00:00
* // ]
*/
export function eachWeekendOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
const dateInterval = eachDayOfInterval({ start, end }, options);
const weekends = [];
let index = 0;
while (index < dateInterval.length) {
const date = dateInterval[index++];
if (isWeekend(date)) weekends.push(constructFrom(start, date));
}
return weekends;
}
// Fallback for modularized imports:
export default eachWeekendOfInterval;
+46
View File
@@ -0,0 +1,46 @@
import { eachWeekendOfInterval } from "./eachWeekendOfInterval.js";
import { endOfMonth } from "./endOfMonth.js";
import { startOfMonth } from "./startOfMonth.js";
/**
* The {@link eachWeekendOfMonth} function options.
*/
/**
* @name eachWeekendOfMonth
* @category Month Helpers
* @summary List all the Saturdays and Sundays in the given month.
*
* @description
* Get all the Saturdays and Sundays in the given month.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The given month
* @param options - An object with options
*
* @returns An array containing all the Saturdays and Sundays
*
* @example
* // Lists all Saturdays and Sundays in the given month
* const result = eachWeekendOfMonth(new Date(2022, 1, 1))
* //=> [
* // Sat Feb 05 2022 00:00:00,
* // Sun Feb 06 2022 00:00:00,
* // Sat Feb 12 2022 00:00:00,
* // Sun Feb 13 2022 00:00:00,
* // Sat Feb 19 2022 00:00:00,
* // Sun Feb 20 2022 00:00:00,
* // Sat Feb 26 2022 00:00:00,
* // Sun Feb 27 2022 00:00:00
* // ]
*/
export function eachWeekendOfMonth(date, options) {
const start = startOfMonth(date, options);
const end = endOfMonth(date, options);
return eachWeekendOfInterval({ start, end }, options);
}
// Fallback for modularized imports:
export default eachWeekendOfMonth;
+43
View File
@@ -0,0 +1,43 @@
import { eachWeekendOfInterval } from "./eachWeekendOfInterval.js";
import { endOfYear } from "./endOfYear.js";
import { startOfYear } from "./startOfYear.js";
/**
* The {@link eachWeekendOfYear} function options.
*/
/**
* @name eachWeekendOfYear
* @category Year Helpers
* @summary List all the Saturdays and Sundays in the year.
*
* @description
* Get all the Saturdays and Sundays in the year.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The given year
* @param options - An object with options
*
* @returns An array containing all the Saturdays and Sundays
*
* @example
* // Lists all Saturdays and Sundays in the year
* const result = eachWeekendOfYear(new Date(2020, 1, 1))
* //=> [
* // Sat Jan 03 2020 00:00:00,
* // Sun Jan 04 2020 00:00:00,
* // ...
* // Sun Dec 27 2020 00:00:00
* // ]
* ]
*/
export function eachWeekendOfYear(date, options) {
const start = startOfYear(date, options);
const end = endOfYear(date, options);
return eachWeekendOfInterval({ start, end }, options);
}
// Fallback for modularized imports:
export default eachWeekendOfYear;
+71
View File
@@ -0,0 +1,71 @@
import { normalizeInterval } from "./_lib/normalizeInterval.js";
import { constructFrom } from "./constructFrom.js";
/**
* The {@link eachYearOfInterval} function options.
*/
/**
* The {@link eachYearOfInterval} function result type. It resolves the proper data type.
* It uses the first argument date object type, starting from the date argument,
* then the start interval date, and finally the end interval date. If
* a context function is passed, it uses the context function return type.
*/
/**
* @name eachYearOfInterval
* @category Interval Helpers
* @summary Return the array of yearly timestamps within the specified time interval.
*
* @description
* Return the array of yearly timestamps within the specified time interval.
*
* @typeParam IntervalType - Interval type.
* @typeParam Options - Options type.
*
* @param interval - The interval.
* @param options - An object with options.
*
* @returns The array with starts of yearly timestamps from the month of the interval start to the month of the interval end
*
* @example
* // Each year between 6 February 2014 and 10 August 2017:
* const result = eachYearOfInterval({
* start: new Date(2014, 1, 6),
* end: new Date(2017, 7, 10)
* })
* //=> [
* // Wed Jan 01 2014 00:00:00,
* // Thu Jan 01 2015 00:00:00,
* // Fri Jan 01 2016 00:00:00,
* // Sun Jan 01 2017 00:00:00
* // ]
*/
export function eachYearOfInterval(interval, options) {
const { start, end } = normalizeInterval(options?.in, interval);
let reversed = +start > +end;
const endTime = reversed ? +start : +end;
const date = reversed ? end : start;
date.setHours(0, 0, 0, 0);
date.setMonth(0, 1);
let step = options?.step ?? 1;
if (!step) return [];
if (step < 0) {
step = -step;
reversed = !reversed;
}
const dates = [];
while (+date <= endTime) {
dates.push(constructFrom(start, date));
date.setFullYear(date.getFullYear() + step);
}
return reversed ? dates.reverse() : dates;
}
// Fallback for modularized imports:
export default eachYearOfInterval;
+36
View File
@@ -0,0 +1,36 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfDay} function options.
*/
/**
* @name endOfDay
* @category Day Helpers
* @summary Return the end of a day for the given date.
*
* @description
* Return the end of a day for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a day
*
* @example
* // The end of a day for 2 September 2014 11:55:00:
* const result = endOfDay(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 02 2014 23:59:59.999
*/
export function endOfDay(date, options) {
const _date = toDate(date, options?.in);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfDay;
+41
View File
@@ -0,0 +1,41 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfDecade} function options.
*/
/**
* @name endOfDecade
* @category Decade Helpers
* @summary Return the end of a decade for the given date.
*
* @description
* Return the end of a decade for the given date.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a decade
*
* @example
* // The end of a decade for 12 May 1984 00:00:00:
* const result = endOfDecade(new Date(1984, 4, 12, 00, 00, 00))
* //=> Dec 31 1989 23:59:59.999
*/
export function endOfDecade(date, options) {
// TODO: Switch to more technical definition in of decades that start with 1
// end with 0. I.e. 2001-2010 instead of current 2000-2009. It's a breaking
// change, so it can only be done in 4.0.
const _date = toDate(date, options?.in);
const year = _date.getFullYear();
const decade = 9 + Math.floor(year / 10) * 10;
_date.setFullYear(decade, 11, 31);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfDecade;
+36
View File
@@ -0,0 +1,36 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfHour} function options.
*/
/**
* @name endOfHour
* @category Hour Helpers
* @summary Return the end of an hour for the given date.
*
* @description
* Return the end of an hour for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of an hour
*
* @example
* // The end of an hour for 2 September 2014 11:55:00:
* const result = endOfHour(new Date(2014, 8, 2, 11, 55))
* //=> Tue Sep 02 2014 11:59:59.999
*/
export function endOfHour(date, options) {
const _date = toDate(date, options?.in);
_date.setMinutes(59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfHour;
+36
View File
@@ -0,0 +1,36 @@
import { endOfWeek } from "./endOfWeek.js";
/**
* The {@link endOfISOWeek} function options.
*/
/**
* @name endOfISOWeek
* @category ISO Week Helpers
* @summary Return the end of an ISO week for the given date.
*
* @description
* Return the end of an ISO week for the given date.
* The result will be in the local timezone.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of an ISO week
*
* @example
* // The end of an ISO week for 2 September 2014 11:55:00:
* const result = endOfISOWeek(new Date(2014, 8, 2, 11, 55, 0))
* //=> Sun Sep 07 2014 23:59:59.999
*/
export function endOfISOWeek(date, options) {
return endOfWeek(date, { ...options, weekStartsOn: 1 });
}
// Fallback for modularized imports:
export default endOfISOWeek;
+45
View File
@@ -0,0 +1,45 @@
import { constructFrom } from "./constructFrom.js";
import { getISOWeekYear } from "./getISOWeekYear.js";
import { startOfISOWeek } from "./startOfISOWeek.js";
/**
* The {@link endOfISOWeekYear} function options.
*/
/**
* @name endOfISOWeekYear
* @category ISO Week-Numbering Year Helpers
* @summary Return the end of an ISO week-numbering year for the given date.
*
* @description
* Return the end of an ISO week-numbering year,
* which always starts 3 days before the year's first Thursday.
* The result will be in the local timezone.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ContextDate - The `Date` type of the context function.
*
* @param date - The original date
* @param options - The options
*
* @returns The end of an ISO week-numbering year
*
* @example
* // The end of an ISO week-numbering year for 2 July 2005:
* const result = endOfISOWeekYear(new Date(2005, 6, 2))
* //=> Sun Jan 01 2006 23:59:59.999
*/
export function endOfISOWeekYear(date, options) {
const year = getISOWeekYear(date, options);
const fourthOfJanuaryOfNextYear = constructFrom(options?.in || date, 0);
fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4);
fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0);
const _date = startOfISOWeek(fourthOfJanuaryOfNextYear, options);
_date.setMilliseconds(_date.getMilliseconds() - 1);
return _date;
}
// Fallback for modularized imports:
export default endOfISOWeekYear;
+36
View File
@@ -0,0 +1,36 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfMinute} function options.
*/
/**
* @name endOfMinute
* @category Minute Helpers
* @summary Return the end of a minute for the given date.
*
* @description
* Return the end of a minute for the given date.
* The result will be in the local timezone or the provided context.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a minute
*
* @example
* // The end of a minute for 1 December 2014 22:15:45.400:
* const result = endOfMinute(new Date(2014, 11, 1, 22, 15, 45, 400))
* //=> Mon Dec 01 2014 22:15:59.999
*/
export function endOfMinute(date, options) {
const _date = toDate(date, options?.in);
_date.setSeconds(59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfMinute;
+38
View File
@@ -0,0 +1,38 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfMonth} function options.
*/
/**
* @name endOfMonth
* @category Month Helpers
* @summary Return the end of a month for the given date.
*
* @description
* Return the end of a month for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a month
*
* @example
* // The end of a month for 2 September 2014 11:55:00:
* const result = endOfMonth(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 30 2014 23:59:59.999
*/
export function endOfMonth(date, options) {
const _date = toDate(date, options?.in);
const month = _date.getMonth();
_date.setFullYear(_date.getFullYear(), month + 1, 0);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfMonth;
+39
View File
@@ -0,0 +1,39 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfQuarter} function options.
*/
/**
* @name endOfQuarter
* @category Quarter Helpers
* @summary Return the end of a year quarter for the given date.
*
* @description
* Return the end of a year quarter for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a quarter
*
* @example
* // The end of a quarter for 2 September 2014 11:55:00:
* const result = endOfQuarter(new Date(2014, 8, 2, 11, 55, 0))
* //=> Tue Sep 30 2014 23:59:59.999
*/
export function endOfQuarter(date, options) {
const _date = toDate(date, options?.in);
const currentMonth = _date.getMonth();
const month = currentMonth - (currentMonth % 3) + 3;
_date.setMonth(month, 0);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfQuarter;
+36
View File
@@ -0,0 +1,36 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfSecond} function options.
*/
/**
* @name endOfSecond
* @category Second Helpers
* @summary Return the end of a second for the given date.
*
* @description
* Return the end of a second for the given date.
* The result will be in the local timezone if no `in` option is specified.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a second
*
* @example
* // The end of a second for 1 December 2014 22:15:45.400:
* const result = endOfSecond(new Date(2014, 11, 1, 22, 15, 45, 400))
* //=> Mon Dec 01 2014 22:15:45.999
*/
export function endOfSecond(date, options) {
const _date = toDate(date, options?.in);
_date.setMilliseconds(999);
return _date;
}
// Fallback for modularized imports:
export default endOfSecond;
+33
View File
@@ -0,0 +1,33 @@
import { endOfDay } from "./endOfDay.js";
/**
* The {@link endOfToday} function options.
*/
/**
* @name endOfToday
* @category Day Helpers
* @summary Return the end of today.
* @pure false
*
* @description
* Return the end of today.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param options - The options
*
* @returns The end of today
*
* @example
* // If today is 6 October 2014:
* const result = endOfToday()
* //=> Mon Oct 6 2014 23:59:59.999
*/
export function endOfToday(options) {
return endOfDay(Date.now(), options);
}
// Fallback for modularized imports:
export default endOfToday;
+40
View File
@@ -0,0 +1,40 @@
import { constructNow } from "./constructNow.js";
/**
* The {@link endOfTomorrow} function options.
*/
/**
* @name endOfTomorrow
* @category Day Helpers
* @summary Return the end of tomorrow.
* @pure false
*
* @description
* Return the end of tomorrow.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param options - The options
* @returns The end of tomorrow
*
* @example
* // If today is 6 October 2014:
* const result = endOfTomorrow()
* //=> Tue Oct 7 2014 23:59:59.999
*/
export function endOfTomorrow(options) {
const now = constructNow(options?.in);
const year = now.getFullYear();
const month = now.getMonth();
const day = now.getDate();
const date = constructNow(options?.in);
date.setFullYear(year, month, day + 1);
date.setHours(23, 59, 59, 999);
return options?.in ? options.in(date) : date;
}
// Fallback for modularized imports:
export default endOfTomorrow;
+54
View File
@@ -0,0 +1,54 @@
import { getDefaultOptions } from "./_lib/defaultOptions.js";
import { toDate } from "./toDate.js";
/**
* The {@link endOfWeek} function options.
*/
/**
* @name endOfWeek
* @category Week Helpers
* @summary Return the end of a week for the given date.
*
* @description
* Return the end of a week for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - An object with options
*
* @returns The end of a week
*
* @example
* // The end of a week for 2 September 2014 11:55:00:
* const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0))
* //=> Sat Sep 06 2014 23:59:59.999
*
* @example
* // If the week starts on Monday, the end of the week for 2 September 2014 11:55:00:
* const result = endOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
* //=> Sun Sep 07 2014 23:59:59.999
*/
export function endOfWeek(date, options) {
const defaultOptions = getDefaultOptions();
const weekStartsOn =
options?.weekStartsOn ??
options?.locale?.options?.weekStartsOn ??
defaultOptions.weekStartsOn ??
defaultOptions.locale?.options?.weekStartsOn ??
0;
const _date = toDate(date, options?.in);
const day = _date.getDay();
const diff = (day < weekStartsOn ? -7 : 0) + 6 - (day - weekStartsOn);
_date.setDate(_date.getDate() + diff);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfWeek;
+38
View File
@@ -0,0 +1,38 @@
import { toDate } from "./toDate.js";
/**
* The {@link endOfYear} function options.
*/
/**
* @name endOfYear
* @category Year Helpers
* @summary Return the end of a year for the given date.
*
* @description
* Return the end of a year for the given date.
* The result will be in the local timezone.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @param date - The original date
* @param options - The options
*
* @returns The end of a year
*
* @example
* // The end of a year for 2 September 2014 11:55:00:
* const result = endOfYear(new Date(2014, 8, 2, 11, 55, 0))
* //=> Wed Dec 31 2014 23:59:59.999
*/
export function endOfYear(date, options) {
const _date = toDate(date, options?.in);
const year = _date.getFullYear();
_date.setFullYear(year + 1, 0, 0);
_date.setHours(23, 59, 59, 999);
return _date;
}
// Fallback for modularized imports:
export default endOfYear;
+36
View File
@@ -0,0 +1,36 @@
import { constructFrom } from "./constructFrom.js";
import { constructNow } from "./constructNow.js";
/**
* The {@link endOfYesterday} function options.
*/
/**
* @name endOfYesterday
* @category Day Helpers
* @summary Return the end of yesterday.
* @pure false
*
* @description
* Return the end of yesterday.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
* @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
*
* @returns The end of yesterday
*
* @example
* // If today is 6 October 2014:
* const result = endOfYesterday()
* //=> Sun Oct 5 2014 23:59:59.999
*/
export function endOfYesterday(options) {
const now = constructNow(options?.in);
const date = constructFrom(options?.in, 0);
date.setFullYear(now.getFullYear(), now.getMonth(), now.getDate() - 1);
date.setHours(23, 59, 59, 999);
return date;
}
// Fallback for modularized imports:
export default endOfYesterday;
+434
View File
@@ -0,0 +1,434 @@
import { defaultLocale } from "./_lib/defaultLocale.js";
import { getDefaultOptions } from "./_lib/defaultOptions.js";
import { formatters } from "./_lib/format/formatters.js";
import { longFormatters } from "./_lib/format/longFormatters.js";
import {
isProtectedDayOfYearToken,
isProtectedWeekYearToken,
warnOrThrowProtectedError,
} from "./_lib/protectedTokens.js";
import { isValid } from "./isValid.js";
import { toDate } from "./toDate.js";
// Rexports of internal for libraries to use.
// See: https://github.com/date-fns/date-fns/issues/3638#issuecomment-1877082874
export { formatters, longFormatters };
// This RegExp consists of three parts separated by `|`:
// - [yYQqMLwIdDecihHKkms]o matches any available ordinal number token
// (one of the certain letters followed by `o`)
// - (\w)\1* matches any sequences of the same letter
// - '' matches two quote characters in a row
// - '(''|[^'])+('|$) matches anything surrounded by two quote characters ('),
// except a single quote symbol, which ends the sequence.
// Two quote characters do not end the sequence.
// If there is no matching single quote
// then the sequence will continue until the end of the string.
// - . matches any single character unmatched by previous parts of the RegExps
const formattingTokensRegExp =
/[yYQqMLwIdDecihHKkms]o|(\w)\1*|''|'(''|[^'])+('|$)|./g;
// This RegExp catches symbols escaped by quotes, and also
// sequences of symbols P, p, and the combinations like `PPPPPPPppppp`
const longFormattingTokensRegExp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;
const escapedStringRegExp = /^'([^]*?)'?$/;
const doubleQuoteRegExp = /''/g;
const unescapedLatinCharacterRegExp = /[a-zA-Z]/;
export { format as formatDate };
/**
* The {@link format} function options.
*/
/**
* @name format
* @alias formatDate
* @category Common Helpers
* @summary Format the date.
*
* @description
* Return the formatted date string in the given format. The result may vary by locale.
*
* > ⚠️ Please note that the `format` tokens differ from Moment.js and other libraries.
* > See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
*
* The characters wrapped between two single quotes characters (') are escaped.
* Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.
* (see the last example)
*
* Format of the string is based on Unicode Technical Standard #35:
* https://www.unicode.org/reports/tr35/tr35-dates.html#Date_Field_Symbol_Table
* with a few additions (see note 7 below the table).
*
* Accepted patterns:
* | Unit | Pattern | Result examples | Notes |
* |---------------------------------|---------|-----------------------------------|-------|
* | Era | G..GGG | AD, BC | |
* | | GGGG | Anno Domini, Before Christ | 2 |
* | | GGGGG | A, B | |
* | Calendar year | y | 44, 1, 1900, 2017 | 5 |
* | | yo | 44th, 1st, 0th, 17th | 5,7 |
* | | yy | 44, 01, 00, 17 | 5 |
* | | yyy | 044, 001, 1900, 2017 | 5 |
* | | yyyy | 0044, 0001, 1900, 2017 | 5 |
* | | yyyyy | ... | 3,5 |
* | Local week-numbering year | Y | 44, 1, 1900, 2017 | 5 |
* | | Yo | 44th, 1st, 1900th, 2017th | 5,7 |
* | | YY | 44, 01, 00, 17 | 5,8 |
* | | YYY | 044, 001, 1900, 2017 | 5 |
* | | YYYY | 0044, 0001, 1900, 2017 | 5,8 |
* | | YYYYY | ... | 3,5 |
* | ISO week-numbering year | R | -43, 0, 1, 1900, 2017 | 5,7 |
* | | RR | -43, 00, 01, 1900, 2017 | 5,7 |
* | | RRR | -043, 000, 001, 1900, 2017 | 5,7 |
* | | RRRR | -0043, 0000, 0001, 1900, 2017 | 5,7 |
* | | RRRRR | ... | 3,5,7 |
* | Extended year | u | -43, 0, 1, 1900, 2017 | 5 |
* | | uu | -43, 01, 1900, 2017 | 5 |
* | | uuu | -043, 001, 1900, 2017 | 5 |
* | | uuuu | -0043, 0001, 1900, 2017 | 5 |
* | | uuuuu | ... | 3,5 |
* | Quarter (formatting) | Q | 1, 2, 3, 4 | |
* | | Qo | 1st, 2nd, 3rd, 4th | 7 |
* | | QQ | 01, 02, 03, 04 | |
* | | QQQ | Q1, Q2, Q3, Q4 | |
* | | QQQQ | 1st quarter, 2nd quarter, ... | 2 |
* | | QQQQQ | 1, 2, 3, 4 | 4 |
* | Quarter (stand-alone) | q | 1, 2, 3, 4 | |
* | | qo | 1st, 2nd, 3rd, 4th | 7 |
* | | qq | 01, 02, 03, 04 | |
* | | qqq | Q1, Q2, Q3, Q4 | |
* | | qqqq | 1st quarter, 2nd quarter, ... | 2 |
* | | qqqqq | 1, 2, 3, 4 | 4 |
* | Month (formatting) | M | 1, 2, ..., 12 | |
* | | Mo | 1st, 2nd, ..., 12th | 7 |
* | | MM | 01, 02, ..., 12 | |
* | | MMM | Jan, Feb, ..., Dec | |
* | | MMMM | January, February, ..., December | 2 |
* | | MMMMM | J, F, ..., D | |
* | Month (stand-alone) | L | 1, 2, ..., 12 | |
* | | Lo | 1st, 2nd, ..., 12th | 7 |
* | | LL | 01, 02, ..., 12 | |
* | | LLL | Jan, Feb, ..., Dec | |
* | | LLLL | January, February, ..., December | 2 |
* | | LLLLL | J, F, ..., D | |
* | Local week of year | w | 1, 2, ..., 53 | |
* | | wo | 1st, 2nd, ..., 53th | 7 |
* | | ww | 01, 02, ..., 53 | |
* | ISO week of year | I | 1, 2, ..., 53 | 7 |
* | | Io | 1st, 2nd, ..., 53th | 7 |
* | | II | 01, 02, ..., 53 | 7 |
* | Day of month | d | 1, 2, ..., 31 | |
* | | do | 1st, 2nd, ..., 31st | 7 |
* | | dd | 01, 02, ..., 31 | |
* | Day of year | D | 1, 2, ..., 365, 366 | 9 |
* | | Do | 1st, 2nd, ..., 365th, 366th | 7 |
* | | DD | 01, 02, ..., 365, 366 | 9 |
* | | DDD | 001, 002, ..., 365, 366 | |
* | | DDDD | ... | 3 |
* | Day of week (formatting) | E..EEE | Mon, Tue, Wed, ..., Sun | |
* | | EEEE | Monday, Tuesday, ..., Sunday | 2 |
* | | EEEEE | M, T, W, T, F, S, S | |
* | | EEEEEE | Mo, Tu, We, Th, Fr, Sa, Su | |
* | ISO day of week (formatting) | i | 1, 2, 3, ..., 7 | 7 |
* | | io | 1st, 2nd, ..., 7th | 7 |
* | | ii | 01, 02, ..., 07 | 7 |
* | | iii | Mon, Tue, Wed, ..., Sun | 7 |
* | | iiii | Monday, Tuesday, ..., Sunday | 2,7 |
* | | iiiii | M, T, W, T, F, S, S | 7 |
* | | iiiiii | Mo, Tu, We, Th, Fr, Sa, Su | 7 |
* | Local day of week (formatting) | e | 2, 3, 4, ..., 1 | |
* | | eo | 2nd, 3rd, ..., 1st | 7 |
* | | ee | 02, 03, ..., 01 | |
* | | eee | Mon, Tue, Wed, ..., Sun | |
* | | eeee | Monday, Tuesday, ..., Sunday | 2 |
* | | eeeee | M, T, W, T, F, S, S | |
* | | eeeeee | Mo, Tu, We, Th, Fr, Sa, Su | |
* | Local day of week (stand-alone) | c | 2, 3, 4, ..., 1 | |
* | | co | 2nd, 3rd, ..., 1st | 7 |
* | | cc | 02, 03, ..., 01 | |
* | | ccc | Mon, Tue, Wed, ..., Sun | |
* | | cccc | Monday, Tuesday, ..., Sunday | 2 |
* | | ccccc | M, T, W, T, F, S, S | |
* | | cccccc | Mo, Tu, We, Th, Fr, Sa, Su | |
* | AM, PM | a..aa | AM, PM | |
* | | aaa | am, pm | |
* | | aaaa | a.m., p.m. | 2 |
* | | aaaaa | a, p | |
* | AM, PM, noon, midnight | b..bb | AM, PM, noon, midnight | |
* | | bbb | am, pm, noon, midnight | |
* | | bbbb | a.m., p.m., noon, midnight | 2 |
* | | bbbbb | a, p, n, mi | |
* | Flexible day period | B..BBB | at night, in the morning, ... | |
* | | BBBB | at night, in the morning, ... | 2 |
* | | BBBBB | at night, in the morning, ... | |
* | Hour [1-12] | h | 1, 2, ..., 11, 12 | |
* | | ho | 1st, 2nd, ..., 11th, 12th | 7 |
* | | hh | 01, 02, ..., 11, 12 | |
* | Hour [0-23] | H | 0, 1, 2, ..., 23 | |
* | | Ho | 0th, 1st, 2nd, ..., 23rd | 7 |
* | | HH | 00, 01, 02, ..., 23 | |
* | Hour [0-11] | K | 1, 2, ..., 11, 0 | |
* | | Ko | 1st, 2nd, ..., 11th, 0th | 7 |
* | | KK | 01, 02, ..., 11, 00 | |
* | Hour [1-24] | k | 24, 1, 2, ..., 23 | |
* | | ko | 24th, 1st, 2nd, ..., 23rd | 7 |
* | | kk | 24, 01, 02, ..., 23 | |
* | Minute | m | 0, 1, ..., 59 | |
* | | mo | 0th, 1st, ..., 59th | 7 |
* | | mm | 00, 01, ..., 59 | |
* | Second | s | 0, 1, ..., 59 | |
* | | so | 0th, 1st, ..., 59th | 7 |
* | | ss | 00, 01, ..., 59 | |
* | Fraction of second | S | 0, 1, ..., 9 | |
* | | SS | 00, 01, ..., 99 | |
* | | SSS | 000, 001, ..., 999 | |
* | | SSSS | ... | 3 |
* | Timezone (ISO-8601 w/ Z) | X | -08, +0530, Z | |
* | | XX | -0800, +0530, Z | |
* | | XXX | -08:00, +05:30, Z | |
* | | XXXX | -0800, +0530, Z, +123456 | 2 |
* | | XXXXX | -08:00, +05:30, Z, +12:34:56 | |
* | Timezone (ISO-8601 w/o Z) | x | -08, +0530, +00 | |
* | | xx | -0800, +0530, +0000 | |
* | | xxx | -08:00, +05:30, +00:00 | 2 |
* | | xxxx | -0800, +0530, +0000, +123456 | |
* | | xxxxx | -08:00, +05:30, +00:00, +12:34:56 | |
* | Timezone (GMT) | O...OOO | GMT-8, GMT+5:30, GMT+0 | |
* | | OOOO | GMT-08:00, GMT+05:30, GMT+00:00 | 2 |
* | Timezone (specific non-locat.) | z...zzz | GMT-8, GMT+5:30, GMT+0 | 6 |
* | | zzzz | GMT-08:00, GMT+05:30, GMT+00:00 | 2,6 |
* | Seconds timestamp | t | 512969520 | 7 |
* | | tt | ... | 3,7 |
* | Milliseconds timestamp | T | 512969520900 | 7 |
* | | TT | ... | 3,7 |
* | Long localized date | P | 04/29/1453 | 7 |
* | | PP | Apr 29, 1453 | 7 |
* | | PPP | April 29th, 1453 | 7 |
* | | PPPP | Friday, April 29th, 1453 | 2,7 |
* | Long localized time | p | 12:00 AM | 7 |
* | | pp | 12:00:00 AM | 7 |
* | | ppp | 12:00:00 AM GMT+2 | 7 |
* | | pppp | 12:00:00 AM GMT+02:00 | 2,7 |
* | Combination of date and time | Pp | 04/29/1453, 12:00 AM | 7 |
* | | PPpp | Apr 29, 1453, 12:00:00 AM | 7 |
* | | PPPppp | April 29th, 1453 at ... | 7 |
* | | PPPPpppp| Friday, April 29th, 1453 at ... | 2,7 |
* Notes:
* 1. "Formatting" units (e.g. formatting quarter) in the default en-US locale
* are the same as "stand-alone" units, but are different in some languages.
* "Formatting" units are declined according to the rules of the language
* in the context of a date. "Stand-alone" units are always nominative singular:
*
* `format(new Date(2017, 10, 6), 'do LLLL', {locale: cs}) //=> '6. listopad'`
*
* `format(new Date(2017, 10, 6), 'do MMMM', {locale: cs}) //=> '6. listopadu'`
*
* 2. Any sequence of the identical letters is a pattern, unless it is escaped by
* the single quote characters (see below).
* If the sequence is longer than listed in table (e.g. `EEEEEEEEEEE`)
* the output will be the same as default pattern for this unit, usually
* the longest one (in case of ISO weekdays, `EEEE`). Default patterns for units
* are marked with "2" in the last column of the table.
*
* `format(new Date(2017, 10, 6), 'MMM') //=> 'Nov'`
*
* `format(new Date(2017, 10, 6), 'MMMM') //=> 'November'`
*
* `format(new Date(2017, 10, 6), 'MMMMM') //=> 'N'`
*
* `format(new Date(2017, 10, 6), 'MMMMMM') //=> 'November'`
*
* `format(new Date(2017, 10, 6), 'MMMMMMM') //=> 'November'`
*
* 3. Some patterns could be unlimited length (such as `yyyyyyyy`).
* The output will be padded with zeros to match the length of the pattern.
*
* `format(new Date(2017, 10, 6), 'yyyyyyyy') //=> '00002017'`
*
* 4. `QQQQQ` and `qqqqq` could be not strictly numerical in some locales.
* These tokens represent the shortest form of the quarter.
*
* 5. The main difference between `y` and `u` patterns are B.C. years:
*
* | Year | `y` | `u` |
* |------|-----|-----|
* | AC 1 | 1 | 1 |
* | BC 1 | 1 | 0 |
* | BC 2 | 2 | -1 |
*
* Also `yy` always returns the last two digits of a year,
* while `uu` pads single digit years to 2 characters and returns other years unchanged:
*
* | Year | `yy` | `uu` |
* |------|------|------|
* | 1 | 01 | 01 |
* | 14 | 14 | 14 |
* | 376 | 76 | 376 |
* | 1453 | 53 | 1453 |
*
* The same difference is true for local and ISO week-numbering years (`Y` and `R`),
* except local week-numbering years are dependent on `options.weekStartsOn`
* and `options.firstWeekContainsDate` (compare [getISOWeekYear](https://date-fns.org/docs/getISOWeekYear)
* and [getWeekYear](https://date-fns.org/docs/getWeekYear)).
*
* 6. Specific non-location timezones are currently unavailable in `date-fns`,
* so right now these tokens fall back to GMT timezones.
*
* 7. These patterns are not in the Unicode Technical Standard #35:
* - `i`: ISO day of week
* - `I`: ISO week of year
* - `R`: ISO week-numbering year
* - `t`: seconds timestamp
* - `T`: milliseconds timestamp
* - `o`: ordinal number modifier
* - `P`: long localized date
* - `p`: long localized time
*
* 8. `YY` and `YYYY` tokens represent week-numbering years but they are often confused with years.
* You should enable `options.useAdditionalWeekYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
*
* 9. `D` and `DD` tokens represent days of the year but they are often confused with days of the month.
* You should enable `options.useAdditionalDayOfYearTokens` to use them. See: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
*
* @param date - The original date
* @param format - The string of tokens
* @param options - An object with options
*
* @returns The formatted date string
*
* @throws `date` must not be Invalid Date
* @throws `options.locale` must contain `localize` property
* @throws `options.locale` must contain `formatLong` property
* @throws use `yyyy` instead of `YYYY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
* @throws use `yy` instead of `YY` for formatting years using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
* @throws use `d` instead of `D` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
* @throws use `dd` instead of `DD` for formatting days of the month using [format provided] to the input [input provided]; see: https://github.com/date-fns/date-fns/blob/master/docs/unicodeTokens.md
* @throws format string contains an unescaped latin alphabet character
*
* @example
* // Represent 11 February 2014 in middle-endian format:
* const result = format(new Date(2014, 1, 11), 'MM/dd/yyyy')
* //=> '02/11/2014'
*
* @example
* // Represent 2 July 2014 in Esperanto:
* import { eoLocale } from 'date-fns/locale/eo'
* const result = format(new Date(2014, 6, 2), "do 'de' MMMM yyyy", {
* locale: eoLocale
* })
* //=> '2-a de julio 2014'
*
* @example
* // Escape string by single quote characters:
* const result = format(new Date(2014, 6, 2, 15), "h 'o''clock'")
* //=> "3 o'clock"
*/
export function format(date, formatStr, options) {
const defaultOptions = getDefaultOptions();
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
const firstWeekContainsDate =
options?.firstWeekContainsDate ??
options?.locale?.options?.firstWeekContainsDate ??
defaultOptions.firstWeekContainsDate ??
defaultOptions.locale?.options?.firstWeekContainsDate ??
1;
const weekStartsOn =
options?.weekStartsOn ??
options?.locale?.options?.weekStartsOn ??
defaultOptions.weekStartsOn ??
defaultOptions.locale?.options?.weekStartsOn ??
0;
const originalDate = toDate(date, options?.in);
if (!isValid(originalDate)) {
throw new RangeError("Invalid time value");
}
let parts = formatStr
.match(longFormattingTokensRegExp)
.map((substring) => {
const firstCharacter = substring[0];
if (firstCharacter === "p" || firstCharacter === "P") {
const longFormatter = longFormatters[firstCharacter];
return longFormatter(substring, locale.formatLong);
}
return substring;
})
.join("")
.match(formattingTokensRegExp)
.map((substring) => {
// Replace two single quote characters with one single quote character
if (substring === "''") {
return { isToken: false, value: "'" };
}
const firstCharacter = substring[0];
if (firstCharacter === "'") {
return { isToken: false, value: cleanEscapedString(substring) };
}
if (formatters[firstCharacter]) {
return { isToken: true, value: substring };
}
if (firstCharacter.match(unescapedLatinCharacterRegExp)) {
throw new RangeError(
"Format string contains an unescaped latin alphabet character `" +
firstCharacter +
"`",
);
}
return { isToken: false, value: substring };
});
// invoke localize preprocessor (only for french locales at the moment)
if (locale.localize.preprocessor) {
parts = locale.localize.preprocessor(originalDate, parts);
}
const formatterOptions = {
firstWeekContainsDate,
weekStartsOn,
locale,
};
return parts
.map((part) => {
if (!part.isToken) return part.value;
const token = part.value;
if (
(!options?.useAdditionalWeekYearTokens &&
isProtectedWeekYearToken(token)) ||
(!options?.useAdditionalDayOfYearTokens &&
isProtectedDayOfYearToken(token))
) {
warnOrThrowProtectedError(token, formatStr, String(date));
}
const formatter = formatters[token[0]];
return formatter(originalDate, token, locale.localize, formatterOptions);
})
.join("");
}
function cleanEscapedString(input) {
const matched = input.match(escapedStringRegExp);
if (!matched) {
return input;
}
return matched[1].replace(doubleQuoteRegExp, "'");
}
// Fallback for modularized imports:
export default format;
+199
View File
@@ -0,0 +1,199 @@
import { defaultLocale } from "./_lib/defaultLocale.js";
import { getDefaultOptions } from "./_lib/defaultOptions.js";
import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { compareAsc } from "./compareAsc.js";
import { minutesInDay, minutesInMonth } from "./constants.js";
import { differenceInMonths } from "./differenceInMonths.js";
import { differenceInSeconds } from "./differenceInSeconds.js";
/**
* The {@link formatDistance} function options.
*/
/**
* @name formatDistance
* @category Common Helpers
* @summary Return the distance between the given dates in words.
*
* @description
* Return the distance between the given dates in words.
*
* | Distance between dates | Result |
* |-------------------------------------------------------------------|---------------------|
* | 0 ... 30 secs | less than a minute |
* | 30 secs ... 1 min 30 secs | 1 minute |
* | 1 min 30 secs ... 44 mins 30 secs | [2..44] minutes |
* | 44 mins ... 30 secs ... 89 mins 30 secs | about 1 hour |
* | 89 mins 30 secs ... 23 hrs 59 mins 30 secs | about [2..24] hours |
* | 23 hrs 59 mins 30 secs ... 41 hrs 59 mins 30 secs | 1 day |
* | 41 hrs 59 mins 30 secs ... 29 days 23 hrs 59 mins 30 secs | [2..30] days |
* | 29 days 23 hrs 59 mins 30 secs ... 44 days 23 hrs 59 mins 30 secs | about 1 month |
* | 44 days 23 hrs 59 mins 30 secs ... 59 days 23 hrs 59 mins 30 secs | about 2 months |
* | 59 days 23 hrs 59 mins 30 secs ... 1 yr | [2..12] months |
* | 1 yr ... 1 yr 3 months | about 1 year |
* | 1 yr 3 months ... 1 yr 9 month s | over 1 year |
* | 1 yr 9 months ... 2 yrs | almost 2 years |
* | N yrs ... N yrs 3 months | about N years |
* | N yrs 3 months ... N yrs 9 months | over N years |
* | N yrs 9 months ... N+1 yrs | almost N+1 years |
*
* With `options.includeSeconds == true`:
* | Distance between dates | Result |
* |------------------------|----------------------|
* | 0 secs ... 5 secs | less than 5 seconds |
* | 5 secs ... 10 secs | less than 10 seconds |
* | 10 secs ... 20 secs | less than 20 seconds |
* | 20 secs ... 40 secs | half a minute |
* | 40 secs ... 60 secs | less than a minute |
* | 60 secs ... 90 secs | 1 minute |
*
* @param laterDate - The date
* @param earlierDate - The date to compare with
* @param options - An object with options
*
* @returns The distance in words
*
* @throws `date` must not be Invalid Date
* @throws `baseDate` must not be Invalid Date
* @throws `options.locale` must contain `formatDistance` property
*
* @example
* // What is the distance between 2 July 2014 and 1 January 2015?
* const result = formatDistance(new Date(2014, 6, 2), new Date(2015, 0, 1))
* //=> '6 months'
*
* @example
* // What is the distance between 1 January 2015 00:00:15
* // and 1 January 2015 00:00:00, including seconds?
* const result = formatDistance(
* new Date(2015, 0, 1, 0, 0, 15),
* new Date(2015, 0, 1, 0, 0, 0),
* { includeSeconds: true }
* )
* //=> 'less than 20 seconds'
*
* @example
* // What is the distance from 1 January 2016
* // to 1 January 2015, with a suffix?
* const result = formatDistance(new Date(2015, 0, 1), new Date(2016, 0, 1), {
* addSuffix: true
* })
* //=> 'about 1 year ago'
*
* @example
* // What is the distance between 1 August 2016 and 1 January 2015 in Esperanto?
* import { eoLocale } from 'date-fns/locale/eo'
* const result = formatDistance(new Date(2016, 7, 1), new Date(2015, 0, 1), {
* locale: eoLocale
* })
* //=> 'pli ol 1 jaro'
*/
export function formatDistance(laterDate, earlierDate, options) {
const defaultOptions = getDefaultOptions();
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
const minutesInAlmostTwoDays = 2520;
const comparison = compareAsc(laterDate, earlierDate);
if (isNaN(comparison)) throw new RangeError("Invalid time value");
const localizeOptions = Object.assign({}, options, {
addSuffix: options?.addSuffix,
comparison: comparison,
});
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
...(comparison > 0 ? [earlierDate, laterDate] : [laterDate, earlierDate]),
);
const seconds = differenceInSeconds(earlierDate_, laterDate_);
const offsetInSeconds =
(getTimezoneOffsetInMilliseconds(earlierDate_) -
getTimezoneOffsetInMilliseconds(laterDate_)) /
1000;
const minutes = Math.round((seconds - offsetInSeconds) / 60);
let months;
// 0 up to 2 mins
if (minutes < 2) {
if (options?.includeSeconds) {
if (seconds < 5) {
return locale.formatDistance("lessThanXSeconds", 5, localizeOptions);
} else if (seconds < 10) {
return locale.formatDistance("lessThanXSeconds", 10, localizeOptions);
} else if (seconds < 20) {
return locale.formatDistance("lessThanXSeconds", 20, localizeOptions);
} else if (seconds < 40) {
return locale.formatDistance("halfAMinute", 0, localizeOptions);
} else if (seconds < 60) {
return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
} else {
return locale.formatDistance("xMinutes", 1, localizeOptions);
}
} else {
if (minutes === 0) {
return locale.formatDistance("lessThanXMinutes", 1, localizeOptions);
} else {
return locale.formatDistance("xMinutes", minutes, localizeOptions);
}
}
// 2 mins up to 0.75 hrs
} else if (minutes < 45) {
return locale.formatDistance("xMinutes", minutes, localizeOptions);
// 0.75 hrs up to 1.5 hrs
} else if (minutes < 90) {
return locale.formatDistance("aboutXHours", 1, localizeOptions);
// 1.5 hrs up to 24 hrs
} else if (minutes < minutesInDay) {
const hours = Math.round(minutes / 60);
return locale.formatDistance("aboutXHours", hours, localizeOptions);
// 1 day up to 1.75 days
} else if (minutes < minutesInAlmostTwoDays) {
return locale.formatDistance("xDays", 1, localizeOptions);
// 1.75 days up to 30 days
} else if (minutes < minutesInMonth) {
const days = Math.round(minutes / minutesInDay);
return locale.formatDistance("xDays", days, localizeOptions);
// 1 month up to 2 months
} else if (minutes < minutesInMonth * 2) {
months = Math.round(minutes / minutesInMonth);
return locale.formatDistance("aboutXMonths", months, localizeOptions);
}
months = differenceInMonths(earlierDate_, laterDate_);
// 2 months up to 12 months
if (months < 12) {
const nearestMonth = Math.round(minutes / minutesInMonth);
return locale.formatDistance("xMonths", nearestMonth, localizeOptions);
// 1 year up to max Date
} else {
const monthsSinceStartOfYear = months % 12;
const years = Math.trunc(months / 12);
// N years up to 1 years 3 months
if (monthsSinceStartOfYear < 3) {
return locale.formatDistance("aboutXYears", years, localizeOptions);
// N years 3 months up to N years 9 months
} else if (monthsSinceStartOfYear < 9) {
return locale.formatDistance("overXYears", years, localizeOptions);
// N years 9 months up to N year 12 months
} else {
return locale.formatDistance("almostXYears", years + 1, localizeOptions);
}
}
}
// Fallback for modularized imports:
export default formatDistance;
+189
View File
@@ -0,0 +1,189 @@
import { defaultLocale } from "./_lib/defaultLocale.js";
import { getDefaultOptions } from "./_lib/defaultOptions.js";
import { getRoundingMethod } from "./_lib/getRoundingMethod.js";
import { getTimezoneOffsetInMilliseconds } from "./_lib/getTimezoneOffsetInMilliseconds.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { compareAsc } from "./compareAsc.js";
import {
millisecondsInMinute,
minutesInDay,
minutesInMonth,
minutesInYear,
} from "./constants.js";
/**
* The {@link formatDistanceStrict} function options.
*/
/**
* The unit used to format the distance in {@link formatDistanceStrict}.
*/
/**
* @name formatDistanceStrict
* @category Common Helpers
* @summary Return the distance between the given dates in words.
*
* @description
* Return the distance between the given dates in words, using strict units.
* This is like `formatDistance`, but does not use helpers like 'almost', 'over',
* 'less than' and the like.
*
* | Distance between dates | Result |
* |------------------------|---------------------|
* | 0 ... 59 secs | [0..59] seconds |
* | 1 ... 59 mins | [1..59] minutes |
* | 1 ... 23 hrs | [1..23] hours |
* | 1 ... 29 days | [1..29] days |
* | 1 ... 11 months | [1..11] months |
* | 1 ... N years | [1..N] years |
*
* @param laterDate - The date
* @param earlierDate - The date to compare with
* @param options - An object with options
*
* @returns The distance in words
*
* @throws `date` must not be Invalid Date
* @throws `baseDate` must not be Invalid Date
* @throws `options.unit` must be 'second', 'minute', 'hour', 'day', 'month' or 'year'
* @throws `options.locale` must contain `formatDistance` property
*
* @example
* // What is the distance between 2 July 2014 and 1 January 2015?
* const result = formatDistanceStrict(new Date(2014, 6, 2), new Date(2015, 0, 2))
* //=> '6 months'
*
* @example
* // What is the distance between 1 January 2015 00:00:15
* // and 1 January 2015 00:00:00?
* const result = formatDistanceStrict(
* new Date(2015, 0, 1, 0, 0, 15),
* new Date(2015, 0, 1, 0, 0, 0)
* )
* //=> '15 seconds'
*
* @example
* // What is the distance from 1 January 2016
* // to 1 January 2015, with a suffix?
* const result = formatDistanceStrict(new Date(2015, 0, 1), new Date(2016, 0, 1), {
* addSuffix: true
* })
* //=> '1 year ago'
*
* @example
* // What is the distance from 1 January 2016
* // to 1 January 2015, in minutes?
* const result = formatDistanceStrict(new Date(2016, 0, 1), new Date(2015, 0, 1), {
* unit: 'minute'
* })
* //=> '525600 minutes'
*
* @example
* // What is the distance from 1 January 2015
* // to 28 January 2015, in months, rounded up?
* const result = formatDistanceStrict(new Date(2015, 0, 28), new Date(2015, 0, 1), {
* unit: 'month',
* roundingMethod: 'ceil'
* })
* //=> '1 month'
*
* @example
* // What is the distance between 1 August 2016 and 1 January 2015 in Esperanto?
* import { eoLocale } from 'date-fns/locale/eo'
* const result = formatDistanceStrict(new Date(2016, 7, 1), new Date(2015, 0, 1), {
* locale: eoLocale
* })
* //=> '1 jaro'
*/
export function formatDistanceStrict(laterDate, earlierDate, options) {
const defaultOptions = getDefaultOptions();
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
const comparison = compareAsc(laterDate, earlierDate);
if (isNaN(comparison)) {
throw new RangeError("Invalid time value");
}
const localizeOptions = Object.assign({}, options, {
addSuffix: options?.addSuffix,
comparison: comparison,
});
const [laterDate_, earlierDate_] = normalizeDates(
options?.in,
...(comparison > 0 ? [earlierDate, laterDate] : [laterDate, earlierDate]),
);
const roundingMethod = getRoundingMethod(options?.roundingMethod ?? "round");
const milliseconds = earlierDate_.getTime() - laterDate_.getTime();
const minutes = milliseconds / millisecondsInMinute;
const timezoneOffset =
getTimezoneOffsetInMilliseconds(earlierDate_) -
getTimezoneOffsetInMilliseconds(laterDate_);
// Use DST-normalized difference in minutes for years, months and days;
// use regular difference in minutes for hours, minutes and seconds.
const dstNormalizedMinutes =
(milliseconds - timezoneOffset) / millisecondsInMinute;
const defaultUnit = options?.unit;
let unit;
if (!defaultUnit) {
if (minutes < 1) {
unit = "second";
} else if (minutes < 60) {
unit = "minute";
} else if (minutes < minutesInDay) {
unit = "hour";
} else if (dstNormalizedMinutes < minutesInMonth) {
unit = "day";
} else if (dstNormalizedMinutes < minutesInYear) {
unit = "month";
} else {
unit = "year";
}
} else {
unit = defaultUnit;
}
// 0 up to 60 seconds
if (unit === "second") {
const seconds = roundingMethod(milliseconds / 1000);
return locale.formatDistance("xSeconds", seconds, localizeOptions);
// 1 up to 60 mins
} else if (unit === "minute") {
const roundedMinutes = roundingMethod(minutes);
return locale.formatDistance("xMinutes", roundedMinutes, localizeOptions);
// 1 up to 24 hours
} else if (unit === "hour") {
const hours = roundingMethod(minutes / 60);
return locale.formatDistance("xHours", hours, localizeOptions);
// 1 up to 30 days
} else if (unit === "day") {
const days = roundingMethod(dstNormalizedMinutes / minutesInDay);
return locale.formatDistance("xDays", days, localizeOptions);
// 1 up to 12 months
} else if (unit === "month") {
const months = roundingMethod(dstNormalizedMinutes / minutesInMonth);
return months === 12 && defaultUnit !== "month"
? locale.formatDistance("xYears", 1, localizeOptions)
: locale.formatDistance("xMonths", months, localizeOptions);
// 1 year up to max Date
} else {
const years = roundingMethod(dstNormalizedMinutes / minutesInYear);
return locale.formatDistance("xYears", years, localizeOptions);
}
}
// Fallback for modularized imports:
export default formatDistanceStrict;
+95
View File
@@ -0,0 +1,95 @@
import { constructNow } from "./constructNow.js";
import { formatDistance } from "./formatDistance.js";
/**
* The {@link formatDistanceToNow} function options.
*/
/**
* @name formatDistanceToNow
* @category Common Helpers
* @summary Return the distance between the given date and now in words.
* @pure false
*
* @description
* Return the distance between the given date and now in words.
*
* | Distance to now | Result |
* |-------------------------------------------------------------------|---------------------|
* | 0 ... 30 secs | less than a minute |
* | 30 secs ... 1 min 30 secs | 1 minute |
* | 1 min 30 secs ... 44 mins 30 secs | [2..44] minutes |
* | 44 mins ... 30 secs ... 89 mins 30 secs | about 1 hour |
* | 89 mins 30 secs ... 23 hrs 59 mins 30 secs | about [2..24] hours |
* | 23 hrs 59 mins 30 secs ... 41 hrs 59 mins 30 secs | 1 day |
* | 41 hrs 59 mins 30 secs ... 29 days 23 hrs 59 mins 30 secs | [2..30] days |
* | 29 days 23 hrs 59 mins 30 secs ... 44 days 23 hrs 59 mins 30 secs | about 1 month |
* | 44 days 23 hrs 59 mins 30 secs ... 59 days 23 hrs 59 mins 30 secs | about 2 months |
* | 59 days 23 hrs 59 mins 30 secs ... 1 yr | [2..12] months |
* | 1 yr ... 1 yr 3 months | about 1 year |
* | 1 yr 3 months ... 1 yr 9 month s | over 1 year |
* | 1 yr 9 months ... 2 yrs | almost 2 years |
* | N yrs ... N yrs 3 months | about N years |
* | N yrs 3 months ... N yrs 9 months | over N years |
* | N yrs 9 months ... N+1 yrs | almost N+1 years |
*
* With `options.includeSeconds == true`:
* | Distance to now | Result |
* |---------------------|----------------------|
* | 0 secs ... 5 secs | less than 5 seconds |
* | 5 secs ... 10 secs | less than 10 seconds |
* | 10 secs ... 20 secs | less than 20 seconds |
* | 20 secs ... 40 secs | half a minute |
* | 40 secs ... 60 secs | less than a minute |
* | 60 secs ... 90 secs | 1 minute |
*
* @param date - The given date
* @param options - The object with options
*
* @returns The distance in words
*
* @throws `date` must not be Invalid Date
* @throws `options.locale` must contain `formatDistance` property
*
* @example
* // If today is 1 January 2015, what is the distance to 2 July 2014?
* const result = formatDistanceToNow(
* new Date(2014, 6, 2)
* )
* //=> '6 months'
*
* @example
* // If now is 1 January 2015 00:00:00,
* // what is the distance to 1 January 2015 00:00:15, including seconds?
* const result = formatDistanceToNow(
* new Date(2015, 0, 1, 0, 0, 15),
* {includeSeconds: true}
* )
* //=> 'less than 20 seconds'
*
* @example
* // If today is 1 January 2015,
* // what is the distance to 1 January 2016, with a suffix?
* const result = formatDistanceToNow(
* new Date(2016, 0, 1),
* {addSuffix: true}
* )
* //=> 'in about 1 year'
*
* @example
* // If today is 1 January 2015,
* // what is the distance to 1 August 2016 in Esperanto?
* const eoLocale = require('date-fns/locale/eo')
* const result = formatDistanceToNow(
* new Date(2016, 7, 1),
* {locale: eoLocale}
* )
* //=> 'pli ol 1 jaro'
*/
export function formatDistanceToNow(date, options) {
return formatDistance(date, constructNow(date), options);
}
// Fallback for modularized imports:
export default formatDistanceToNow;
+85
View File
@@ -0,0 +1,85 @@
import { constructNow } from "./constructNow.js";
import { formatDistanceStrict } from "./formatDistanceStrict.js";
/**
* The {@link formatDistanceToNowStrict} function options.
*/
/**
* @name formatDistanceToNowStrict
* @category Common Helpers
* @summary Return the distance between the given date and now in words.
* @pure false
*
* @description
* Return the distance between the given dates in words, using strict units.
* This is like `formatDistance`, but does not use helpers like 'almost', 'over',
* 'less than' and the like.
*
* | Distance between dates | Result |
* |------------------------|---------------------|
* | 0 ... 59 secs | [0..59] seconds |
* | 1 ... 59 mins | [1..59] minutes |
* | 1 ... 23 hrs | [1..23] hours |
* | 1 ... 29 days | [1..29] days |
* | 1 ... 11 months | [1..11] months |
* | 1 ... N years | [1..N] years |
*
* @param date - The given date
* @param options - An object with options.
*
* @returns The distance in words
*
* @throws `date` must not be Invalid Date
* @throws `options.locale` must contain `formatDistance` property
*
* @example
* // If today is 1 January 2015, what is the distance to 2 July 2014?
* const result = formatDistanceToNowStrict(
* new Date(2014, 6, 2)
* )
* //=> '6 months'
*
* @example
* // If now is 1 January 2015 00:00:00,
* // what is the distance to 1 January 2015 00:00:15, including seconds?
* const result = formatDistanceToNowStrict(
* new Date(2015, 0, 1, 0, 0, 15)
* )
* //=> '15 seconds'
*
* @example
* // If today is 1 January 2015,
* // what is the distance to 1 January 2016, with a suffix?
* const result = formatDistanceToNowStrict(
* new Date(2016, 0, 1),
* {addSuffix: true}
* )
* //=> 'in 1 year'
*
* @example
* // If today is 28 January 2015,
* // what is the distance to 1 January 2015, in months, rounded up??
* const result = formatDistanceToNowStrict(new Date(2015, 0, 1), {
* unit: 'month',
* roundingMethod: 'ceil'
* })
* //=> '1 month'
*
* @example
* // If today is 1 January 2015,
* // what is the distance to 1 January 2016 in Esperanto?
* const eoLocale = require('date-fns/locale/eo')
* const result = formatDistanceToNowStrict(
* new Date(2016, 0, 1),
* {locale: eoLocale}
* )
* //=> '1 jaro'
*/
export function formatDistanceToNowStrict(date, options) {
return formatDistanceStrict(date, constructNow(date), options);
}
// Fallback for modularized imports:
export default formatDistanceToNowStrict;
+102
View File
@@ -0,0 +1,102 @@
import { defaultLocale } from "./_lib/defaultLocale.js";
import { getDefaultOptions } from "./_lib/defaultOptions.js";
/**
* The {@link formatDuration} function options.
*/
const defaultFormat = [
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
];
/**
* @name formatDuration
* @category Common Helpers
* @summary Formats a duration in human-readable format
*
* @description
* Return human-readable duration string i.e. "9 months 2 days"
*
* @param duration - The duration to format
* @param options - An object with options.
*
* @returns The formatted date string
*
* @example
* // Format full duration
* formatDuration({
* years: 2,
* months: 9,
* weeks: 1,
* days: 7,
* hours: 5,
* minutes: 9,
* seconds: 30
* })
* //=> '2 years 9 months 1 week 7 days 5 hours 9 minutes 30 seconds'
*
* @example
* // Format partial duration
* formatDuration({ months: 9, days: 2 })
* //=> '9 months 2 days'
*
* @example
* // Customize the format
* formatDuration(
* {
* years: 2,
* months: 9,
* weeks: 1,
* days: 7,
* hours: 5,
* minutes: 9,
* seconds: 30
* },
* { format: ['months', 'weeks'] }
* ) === '9 months 1 week'
*
* @example
* // Customize the zeros presence
* formatDuration({ years: 0, months: 9 })
* //=> '9 months'
* formatDuration({ years: 0, months: 9 }, { zero: true })
* //=> '0 years 9 months'
*
* @example
* // Customize the delimiter
* formatDuration({ years: 2, months: 9, weeks: 3 }, { delimiter: ', ' })
* //=> '2 years, 9 months, 3 weeks'
*/
export function formatDuration(duration, options) {
const defaultOptions = getDefaultOptions();
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
const format = options?.format ?? defaultFormat;
const zero = options?.zero ?? false;
const delimiter = options?.delimiter ?? " ";
if (!locale.formatDistance) {
return "";
}
const result = format
.reduce((acc, unit) => {
const token = `x${unit.replace(/(^.)/, (m) => m.toUpperCase())}`;
const value = duration[unit];
if (value !== undefined && (zero || duration[unit])) {
return acc.concat(locale.formatDistance(token, value));
}
return acc;
}, [])
.join(delimiter);
return result;
}
// Fallback for modularized imports:
export default formatDuration;
+104
View File
@@ -0,0 +1,104 @@
import { addLeadingZeros } from "./_lib/addLeadingZeros.js";
import { toDate } from "./toDate.js";
/**
* The {@link formatISO} function options.
*/
/**
* @name formatISO
* @category Common Helpers
* @summary Format the date according to the ISO 8601 standard (https://support.sas.com/documentation/cdl/en/lrdict/64316/HTML/default/viewer.htm#a003169814.htm).
*
* @description
* Return the formatted date string in ISO 8601 format. Options may be passed to control the parts and notations of the date.
*
* @param date - The original date
* @param options - An object with options.
*
* @returns The formatted date string (in local time zone)
*
* @throws `date` must not be Invalid Date
*
* @example
* // Represent 18 September 2019 in ISO 8601 format (local time zone is UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52))
* //=> '2019-09-18T19:00:52Z'
*
* @example
* // Represent 18 September 2019 in ISO 8601, short format (local time zone is UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { format: 'basic' })
* //=> '20190918T190052'
*
* @example
* // Represent 18 September 2019 in ISO 8601 format, date only:
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'date' })
* //=> '2019-09-18'
*
* @example
* // Represent 18 September 2019 in ISO 8601 format, time only (local time zone is UTC):
* const result = formatISO(new Date(2019, 8, 18, 19, 0, 52), { representation: 'time' })
* //=> '19:00:52Z'
*/
export function formatISO(date, options) {
const date_ = toDate(date, options?.in);
if (isNaN(+date_)) {
throw new RangeError("Invalid time value");
}
const format = options?.format ?? "extended";
const representation = options?.representation ?? "complete";
let result = "";
let tzOffset = "";
const dateDelimiter = format === "extended" ? "-" : "";
const timeDelimiter = format === "extended" ? ":" : "";
// Representation is either 'date' or 'complete'
if (representation !== "time") {
const day = addLeadingZeros(date_.getDate(), 2);
const month = addLeadingZeros(date_.getMonth() + 1, 2);
const year = addLeadingZeros(date_.getFullYear(), 4);
// yyyyMMdd or yyyy-MM-dd.
result = `${year}${dateDelimiter}${month}${dateDelimiter}${day}`;
}
// Representation is either 'time' or 'complete'
if (representation !== "date") {
// Add the timezone.
const offset = date_.getTimezoneOffset();
if (offset !== 0) {
const absoluteOffset = Math.abs(offset);
const hourOffset = addLeadingZeros(Math.trunc(absoluteOffset / 60), 2);
const minuteOffset = addLeadingZeros(absoluteOffset % 60, 2);
// If less than 0, the sign is +, because it is ahead of time.
const sign = offset < 0 ? "+" : "-";
tzOffset = `${sign}${hourOffset}:${minuteOffset}`;
} else {
tzOffset = "Z";
}
const hour = addLeadingZeros(date_.getHours(), 2);
const minute = addLeadingZeros(date_.getMinutes(), 2);
const second = addLeadingZeros(date_.getSeconds(), 2);
// If there's also date, separate it with time with 'T'
const separator = result === "" ? "" : "T";
// Creates a time string consisting of hour, minute, and second, separated by delimiters, if defined.
const time = [hour, minute, second].join(timeDelimiter);
// HHmmss or HH:mm:ss.
result = `${result}${separator}${time}${tzOffset}`;
}
return result;
}
// Fallback for modularized imports:
export default formatISO;
+86
View File
@@ -0,0 +1,86 @@
import { addLeadingZeros } from "./_lib/addLeadingZeros.js";
import { isValid } from "./isValid.js";
import { toDate } from "./toDate.js";
/**
* The {@link formatISO9075} function options.
*/
/**
* @name formatISO9075
* @category Common Helpers
* @summary Format the date according to the ISO 9075 standard (https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_get-format).
*
* @description
* Return the formatted date string in ISO 9075 format. Options may be passed to control the parts and notations of the date.
*
* @param date - The original date
* @param options - An object with options.
*
* @returns The formatted date string
*
* @throws `date` must not be Invalid Date
*
* @example
* // Represent 18 September 2019 in ISO 9075 format:
* const result = formatISO9075(new Date(2019, 8, 18, 19, 0, 52))
* //=> '2019-09-18 19:00:52'
*
* @example
* // Represent 18 September 2019 in ISO 9075, short format:
* const result = formatISO9075(new Date(2019, 8, 18, 19, 0, 52), { format: 'basic' })
* //=> '20190918 190052'
*
* @example
* // Represent 18 September 2019 in ISO 9075 format, date only:
* const result = formatISO9075(new Date(2019, 8, 18, 19, 0, 52), { representation: 'date' })
* //=> '2019-09-18'
*
* @example
* // Represent 18 September 2019 in ISO 9075 format, time only:
* const result = formatISO9075(new Date(2019, 8, 18, 19, 0, 52), { representation: 'time' })
* //=> '19:00:52'
*/
export function formatISO9075(date, options) {
const date_ = toDate(date, options?.in);
if (!isValid(date_)) {
throw new RangeError("Invalid time value");
}
const format = options?.format ?? "extended";
const representation = options?.representation ?? "complete";
let result = "";
const dateDelimiter = format === "extended" ? "-" : "";
const timeDelimiter = format === "extended" ? ":" : "";
// Representation is either 'date' or 'complete'
if (representation !== "time") {
const day = addLeadingZeros(date_.getDate(), 2);
const month = addLeadingZeros(date_.getMonth() + 1, 2);
const year = addLeadingZeros(date_.getFullYear(), 4);
// yyyyMMdd or yyyy-MM-dd.
result = `${year}${dateDelimiter}${month}${dateDelimiter}${day}`;
}
// Representation is either 'time' or 'complete'
if (representation !== "date") {
const hour = addLeadingZeros(date_.getHours(), 2);
const minute = addLeadingZeros(date_.getMinutes(), 2);
const second = addLeadingZeros(date_.getSeconds(), 2);
// If there's also date, separate it with time with a space
const separator = result === "" ? "" : " ";
// HHmmss or HH:mm:ss.
result = `${result}${separator}${hour}${timeDelimiter}${minute}${timeDelimiter}${second}`;
}
return result;
}
// Fallback for modularized imports:
export default formatISO9075;
+39
View File
@@ -0,0 +1,39 @@
/**
* @name formatISODuration
* @category Common Helpers
* @summary Format a duration object according as ISO 8601 duration string
*
* @description
* Format a duration object according to the ISO 8601 duration standard (https://www.digi.com/resources/documentation/digidocs//90001488-13/reference/r_iso_8601_duration_format.htm)
*
* @param duration - The duration to format
*
* @returns The ISO 8601 duration string
*
* @example
* // Format the given duration as ISO 8601 string
* const result = formatISODuration({
* years: 39,
* months: 2,
* days: 20,
* hours: 7,
* minutes: 5,
* seconds: 0
* })
* //=> 'P39Y2M20DT0H0M0S'
*/
export function formatISODuration(duration) {
const {
years = 0,
months = 0,
days = 0,
hours = 0,
minutes = 0,
seconds = 0,
} = duration;
return `P${years}Y${months}M${days}DT${hours}H${minutes}M${seconds}S`;
}
// Fallback for modularized imports:
export default formatISODuration;
+81
View File
@@ -0,0 +1,81 @@
import { addLeadingZeros } from "./_lib/addLeadingZeros.js";
import { isValid } from "./isValid.js";
import { toDate } from "./toDate.js";
/**
* The {@link formatRFC3339} function options.
*/
/**
* @name formatRFC3339
* @category Common Helpers
* @summary Format the date according to the RFC 3339 standard (https://tools.ietf.org/html/rfc3339#section-5.6).
*
* @description
* Return the formatted date string in RFC 3339 format. Options may be passed to control the parts and notations of the date.
*
* @param date - The original date
* @param options - An object with options.
*
* @returns The formatted date string
*
* @throws `date` must not be Invalid Date
*
* @example
* // Represent 18 September 2019 in RFC 3339 format:
* formatRFC3339(new Date(2019, 8, 18, 19, 0, 52))
* //=> '2019-09-18T19:00:52Z'
*
* @example
* // Represent 18 September 2019 in RFC 3339 format, 3 digits of second fraction
* formatRFC3339(new Date(2019, 8, 18, 19, 0, 52, 234), {
* fractionDigits: 3
* })
* //=> '2019-09-18T19:00:52.234Z'
*/
export function formatRFC3339(date, options) {
const date_ = toDate(date, options?.in);
if (!isValid(date_)) {
throw new RangeError("Invalid time value");
}
const fractionDigits = options?.fractionDigits ?? 0;
const day = addLeadingZeros(date_.getDate(), 2);
const month = addLeadingZeros(date_.getMonth() + 1, 2);
const year = date_.getFullYear();
const hour = addLeadingZeros(date_.getHours(), 2);
const minute = addLeadingZeros(date_.getMinutes(), 2);
const second = addLeadingZeros(date_.getSeconds(), 2);
let fractionalSecond = "";
if (fractionDigits > 0) {
const milliseconds = date_.getMilliseconds();
const fractionalSeconds = Math.trunc(
milliseconds * Math.pow(10, fractionDigits - 3),
);
fractionalSecond = "." + addLeadingZeros(fractionalSeconds, fractionDigits);
}
let offset = "";
const tzOffset = date_.getTimezoneOffset();
if (tzOffset !== 0) {
const absoluteOffset = Math.abs(tzOffset);
const hourOffset = addLeadingZeros(Math.trunc(absoluteOffset / 60), 2);
const minuteOffset = addLeadingZeros(absoluteOffset % 60, 2);
// If less than 0, the sign is +, because it is ahead of time.
const sign = tzOffset < 0 ? "+" : "-";
offset = `${sign}${hourOffset}:${minuteOffset}`;
} else {
offset = "Z";
}
return `${year}-${month}-${day}T${hour}:${minute}:${second}${fractionalSecond}${offset}`;
}
// Fallback for modularized imports:
export default formatRFC3339;
+63
View File
@@ -0,0 +1,63 @@
import { addLeadingZeros } from "./_lib/addLeadingZeros.js";
import { isValid } from "./isValid.js";
import { toDate } from "./toDate.js";
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const months = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec",
];
/**
* @name formatRFC7231
* @category Common Helpers
* @summary Format the date according to the RFC 7231 standard (https://tools.ietf.org/html/rfc7231#section-7.1.1.1).
*
* @description
* Return the formatted date string in RFC 7231 format.
* The result will always be in UTC timezone.
*
* @param date - The original date
*
* @returns The formatted date string
*
* @throws `date` must not be Invalid Date
*
* @example
* // Represent 18 September 2019 in RFC 7231 format:
* const result = formatRFC7231(new Date(2019, 8, 18, 19, 0, 52))
* //=> 'Wed, 18 Sep 2019 19:00:52 GMT'
*/
export function formatRFC7231(date) {
const _date = toDate(date);
if (!isValid(_date)) {
throw new RangeError("Invalid time value");
}
const dayName = days[_date.getUTCDay()];
const dayOfMonth = addLeadingZeros(_date.getUTCDate(), 2);
const monthName = months[_date.getUTCMonth()];
const year = _date.getUTCFullYear();
const hour = addLeadingZeros(_date.getUTCHours(), 2);
const minute = addLeadingZeros(_date.getUTCMinutes(), 2);
const second = addLeadingZeros(_date.getUTCSeconds(), 2);
// Result variables.
return `${dayName}, ${dayOfMonth} ${monthName} ${year} ${hour}:${minute}:${second} GMT`;
}
// Fallback for modularized imports:
export default formatRFC7231;
+88
View File
@@ -0,0 +1,88 @@
import { defaultLocale } from "./_lib/defaultLocale.js";
import { getDefaultOptions } from "./_lib/defaultOptions.js";
import { normalizeDates } from "./_lib/normalizeDates.js";
import { differenceInCalendarDays } from "./differenceInCalendarDays.js";
import { format } from "./format.js";
/**
* The {@link formatRelative} function options.
*/
/**
* @name formatRelative
* @category Common Helpers
* @summary Represent the date in words relative to the given base date.
*
* @description
* Represent the date in words relative to the given base date.
*
* | Distance to the base date | Result |
* |---------------------------|---------------------------|
* | Previous 6 days | last Sunday at 04:30 AM |
* | Last day | yesterday at 04:30 AM |
* | Same day | today at 04:30 AM |
* | Next day | tomorrow at 04:30 AM |
* | Next 6 days | Sunday at 04:30 AM |
* | Other | 12/31/2017 |
*
* @param date - The date to format
* @param baseDate - The date to compare with
* @param options - An object with options
*
* @returns The date in words
*
* @throws `date` must not be Invalid Date
* @throws `baseDate` must not be Invalid Date
* @throws `options.locale` must contain `localize` property
* @throws `options.locale` must contain `formatLong` property
* @throws `options.locale` must contain `formatRelative` property
*
* @example
* // Represent the date of 6 days ago in words relative to the given base date. In this example, today is Wednesday
* const result = formatRelative(subDays(new Date(), 6), new Date())
* //=> "last Thursday at 12:45 AM"
*/
export function formatRelative(date, baseDate, options) {
const [date_, baseDate_] = normalizeDates(options?.in, date, baseDate);
const defaultOptions = getDefaultOptions();
const locale = options?.locale ?? defaultOptions.locale ?? defaultLocale;
const weekStartsOn =
options?.weekStartsOn ??
options?.locale?.options?.weekStartsOn ??
defaultOptions.weekStartsOn ??
defaultOptions.locale?.options?.weekStartsOn ??
0;
const diff = differenceInCalendarDays(date_, baseDate_);
if (isNaN(diff)) {
throw new RangeError("Invalid time value");
}
let token;
if (diff < -6) {
token = "other";
} else if (diff < -1) {
token = "lastWeek";
} else if (diff < 0) {
token = "yesterday";
} else if (diff < 1) {
token = "today";
} else if (diff < 2) {
token = "tomorrow";
} else if (diff < 7) {
token = "nextWeek";
} else {
token = "other";
}
const formatStr = locale.formatRelative(token, date_, baseDate_, {
locale,
weekStartsOn,
});
return format(date_, formatStr, { locale, weekStartsOn });
}
// Fallback for modularized imports:
export default formatRelative;
+32
View File
@@ -0,0 +1,32 @@
import { toDate } from "./toDate.js";
/**
* The {@link fromUnixTime} function options.
*/
/**
* @name fromUnixTime
* @category Timestamp Helpers
* @summary Create a date from a Unix timestamp.
*
* @description
* Create a date from a Unix timestamp (in seconds). Decimal values will be discarded.
*
* @param unixTime - The given Unix timestamp (in seconds)
* @param options - An object with options. Allows to pass a context.
*
* @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
*
* @returns The date
*
* @example
* // Create the date 29 February 2012 11:45:05:
* const result = fromUnixTime(1330515905)
* //=> Wed Feb 29 2012 11:45:05
*/
export function fromUnixTime(unixTime, options) {
return toDate(unixTime * 1000, options?.in);
}
// Fallback for modularized imports:
export default fromUnixTime;
+30
View File
@@ -0,0 +1,30 @@
import { toDate } from "./toDate.js";
/**
* The {@link getDate} function options.
*/
/**
* @name getDate
* @category Day Helpers
* @summary Get the day of the month of the given date.
*
* @description
* Get the day of the month of the given date.
*
* @param date - The given date
* @param options - An object with options.
*
* @returns The day of month
*
* @example
* // Which day of the month is 29 February 2012?
* const result = getDate(new Date(2012, 1, 29))
* //=> 29
*/
export function getDate(date, options) {
return toDate(date, options?.in).getDate();
}
// Fallback for modularized imports:
export default getDate;
+30
View File
@@ -0,0 +1,30 @@
import { toDate } from "./toDate.js";
/**
* The {@link getDay} function options.
*/
/**
* @name getDay
* @category Weekday Helpers
* @summary Get the day of the week of the given date.
*
* @description
* Get the day of the week of the given date.
*
* @param date - The given date
* @param options - The options
*
* @returns The day of week, 0 represents Sunday
*
* @example
* // Which day of the week is 29 February 2012?
* const result = getDay(new Date(2012, 1, 29))
* //=> 3
*/
export function getDay(date, options) {
return toDate(date, options?.in).getDay();
}
// Fallback for modularized imports:
export default getDay;
+35
View File
@@ -0,0 +1,35 @@
import { differenceInCalendarDays } from "./differenceInCalendarDays.js";
import { startOfYear } from "./startOfYear.js";
import { toDate } from "./toDate.js";
/**
* The {@link getDayOfYear} function options.
*/
/**
* @name getDayOfYear
* @category Day Helpers
* @summary Get the day of the year of the given date.
*
* @description
* Get the day of the year of the given date.
*
* @param date - The given date
* @param options - The options
*
* @returns The day of year
*
* @example
* // Which day of the year is 2 July 2014?
* const result = getDayOfYear(new Date(2014, 6, 2))
* //=> 183
*/
export function getDayOfYear(date, options) {
const _date = toDate(date, options?.in);
const diff = differenceInCalendarDays(_date, startOfYear(_date));
const dayOfYear = diff + 1;
return dayOfYear;
}
// Fallback for modularized imports:
export default getDayOfYear;
+37
View File
@@ -0,0 +1,37 @@
import { constructFrom } from "./constructFrom.js";
import { toDate } from "./toDate.js";
/**
* The {@link getDaysInMonth} function options.
*/
/**
* @name getDaysInMonth
* @category Month Helpers
* @summary Get the number of days in a month of the given date.
*
* @description
* Get the number of days in a month of the given date, considering the context if provided.
*
* @param date - The given date
* @param options - An object with options
*
* @returns The number of days in a month
*
* @example
* // How many days are in February 2000?
* const result = getDaysInMonth(new Date(2000, 1))
* //=> 29
*/
export function getDaysInMonth(date, options) {
const _date = toDate(date, options?.in);
const year = _date.getFullYear();
const monthIndex = _date.getMonth();
const lastDayOfMonth = constructFrom(_date, 0);
lastDayOfMonth.setFullYear(year, monthIndex + 1, 0);
lastDayOfMonth.setHours(0, 0, 0, 0);
return lastDayOfMonth.getDate();
}
// Fallback for modularized imports:
export default getDaysInMonth;
+33
View File
@@ -0,0 +1,33 @@
import { isLeapYear } from "./isLeapYear.js";
import { toDate } from "./toDate.js";
/**
* The {@link getDaysInYear} function options.
*/
/**
* @name getDaysInYear
* @category Year Helpers
* @summary Get the number of days in a year of the given date.
*
* @description
* Get the number of days in a year of the given date.
*
* @param date - The given date
* @param options - An object with options
*
* @returns The number of days in a year
*
* @example
* // How many days are in 2012?
* const result = getDaysInYear(new Date(2012, 0, 1))
* //=> 366
*/
export function getDaysInYear(date, options) {
const _date = toDate(date, options?.in);
if (Number.isNaN(+_date)) return NaN;
return isLeapYear(_date) ? 366 : 365;
}
// Fallback for modularized imports:
export default getDaysInYear;
+36
View File
@@ -0,0 +1,36 @@
import { toDate } from "./toDate.js";
/**
* The {@link getDecade} function options.
*/
/**
* @name getDecade
* @category Decade Helpers
* @summary Get the decade of the given date.
*
* @description
* Get the decade of the given date.
*
* @param date - The given date
* @param options - An object with options
*
* @returns The year of decade
*
* @example
* // Which decade belongs 27 November 1942?
* const result = getDecade(new Date(1942, 10, 27))
* //=> 1940
*/
export function getDecade(date, options) {
// TODO: Switch to more technical definition in of decades that start with 1
// end with 0. I.e. 2001-2010 instead of current 2000-2009. It's a breaking
// change, so it can only be done in 4.0.
const _date = toDate(date, options?.in);
const year = _date.getFullYear();
const decade = Math.floor(year / 10) * 10;
return decade;
}
// Fallback for modularized imports:
export default getDecade;
+32
View File
@@ -0,0 +1,32 @@
import { getDefaultOptions as getInternalDefaultOptions } from "./_lib/defaultOptions.js";
/**
* @name getDefaultOptions
* @category Common Helpers
* @summary Get default options.
* @pure false
*
* @description
* Returns an object that contains defaults for
* `options.locale`, `options.weekStartsOn` and `options.firstWeekContainsDate`
* arguments for all functions.
*
* You can change these with [setDefaultOptions](https://date-fns.org/docs/setDefaultOptions).
*
* @returns The default options
*
* @example
* const result = getDefaultOptions()
* //=> {}
*
* @example
* setDefaultOptions({ weekStarsOn: 1, firstWeekContainsDate: 4 })
* const result = getDefaultOptions()
* //=> { weekStarsOn: 1, firstWeekContainsDate: 4 }
*/
export function getDefaultOptions() {
return Object.assign({}, getInternalDefaultOptions());
}
// Fallback for modularized imports:
export default getDefaultOptions;
+30
View File
@@ -0,0 +1,30 @@
import { toDate } from "./toDate.js";
/**
* The {@link getHours} function options.
*/
/**
* @name getHours
* @category Hour Helpers
* @summary Get the hours of the given date.
*
* @description
* Get the hours of the given date.
*
* @param date - The given date
* @param options - An object with options
*
* @returns The hours
*
* @example
* // Get the hours of 29 February 2012 11:45:00:
* const result = getHours(new Date(2012, 1, 29, 11, 45))
* //=> 11
*/
export function getHours(date, options) {
return toDate(date, options?.in).getHours();
}
// Fallback for modularized imports:
export default getHours;
+34
View File
@@ -0,0 +1,34 @@
import { toDate } from "./toDate.js";
/**
* The {@link getISODay} function options.
*/
/**
* @name getISODay
* @category Weekday Helpers
* @summary Get the day of the ISO week of the given date.
*
* @description
* Get the day of the ISO week of the given date,
* which is 7 for Sunday, 1 for Monday etc.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param date - The given date
* @param options - An object with options
*
* @returns The day of ISO week
*
* @example
* // Which day of the ISO week is 26 February 2012?
* const result = getISODay(new Date(2012, 1, 26))
* //=> 7
*/
export function getISODay(date, options) {
const day = toDate(date, options?.in).getDay();
return day === 0 ? 7 : day;
}
// Fallback for modularized imports:
export default getISODay;
+41
View File
@@ -0,0 +1,41 @@
import { millisecondsInWeek } from "./constants.js";
import { startOfISOWeek } from "./startOfISOWeek.js";
import { startOfISOWeekYear } from "./startOfISOWeekYear.js";
import { toDate } from "./toDate.js";
/**
* The {@link getISOWeek} function options.
*/
/**
* @name getISOWeek
* @category ISO Week Helpers
* @summary Get the ISO week of the given date.
*
* @description
* Get the ISO week of the given date.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param date - The given date
* @param options - The options
*
* @returns The ISO week
*
* @example
* // Which week of the ISO-week numbering year is 2 January 2005?
* const result = getISOWeek(new Date(2005, 0, 2))
* //=> 53
*/
export function getISOWeek(date, options) {
const _date = toDate(date, options?.in);
const diff = +startOfISOWeek(_date) - +startOfISOWeekYear(_date);
// Round the number of weeks to the nearest integer because the number of
// milliseconds in a week is not constant (e.g. it's different in the week of
// the daylight saving time clock shift).
return Math.round(diff / millisecondsInWeek) + 1;
}
// Fallback for modularized imports:
export default getISOWeek;
+53
View File
@@ -0,0 +1,53 @@
import { constructFrom } from "./constructFrom.js";
import { startOfISOWeek } from "./startOfISOWeek.js";
import { toDate } from "./toDate.js";
/**
* The {@link getISOWeekYear} function options.
*/
/**
* @name getISOWeekYear
* @category ISO Week-Numbering Year Helpers
* @summary Get the ISO week-numbering year of the given date.
*
* @description
* Get the ISO week-numbering year of the given date,
* which always starts 3 days before the year's first Thursday.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param date - The given date
*
* @returns The ISO week-numbering year
*
* @example
* // Which ISO-week numbering year is 2 January 2005?
* const result = getISOWeekYear(new Date(2005, 0, 2))
* //=> 2004
*/
export function getISOWeekYear(date, options) {
const _date = toDate(date, options?.in);
const year = _date.getFullYear();
const fourthOfJanuaryOfNextYear = constructFrom(_date, 0);
fourthOfJanuaryOfNextYear.setFullYear(year + 1, 0, 4);
fourthOfJanuaryOfNextYear.setHours(0, 0, 0, 0);
const startOfNextYear = startOfISOWeek(fourthOfJanuaryOfNextYear);
const fourthOfJanuaryOfThisYear = constructFrom(_date, 0);
fourthOfJanuaryOfThisYear.setFullYear(year, 0, 4);
fourthOfJanuaryOfThisYear.setHours(0, 0, 0, 0);
const startOfThisYear = startOfISOWeek(fourthOfJanuaryOfThisYear);
if (_date.getTime() >= startOfNextYear.getTime()) {
return year + 1;
} else if (_date.getTime() >= startOfThisYear.getTime()) {
return year;
} else {
return year - 1;
}
}
// Fallback for modularized imports:
export default getISOWeekYear;
+41
View File
@@ -0,0 +1,41 @@
import { addWeeks } from "./addWeeks.js";
import { millisecondsInWeek } from "./constants.js";
import { startOfISOWeekYear } from "./startOfISOWeekYear.js";
/**
* The {@link getISOWeeksInYear} function options.
*/
/**
* @name getISOWeeksInYear
* @category ISO Week-Numbering Year Helpers
* @summary Get the number of weeks in an ISO week-numbering year of the given date.
*
* @description
* Get the number of weeks in an ISO week-numbering year of the given date.
*
* ISO week-numbering year: http://en.wikipedia.org/wiki/ISO_week_date
*
* @param date - The given date
* @param options - An object with options
*
* @returns The number of ISO weeks in a year
*
* @example
* // How many weeks are in ISO week-numbering year 2015?
* const result = getISOWeeksInYear(new Date(2015, 1, 11))
* //=> 53
*/
export function getISOWeeksInYear(date, options) {
const thisYear = startOfISOWeekYear(date, options);
const nextYear = startOfISOWeekYear(addWeeks(thisYear, 60));
const diff = +nextYear - +thisYear;
// Round the number of weeks to the nearest integer because the number of
// milliseconds in a week is not constant (e.g. it's different in the week of
// the daylight saving time clock shift).
return Math.round(diff / millisecondsInWeek);
}
// Fallback for modularized imports:
export default getISOWeeksInYear;

Some files were not shown because too many files have changed in this diff Show More