@formkit/tempo 0.0.18 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/addDay.d.ts +9 -0
- package/dist/addDay.mjs +11 -0
- package/dist/addDay.mjs.map +1 -0
- package/dist/addHour.d.ts +9 -0
- package/dist/addHour.mjs +11 -0
- package/dist/addHour.mjs.map +1 -0
- package/dist/addMinute.d.ts +9 -0
- package/dist/addMinute.mjs +11 -0
- package/dist/addMinute.mjs.map +1 -0
- package/dist/addMonth.d.ts +13 -0
- package/dist/addMonth.mjs +19 -0
- package/dist/addMonth.mjs.map +1 -0
- package/dist/addSecond.d.ts +9 -0
- package/dist/addSecond.mjs +11 -0
- package/dist/addSecond.mjs.map +1 -0
- package/dist/addYear.d.ts +13 -0
- package/dist/addYear.mjs +19 -0
- package/dist/addYear.mjs.map +1 -0
- package/dist/ap.d.ts +8 -0
- package/dist/ap.mjs +28 -0
- package/dist/ap.mjs.map +1 -0
- package/dist/applyOffset.d.ts +11 -0
- package/dist/applyOffset.mjs +20 -0
- package/dist/applyOffset.mjs.map +1 -0
- package/dist/bundle.mjs +1215 -0
- package/dist/bundle.mjs.map +1 -0
- package/dist/common.d.ts +137 -0
- package/dist/common.mjs +252 -0
- package/dist/common.mjs.map +1 -0
- package/dist/date.d.ts +9 -0
- package/dist/date.mjs +28 -0
- package/dist/date.mjs.map +1 -0
- package/dist/dayEnd.d.ts +9 -0
- package/dist/dayEnd.mjs +11 -0
- package/dist/dayEnd.mjs.map +1 -0
- package/dist/dayOfYear.d.ts +10 -0
- package/dist/dayOfYear.mjs +12 -0
- package/dist/dayOfYear.mjs.map +1 -0
- package/dist/dayStart.d.ts +9 -0
- package/dist/dayStart.mjs +11 -0
- package/dist/dayStart.mjs.map +1 -0
- package/dist/deviceLocale.d.ts +7 -0
- package/dist/deviceLocale.mjs +8 -0
- package/dist/deviceLocale.mjs.map +1 -0
- package/dist/deviceTZ.d.ts +8 -0
- package/dist/deviceTZ.mjs +8 -0
- package/dist/deviceTZ.mjs.map +1 -0
- package/dist/diffDays.d.ts +12 -0
- package/dist/diffDays.mjs +14 -0
- package/dist/diffDays.mjs.map +1 -0
- package/dist/diffHours.d.ts +12 -0
- package/dist/diffHours.mjs +14 -0
- package/dist/diffHours.mjs.map +1 -0
- package/dist/diffMilliseconds.d.ts +10 -0
- package/dist/diffMilliseconds.mjs +11 -0
- package/dist/diffMilliseconds.mjs.map +1 -0
- package/dist/diffMinutes.d.ts +11 -0
- package/dist/diffMinutes.mjs +10 -0
- package/dist/diffMinutes.mjs.map +1 -0
- package/dist/diffMonths.d.ts +10 -0
- package/dist/diffMonths.mjs +25 -0
- package/dist/diffMonths.mjs.map +1 -0
- package/dist/diffRound.d.ts +9 -0
- package/dist/diffRound.mjs +9 -0
- package/dist/diffRound.mjs.map +1 -0
- package/dist/diffSeconds.d.ts +12 -0
- package/dist/diffSeconds.mjs +10 -0
- package/dist/diffSeconds.mjs.map +1 -0
- package/dist/diffWeeks.d.ts +12 -0
- package/dist/diffWeeks.mjs +14 -0
- package/dist/diffWeeks.mjs.map +1 -0
- package/dist/diffYears.d.ts +10 -0
- package/dist/diffYears.mjs +10 -0
- package/dist/diffYears.mjs.map +1 -0
- package/dist/format.d.ts +36 -0
- package/dist/format.mjs +48 -0
- package/dist/format.mjs.map +1 -0
- package/dist/formatStr.d.ts +13 -0
- package/dist/formatStr.mjs +13 -0
- package/dist/formatStr.mjs.map +1 -0
- package/dist/fourDigitYear.d.ts +10 -0
- package/dist/fourDigitYear.mjs +12 -0
- package/dist/fourDigitYear.mjs.map +1 -0
- package/dist/hourEnd.d.ts +9 -0
- package/dist/hourEnd.mjs +11 -0
- package/dist/hourEnd.mjs.map +1 -0
- package/dist/hourStart.d.ts +9 -0
- package/dist/hourStart.mjs +11 -0
- package/dist/hourStart.mjs.map +1 -0
- package/dist/index.cjs +140 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +75 -4
- package/dist/index.d.ts +54 -498
- package/dist/index.mjs +62 -1057
- package/dist/index.mjs.map +1 -1
- package/dist/isAfter.d.ts +18 -0
- package/dist/isAfter.mjs +11 -0
- package/dist/isAfter.mjs.map +1 -0
- package/dist/isBefore.d.ts +13 -0
- package/dist/isBefore.mjs +11 -0
- package/dist/isBefore.mjs.map +1 -0
- package/dist/isEqual.d.ts +13 -0
- package/dist/isEqual.mjs +11 -0
- package/dist/isEqual.mjs.map +1 -0
- package/dist/iso8601.d.ts +13 -0
- package/dist/iso8601.mjs +27 -0
- package/dist/iso8601.mjs.map +1 -0
- package/dist/minuteEnd.d.ts +9 -0
- package/dist/minuteEnd.mjs +11 -0
- package/dist/minuteEnd.mjs.map +1 -0
- package/dist/minuteStart.d.ts +9 -0
- package/dist/minuteStart.mjs +11 -0
- package/dist/minuteStart.mjs.map +1 -0
- package/dist/monthDays.d.ts +9 -0
- package/dist/monthDays.mjs +10 -0
- package/dist/monthDays.mjs.map +1 -0
- package/dist/monthEnd.d.ts +10 -0
- package/dist/monthEnd.mjs +13 -0
- package/dist/monthEnd.mjs.map +1 -0
- package/dist/monthStart.d.ts +9 -0
- package/dist/monthStart.mjs +12 -0
- package/dist/monthStart.mjs.map +1 -0
- package/dist/nearestDay.d.ts +12 -0
- package/dist/nearestDay.mjs +46 -0
- package/dist/nearestDay.mjs.map +1 -0
- package/dist/offset.d.ts +14 -0
- package/dist/offset.mjs +36 -0
- package/dist/offset.mjs.map +1 -0
- package/dist/parse.d.ts +13 -0
- package/dist/parse.mjs +163 -0
- package/dist/parse.mjs.map +1 -0
- package/dist/parts.d.ts +12 -0
- package/dist/parts.mjs +214 -0
- package/dist/parts.mjs.map +1 -0
- package/dist/range.d.ts +10 -0
- package/dist/range.mjs +50 -0
- package/dist/range.mjs.map +1 -0
- package/dist/removeOffset.d.ts +10 -0
- package/dist/removeOffset.mjs +13 -0
- package/dist/removeOffset.mjs.map +1 -0
- package/dist/sameDay.d.ts +10 -0
- package/dist/sameDay.mjs +11 -0
- package/dist/sameDay.mjs.map +1 -0
- package/dist/sameHour.d.ts +10 -0
- package/dist/sameHour.mjs +11 -0
- package/dist/sameHour.mjs.map +1 -0
- package/dist/sameMinute.d.ts +10 -0
- package/dist/sameMinute.mjs +11 -0
- package/dist/sameMinute.mjs.map +1 -0
- package/dist/sameSecond.d.ts +10 -0
- package/dist/sameSecond.mjs +11 -0
- package/dist/sameSecond.mjs.map +1 -0
- package/dist/sameYear.d.ts +10 -0
- package/dist/sameYear.mjs +11 -0
- package/dist/sameYear.mjs.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.mjs +1 -0
- package/dist/types.mjs.map +1 -0
- package/dist/tzDate.d.ts +15 -0
- package/dist/tzDate.mjs +12 -0
- package/dist/tzDate.mjs.map +1 -0
- package/dist/weekEnd.d.ts +12 -0
- package/dist/weekEnd.mjs +12 -0
- package/dist/weekEnd.mjs.map +1 -0
- package/dist/weekStart.d.ts +12 -0
- package/dist/weekStart.mjs +15 -0
- package/dist/weekStart.mjs.map +1 -0
- package/dist/yearDays.d.ts +9 -0
- package/dist/yearDays.mjs +10 -0
- package/dist/yearDays.mjs.map +1 -0
- package/dist/yearEnd.d.ts +9 -0
- package/dist/yearEnd.mjs +13 -0
- package/dist/yearEnd.mjs.map +1 -0
- package/dist/yearStart.d.ts +9 -0
- package/dist/yearStart.mjs +13 -0
- package/dist/yearStart.mjs.map +1 -0
- package/package.json +8 -1
package/dist/offset.mjs
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// src/offset.ts
|
|
2
|
+
import { date } from "./date.mjs";
|
|
3
|
+
import { normStr, minsToOffset } from "./common.mjs";
|
|
4
|
+
import { deviceTZ } from "./deviceTZ.mjs";
|
|
5
|
+
function relativeTime(d, timeZone) {
|
|
6
|
+
const utcParts = new Intl.DateTimeFormat("en-US", {
|
|
7
|
+
year: "numeric",
|
|
8
|
+
month: "2-digit",
|
|
9
|
+
day: "2-digit",
|
|
10
|
+
hour: "2-digit",
|
|
11
|
+
minute: "2-digit",
|
|
12
|
+
second: "2-digit",
|
|
13
|
+
timeZone,
|
|
14
|
+
hourCycle: "h23"
|
|
15
|
+
}).formatToParts(d).map(normStr);
|
|
16
|
+
const parts = {};
|
|
17
|
+
utcParts.forEach((part) => {
|
|
18
|
+
parts[part.type] = part.value;
|
|
19
|
+
});
|
|
20
|
+
return /* @__PURE__ */ new Date(
|
|
21
|
+
`${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}Z`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
function offset(utcTime, tzA = "UTC", tzB = "device", timeZoneToken = "Z") {
|
|
25
|
+
var _a;
|
|
26
|
+
tzB = tzB === "device" ? (_a = deviceTZ()) != null ? _a : "utc" : tzB;
|
|
27
|
+
const d = date(utcTime);
|
|
28
|
+
const timeA = relativeTime(d, tzA);
|
|
29
|
+
const timeB = relativeTime(d, tzB);
|
|
30
|
+
const timeDiffInMins = (timeB.getTime() - timeA.getTime()) / 1e3 / 60;
|
|
31
|
+
return minsToOffset(timeDiffInMins, timeZoneToken);
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
offset
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=offset.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/offset.ts"],"sourcesContent":["import { date } from \"./date\"\nimport { normStr, minsToOffset, TimezoneToken } from \"./common\"\nimport { deviceTZ } from \"./deviceTZ\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Converts a date object from one timezone to that same time in UTC. This is\n * only for internal use.\n * @param d - A Date object\n * @param timeZone - A timezone string\n */\nfunction relativeTime(d: Date, timeZone: string): Date {\n const utcParts = new Intl.DateTimeFormat(\"en-US\", {\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n timeZone,\n hourCycle: \"h23\",\n })\n .formatToParts(d)\n .map(normStr)\n const parts: {\n year?: string\n month?: string\n day?: string\n hour?: string\n minute?: string\n second?: string\n } = {}\n utcParts.forEach((part) => {\n parts[part.type as keyof typeof parts] = part.value\n })\n return new Date(\n `${parts.year}-${parts.month}-${parts.day}T${parts.hour}:${parts.minute}:${parts.second}Z`\n )\n}\n\n/**\n * Returns the offset between two timezones on a given date. The results are\n * ISO8601 compatible offsets like -0800 or +0530.\n *\n * @param dateInput - The date on which to determine the offset.\n * @param tzA - (default: UTC) The second timezone to compare determine the offset between.\n * @param tzB - (default: device) The first timezone to compare determine the offset between.\n */\nexport function offset(\n utcTime: DateInput,\n tzA = \"UTC\",\n tzB = \"device\",\n timeZoneToken: TimezoneToken = \"Z\" ,\n): string {\n tzB = tzB === \"device\" ? deviceTZ() ?? \"utc\" : tzB\n const d = date(utcTime)\n const timeA = relativeTime(d, tzA)\n const timeB = relativeTime(d, tzB)\n const timeDiffInMins = (timeB.getTime() - timeA.getTime()) / 1000 / 60\n return minsToOffset(timeDiffInMins, timeZoneToken)\n}\n"],"mappings":";AAAA,SAAS,YAAY;AACrB,SAAS,SAAS,oBAAmC;AACrD,SAAS,gBAAgB;AASzB,SAAS,aAAa,GAAS,UAAwB;AACrD,QAAM,WAAW,IAAI,KAAK,eAAe,SAAS;AAAA,IAChD,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR;AAAA,IACA,WAAW;AAAA,EACb,CAAC,EACE,cAAc,CAAC,EACf,IAAI,OAAO;AACd,QAAM,QAOF,CAAC;AACL,WAAS,QAAQ,CAAC,SAAS;AACzB,UAAM,KAAK,IAA0B,IAAI,KAAK;AAAA,EAChD,CAAC;AACD,SAAO,oBAAI;AAAA,IACT,GAAG,MAAM,IAAI,IAAI,MAAM,KAAK,IAAI,MAAM,GAAG,IAAI,MAAM,IAAI,IAAI,MAAM,MAAM,IAAI,MAAM,MAAM;AAAA,EACzF;AACF;AAUO,SAAS,OACd,SACA,MAAM,OACN,MAAM,UACN,gBAA+B,KACvB;AArDV;AAsDE,QAAM,QAAQ,YAAW,cAAS,MAAT,YAAc,QAAQ;AAC/C,QAAM,IAAI,KAAK,OAAO;AACtB,QAAM,QAAQ,aAAa,GAAG,GAAG;AACjC,QAAM,QAAQ,aAAa,GAAG,GAAG;AACjC,QAAM,kBAAkB,MAAM,QAAQ,IAAI,MAAM,QAAQ,KAAK,MAAO;AACpE,SAAO,aAAa,gBAAgB,aAAa;AACnD;","names":[]}
|
package/dist/parse.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ParseOptions, Format, Part, FilledPart } from './types.js';
|
|
2
|
+
|
|
3
|
+
declare function parse(options: ParseOptions): Date | never;
|
|
4
|
+
declare function parse(dateStr: string, format?: Format, locale?: string): Date | never;
|
|
5
|
+
/**
|
|
6
|
+
* Given a string date and corresponding format parts, fill the parts with the
|
|
7
|
+
* data from the string.
|
|
8
|
+
* @param dateStr - A string to parse.
|
|
9
|
+
* @param formatParts - The expected parts of the given string.
|
|
10
|
+
*/
|
|
11
|
+
declare function parseParts(dateStr: string, formatParts: Part[]): FilledPart[];
|
|
12
|
+
|
|
13
|
+
export { parse, parseParts };
|
package/dist/parse.mjs
ADDED
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
// src/parse.ts
|
|
2
|
+
import { date } from "./date.mjs";
|
|
3
|
+
import { validate, styles, fixedLength, four, two, validOffset, fixedLengthByOffset } from "./common.mjs";
|
|
4
|
+
import { formatStr } from "./formatStr.mjs";
|
|
5
|
+
import { fourDigitYear } from "./fourDigitYear.mjs";
|
|
6
|
+
import { ap } from "./ap.mjs";
|
|
7
|
+
import { range } from "./range.mjs";
|
|
8
|
+
import { monthDays } from "./monthDays.mjs";
|
|
9
|
+
import { parts } from "./parts.mjs";
|
|
10
|
+
function parse(dateStrOrOptions, format = "ISO8601", locale = "device") {
|
|
11
|
+
let partFilter = () => true;
|
|
12
|
+
let dateStr;
|
|
13
|
+
let dateOverflow = "backward";
|
|
14
|
+
if (typeof dateStrOrOptions === "object") {
|
|
15
|
+
;
|
|
16
|
+
({
|
|
17
|
+
date: dateStr,
|
|
18
|
+
format = "ISO8601",
|
|
19
|
+
locale = "device",
|
|
20
|
+
dateOverflow = "backward",
|
|
21
|
+
partFilter = () => true
|
|
22
|
+
} = dateStrOrOptions);
|
|
23
|
+
} else {
|
|
24
|
+
dateStr = dateStrOrOptions;
|
|
25
|
+
}
|
|
26
|
+
if (!dateStr)
|
|
27
|
+
throw new Error("parse() requires a date string.");
|
|
28
|
+
const invalid = () => {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Date (${dateStr}) does not match format (${formatStr(format, locale)})`
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
if (format === "ISO8601")
|
|
34
|
+
return date(dateStr);
|
|
35
|
+
const genitive = styles.includes(format) || typeof format === "object";
|
|
36
|
+
const formatParts = validate(parts(format, locale).filter(partFilter));
|
|
37
|
+
if (!formatParts.length)
|
|
38
|
+
throw new Error("parse() requires a pattern.");
|
|
39
|
+
let parsedParts;
|
|
40
|
+
try {
|
|
41
|
+
parsedParts = parseParts(dateStr, formatParts);
|
|
42
|
+
} catch {
|
|
43
|
+
return invalid();
|
|
44
|
+
}
|
|
45
|
+
const now = /* @__PURE__ */ new Date();
|
|
46
|
+
const parsed = /* @__PURE__ */ new Map([
|
|
47
|
+
["YYYY", now.getFullYear()],
|
|
48
|
+
["MM", now.getMonth() + 1],
|
|
49
|
+
["DD", now.getDate()],
|
|
50
|
+
["HH", 0],
|
|
51
|
+
["mm", 0],
|
|
52
|
+
["ss", 0]
|
|
53
|
+
]);
|
|
54
|
+
let a = null;
|
|
55
|
+
let offset = "";
|
|
56
|
+
parsedParts.forEach((part) => {
|
|
57
|
+
if (part.partName === "literal")
|
|
58
|
+
return;
|
|
59
|
+
if (part.token === part.value)
|
|
60
|
+
return invalid();
|
|
61
|
+
const v = Number(part.value);
|
|
62
|
+
if (parsed.has(part.token)) {
|
|
63
|
+
parsed.set(part.token, v);
|
|
64
|
+
} else if (part.token === "YY") {
|
|
65
|
+
parsed.set("YYYY", fourDigitYear(part.value));
|
|
66
|
+
} else {
|
|
67
|
+
const t = part.token;
|
|
68
|
+
if (t.startsWith("d")) {
|
|
69
|
+
return;
|
|
70
|
+
} else if (t === "D") {
|
|
71
|
+
parsed.set("DD", v);
|
|
72
|
+
} else if (t === "H" || t.startsWith("h")) {
|
|
73
|
+
parsed.set("HH", v);
|
|
74
|
+
} else if (t === "M") {
|
|
75
|
+
parsed.set("MM", v);
|
|
76
|
+
} else if (t === "a" || t === "A") {
|
|
77
|
+
a = part.value.toLowerCase() === ap("am", locale).toLowerCase();
|
|
78
|
+
} else if (t === "Z" || t === "ZZ") {
|
|
79
|
+
offset = validOffset(part.value, t);
|
|
80
|
+
} else {
|
|
81
|
+
const values = range(t, locale, genitive);
|
|
82
|
+
const index = values.indexOf(part.value);
|
|
83
|
+
if (index !== -1) {
|
|
84
|
+
switch (t) {
|
|
85
|
+
case "MMM":
|
|
86
|
+
case "MMMM":
|
|
87
|
+
parsed.set("MM", index + 1);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
let hours = parsed.get("HH") || 0;
|
|
95
|
+
if (a === false) {
|
|
96
|
+
hours += hours === 12 ? 0 : 12;
|
|
97
|
+
parsed.set("HH", hours === 24 ? 0 : hours);
|
|
98
|
+
} else if (a === true && hours === 12) {
|
|
99
|
+
parsed.set("HH", 0);
|
|
100
|
+
}
|
|
101
|
+
parsed.set("MM", (parsed.get("MM") || 1) - 1);
|
|
102
|
+
let [Y, M, D, h, m, s] = Array.from(parsed.values());
|
|
103
|
+
const maxDaysInMonth = monthDays(/* @__PURE__ */ new Date(`${four(Y)}-${two(M + 1)}-10`));
|
|
104
|
+
if (maxDaysInMonth < D && dateOverflow === "throw")
|
|
105
|
+
throw new Error(`Invalid date ${four(Y)}-${two(M + 1)}-${two(D)}`);
|
|
106
|
+
D = dateOverflow === "backward" ? Math.min(D, maxDaysInMonth) : D;
|
|
107
|
+
const isoString = `${four(Y)}-${two(M + 1)}-${two(D)}T${two(h)}:${two(
|
|
108
|
+
m
|
|
109
|
+
)}:${two(s)}${offset}`;
|
|
110
|
+
const d = new Date(isoString);
|
|
111
|
+
if (isFinite(+d))
|
|
112
|
+
return d;
|
|
113
|
+
return invalid();
|
|
114
|
+
}
|
|
115
|
+
function parseParts(dateStr, formatParts) {
|
|
116
|
+
let i = 0;
|
|
117
|
+
const advance = (parts2) => [
|
|
118
|
+
parts2[i++],
|
|
119
|
+
parts2[i]
|
|
120
|
+
];
|
|
121
|
+
let pos = 0;
|
|
122
|
+
const parsed = [];
|
|
123
|
+
let n = void 0;
|
|
124
|
+
do {
|
|
125
|
+
const [current, next] = advance(formatParts);
|
|
126
|
+
n = next;
|
|
127
|
+
let len = 1;
|
|
128
|
+
if (current.partName === "literal") {
|
|
129
|
+
len = current.partValue.length;
|
|
130
|
+
} else if (current.partName === "timeZoneName") {
|
|
131
|
+
len = fixedLengthByOffset(dateStr.substring(pos));
|
|
132
|
+
} else if (current.token in fixedLength) {
|
|
133
|
+
len = fixedLength[current.token];
|
|
134
|
+
} else if (next) {
|
|
135
|
+
if (next.partName === "literal") {
|
|
136
|
+
len = dateStr.indexOf(next.partValue, pos) - pos;
|
|
137
|
+
if (len < 0)
|
|
138
|
+
throw new Error();
|
|
139
|
+
} else if (next.partName === "dayPeriod") {
|
|
140
|
+
for (let i2 = 1; i2 <= 4; i2++) {
|
|
141
|
+
if (isNaN(Number(dateStr.charAt(pos + i2)))) {
|
|
142
|
+
len = i2;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} else {
|
|
147
|
+
const nextChar = dateStr.substring(pos).search(/\d/);
|
|
148
|
+
if (nextChar !== -1)
|
|
149
|
+
len = pos + nextChar;
|
|
150
|
+
}
|
|
151
|
+
} else {
|
|
152
|
+
len = dateStr.length;
|
|
153
|
+
}
|
|
154
|
+
parsed.push({ ...current, value: dateStr.substring(pos, pos + len) });
|
|
155
|
+
pos += len;
|
|
156
|
+
} while (n);
|
|
157
|
+
return parsed;
|
|
158
|
+
}
|
|
159
|
+
export {
|
|
160
|
+
parse,
|
|
161
|
+
parseParts
|
|
162
|
+
};
|
|
163
|
+
//# sourceMappingURL=parse.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parse.ts"],"sourcesContent":["import { date } from \"./date\"\nimport { validate, styles, fixedLength, four, two, validOffset, fixedLengthByOffset } from \"./common\"\nimport { formatStr } from \"./formatStr\"\nimport { fourDigitYear } from \"./fourDigitYear\"\nimport { ap } from \"./ap\"\nimport { range } from \"./range\"\nimport { monthDays } from \"./monthDays\"\nimport { parts } from \"./parts\"\nimport type {\n ParseOptions,\n Format,\n Part,\n FormatStyle,\n FilledPart,\n FormatToken,\n} from \"./types\"\n\nexport function parse(options: ParseOptions): Date | never\nexport function parse(\n dateStr: string,\n format?: Format,\n locale?: string\n): Date | never\n/**\n * Parses a date string into a Date object using the given format.\n * @param dateStr - A string representing a date.\n * @param format - The format the given string is in.\n * @param locale - The locale to parse the string from.\n */\nexport function parse(\n dateStrOrOptions: string | ParseOptions,\n format: Format = \"ISO8601\",\n locale = \"device\"\n): Date | never {\n let partFilter: (part: Part) => boolean = () => true\n let dateStr: string\n let dateOverflow = \"backward\"\n if (typeof dateStrOrOptions === \"object\") {\n ;({\n date: dateStr,\n format = \"ISO8601\",\n locale = \"device\",\n dateOverflow = \"backward\",\n partFilter = () => true,\n } = dateStrOrOptions)\n } else {\n dateStr = dateStrOrOptions\n }\n if (!dateStr) throw new Error(\"parse() requires a date string.\")\n const invalid = (): never => {\n throw new Error(\n `Date (${dateStr}) does not match format (${formatStr(format, locale)})`\n )\n }\n if (format === \"ISO8601\") return date(dateStr)\n const genitive =\n styles.includes(format as FormatStyle) || typeof format === \"object\"\n const formatParts = validate(parts(format, locale).filter(partFilter))\n if (!formatParts.length) throw new Error(\"parse() requires a pattern.\")\n let parsedParts\n try {\n parsedParts = parseParts(dateStr, formatParts)\n } catch {\n return invalid()\n }\n const now = new Date()\n const parsed = new Map([\n [\"YYYY\", now.getFullYear()],\n [\"MM\", now.getMonth() + 1],\n [\"DD\", now.getDate()],\n [\"HH\", 0],\n [\"mm\", 0],\n [\"ss\", 0],\n ])\n let a: null | boolean = null\n let offset = \"\"\n parsedParts.forEach((part): void | never => {\n if (part.partName === \"literal\") return\n if (part.token === part.value) return invalid()\n const v = Number(part.value)\n if (parsed.has(part.token)) {\n // Parse for YYYY, MM, DD, HH, hh, mm, ss, Z\n parsed.set(part.token, v)\n } else if (part.token === \"YY\") {\n // Parse for YY\n parsed.set(\"YYYY\", fourDigitYear(part.value))\n } else {\n /* MMM - Short name Jan-Dec\n * MMMM - Full name January - December\n * h - Minimum hour digits, 12 hour clock, 1-12\n * hh - 2 hour digits, 12 hour clock, 01-12\n * m - The minute 0-59\n * mm - The minute 00-12\n * s - The second 0-59\n * a - am/pm\n * A - AM/PM\n */\n const t = part.token\n if (t.startsWith(\"d\")) {\n // d, ddd, dddd — we just ignore these because they are non specific\n return\n } else if (t === \"D\") {\n parsed.set(\"DD\", v)\n } else if (t === \"H\" || t.startsWith(\"h\")) {\n parsed.set(\"HH\", v)\n } else if (t === \"M\") {\n parsed.set(\"MM\", v)\n } else if (t === \"a\" || t === \"A\") {\n a = part.value.toLowerCase() === ap(\"am\", locale).toLowerCase()\n } else if (t === \"Z\" || t === \"ZZ\") {\n offset = validOffset(part.value, t)\n } else {\n const values = range(t as FormatToken, locale, genitive)\n const index = values.indexOf(part.value)\n if (index !== -1) {\n switch (t) {\n case \"MMM\":\n case \"MMMM\":\n parsed.set(\"MM\", index + 1)\n break\n }\n }\n }\n }\n })\n let hours = parsed.get(\"HH\") || 0\n if (a === false) {\n hours += hours === 12 ? 0 : 12\n parsed.set(\"HH\", hours === 24 ? 0 : hours)\n } else if (a === true && hours === 12) {\n // 12am === 00 in 24 hour clock.\n parsed.set(\"HH\", 0)\n }\n parsed.set(\"MM\", (parsed.get(\"MM\") || 1) - 1)\n // eslint-disable-next-line prefer-const\n let [Y, M, D, h, m, s] = Array.from(parsed.values())\n\n // Determine if the date is valid for the month.\n const maxDaysInMonth = monthDays(new Date(`${four(Y)}-${two(M + 1)}-10`))\n if (maxDaysInMonth < D && dateOverflow === \"throw\")\n throw new Error(`Invalid date ${four(Y)}-${two(M + 1)}-${two(D)}`)\n D = dateOverflow === \"backward\" ? Math.min(D, maxDaysInMonth) : D\n\n // Create the date.\n const isoString = `${four(Y)}-${two(M + 1)}-${two(D)}T${two(h)}:${two(\n m\n )}:${two(s)}${offset}`\n const d = new Date(isoString)\n if (isFinite(+d)) return d\n return invalid()\n}\n\n/**\n * Given a string date and corresponding format parts, fill the parts with the\n * data from the string.\n * @param dateStr - A string to parse.\n * @param formatParts - The expected parts of the given string.\n */\nexport function parseParts(dateStr: string, formatParts: Part[]): FilledPart[] {\n let i = 0\n const advance = (parts: Part[]): [Part, Part | undefined] => [\n parts[i++],\n parts[i],\n ]\n let pos = 0\n const parsed: FilledPart[] = []\n let n: undefined | Part = undefined\n do {\n const [current, next] = advance(formatParts)\n n = next\n let len = 1\n if (current.partName === \"literal\") {\n // Literals can be discarded\n len = current.partValue.length\n } else if (current.partName === \"timeZoneName\") {\n len = fixedLengthByOffset(dateStr.substring(pos))\n } else if (current.token in fixedLength) {\n // Fixed length parse\n len = fixedLength[current.token as keyof typeof fixedLength]\n } else if (next) {\n // Variable length parse.\n if (next.partName === \"literal\") {\n len = dateStr.indexOf(next.partValue, pos) - pos\n if (len < 0) throw new Error()\n } else if (next.partName === \"dayPeriod\") {\n // Our validator is ensuring that the current item must be a variable\n // length number. We need to extract it.\n for (let i = 1; i <= 4; i++) {\n if (isNaN(Number(dateStr.charAt(pos + i)))) {\n len = i\n break\n }\n }\n } else {\n // Our validator guarantees the next is either not a number or it\n // will be the end of the string\n const nextChar = dateStr.substring(pos).search(/\\d/)\n if (nextChar !== -1) len = pos + nextChar\n }\n } else {\n len = dateStr.length\n }\n\n parsed.push({ ...current, value: dateStr.substring(pos, pos + len) })\n pos += len\n } while (n)\n return parsed\n}\n"],"mappings":"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","names":["parts","i"]}
|
package/dist/parts.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Format, Part } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Given a format string, produce an array of matching "parts", each part
|
|
5
|
+
* contains a regular expression and the corresponding
|
|
6
|
+
* Intl.DateTimeFormatPartTypesRegistry key/value.
|
|
7
|
+
* @param format - A format string like MM/DD/YYYY
|
|
8
|
+
* @param locale - The locale to parse for.
|
|
9
|
+
*/
|
|
10
|
+
declare function parts(format: Format, locale: string): Part[];
|
|
11
|
+
|
|
12
|
+
export { parts };
|
package/dist/parts.mjs
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
// src/parts.ts
|
|
2
|
+
import {
|
|
3
|
+
styles,
|
|
4
|
+
normStr,
|
|
5
|
+
tokens,
|
|
6
|
+
memoParts,
|
|
7
|
+
clockAgnostic,
|
|
8
|
+
clock24,
|
|
9
|
+
specDate,
|
|
10
|
+
clock12
|
|
11
|
+
} from "./common.mjs";
|
|
12
|
+
function parts(format, locale) {
|
|
13
|
+
if (styles.includes(format) || typeof format === "object") {
|
|
14
|
+
return styleParts(format, locale);
|
|
15
|
+
}
|
|
16
|
+
let f = format;
|
|
17
|
+
let match = 0;
|
|
18
|
+
const testPattern = (pattern) => {
|
|
19
|
+
if (!pattern[2])
|
|
20
|
+
pattern[2] = new RegExp(`(.)?(${pattern[0]})`, "g");
|
|
21
|
+
if (pattern[2].test(f)) {
|
|
22
|
+
let didAdd = 0;
|
|
23
|
+
f = f.replace(pattern[2], (_, prefix, actualMatch) => {
|
|
24
|
+
if (prefix === "\\")
|
|
25
|
+
return actualMatch;
|
|
26
|
+
return `${typeof prefix === "string" ? prefix : ""}{!${didAdd++ ? match : match++}!}`;
|
|
27
|
+
});
|
|
28
|
+
return !!didAdd;
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
};
|
|
32
|
+
function validate(patterns) {
|
|
33
|
+
const parts3 = patterns.map((part) => part.partName);
|
|
34
|
+
const deduped = new Set(parts3);
|
|
35
|
+
if (parts3.length > deduped.size) {
|
|
36
|
+
throw new Error(`Cannot reuse format tokens.`);
|
|
37
|
+
}
|
|
38
|
+
return patterns;
|
|
39
|
+
}
|
|
40
|
+
function createPart(hour12, [token, option, exp]) {
|
|
41
|
+
const partName = Object.keys(option)[0];
|
|
42
|
+
const partValue = option[partName];
|
|
43
|
+
return {
|
|
44
|
+
option,
|
|
45
|
+
partName,
|
|
46
|
+
partValue,
|
|
47
|
+
token,
|
|
48
|
+
pattern: exp,
|
|
49
|
+
hour12
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const found24Patterns = clockAgnostic.filter(testPattern).concat(clock24.filter(testPattern)).map(createPart.bind(null, false));
|
|
53
|
+
const parts2 = validate(
|
|
54
|
+
found24Patterns.concat(
|
|
55
|
+
clock12.filter(testPattern).map(createPart.bind(null, true))
|
|
56
|
+
)
|
|
57
|
+
);
|
|
58
|
+
const extractIndex = /^\{!(\d+)!\}$/;
|
|
59
|
+
return f.split(/(\{!\d+!\})/).map((match2) => {
|
|
60
|
+
const hasIndex = match2.match(extractIndex);
|
|
61
|
+
if (hasIndex) {
|
|
62
|
+
return parts2[Number(hasIndex[1])];
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
option: { literal: match2 },
|
|
66
|
+
partName: "literal",
|
|
67
|
+
partValue: match2,
|
|
68
|
+
token: match2,
|
|
69
|
+
pattern: new RegExp(""),
|
|
70
|
+
hour12: false
|
|
71
|
+
};
|
|
72
|
+
}).filter((part) => !(part.partName === "literal" && part.partValue === ""));
|
|
73
|
+
}
|
|
74
|
+
function styleParts(format, locale) {
|
|
75
|
+
const options = {
|
|
76
|
+
timeZone: "UTC"
|
|
77
|
+
};
|
|
78
|
+
if (typeof format === "string") {
|
|
79
|
+
options.dateStyle = format;
|
|
80
|
+
} else {
|
|
81
|
+
if ("date" in format)
|
|
82
|
+
options.dateStyle = format.date;
|
|
83
|
+
if ("time" in format)
|
|
84
|
+
options.timeStyle = format.time;
|
|
85
|
+
}
|
|
86
|
+
const formatter = new Intl.DateTimeFormat(locale, options);
|
|
87
|
+
const segments = formatter.formatToParts(new Date(specDate)).map(normStr);
|
|
88
|
+
const hourTypeSegments = formatter.formatToParts(/* @__PURE__ */ new Date("1999-04-05T23:05:01.000Z")).map(normStr);
|
|
89
|
+
const hourPart = hourTypeSegments.find((segment) => segment.type === "hour");
|
|
90
|
+
const hourType = hourPart && hourPart.value === "23" ? 24 : 12;
|
|
91
|
+
return segments.map((part) => {
|
|
92
|
+
const partName = part.type;
|
|
93
|
+
const formatPattern = guessPattern(
|
|
94
|
+
part.type,
|
|
95
|
+
part.value,
|
|
96
|
+
locale,
|
|
97
|
+
part.type === "hour" ? hourType : void 0,
|
|
98
|
+
options
|
|
99
|
+
);
|
|
100
|
+
if (formatPattern === void 0)
|
|
101
|
+
return;
|
|
102
|
+
const partValue = formatPattern[1][partName];
|
|
103
|
+
if (!partValue)
|
|
104
|
+
return;
|
|
105
|
+
if (!formatPattern[2])
|
|
106
|
+
formatPattern[2] = new RegExp(`${formatPattern[0]}`, "g");
|
|
107
|
+
return {
|
|
108
|
+
option: { [partName]: partValue },
|
|
109
|
+
partName,
|
|
110
|
+
partValue,
|
|
111
|
+
token: formatPattern[0],
|
|
112
|
+
pattern: formatPattern[2],
|
|
113
|
+
hour12: hourType === 12
|
|
114
|
+
};
|
|
115
|
+
}).filter((part) => !!part);
|
|
116
|
+
}
|
|
117
|
+
function guessPattern(partName, partValue, locale, hour, options) {
|
|
118
|
+
const l = partValue.length;
|
|
119
|
+
const n = !isNaN(Number(partValue));
|
|
120
|
+
let style;
|
|
121
|
+
switch (partName) {
|
|
122
|
+
case "year":
|
|
123
|
+
return l === 2 ? tokens.get("YY") : tokens.get("YYYY");
|
|
124
|
+
case "month":
|
|
125
|
+
if (n)
|
|
126
|
+
return l === 1 ? tokens.get("M") : tokens.get("MM");
|
|
127
|
+
style = partStyle(locale, partName, partValue);
|
|
128
|
+
switch (style) {
|
|
129
|
+
case "long":
|
|
130
|
+
return tokens.get("MMMM");
|
|
131
|
+
default:
|
|
132
|
+
return tokens.get("MMM");
|
|
133
|
+
}
|
|
134
|
+
case "day":
|
|
135
|
+
return l === 1 ? tokens.get("D") : tokens.get("DD");
|
|
136
|
+
case "weekday":
|
|
137
|
+
style = partStyle(locale, partName, partValue);
|
|
138
|
+
switch (style) {
|
|
139
|
+
case "narrow":
|
|
140
|
+
return tokens.get("d");
|
|
141
|
+
case "short":
|
|
142
|
+
return tokens.get("ddd");
|
|
143
|
+
default:
|
|
144
|
+
return tokens.get("dddd");
|
|
145
|
+
}
|
|
146
|
+
case "hour":
|
|
147
|
+
if (hour === 12)
|
|
148
|
+
return l === 1 ? tokens.get("h") : tokens.get("hh");
|
|
149
|
+
return l === 1 ? tokens.get("H") : tokens.get("HH");
|
|
150
|
+
case "minute":
|
|
151
|
+
return l === 1 ? tokens.get("m") : tokens.get("mm");
|
|
152
|
+
case "second":
|
|
153
|
+
return l === 1 ? tokens.get("s") : tokens.get("ss");
|
|
154
|
+
case "dayPeriod":
|
|
155
|
+
return /^[A-Z]+$/u.test(partValue) ? tokens.get("A") : tokens.get("a");
|
|
156
|
+
case "literal":
|
|
157
|
+
return [partValue, { literal: partValue }, new RegExp("")];
|
|
158
|
+
case "timeZoneName":
|
|
159
|
+
return options.timeStyle === "full" ? tokens.get("Z") : tokens.get("ZZ");
|
|
160
|
+
default:
|
|
161
|
+
return void 0;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function partStyle(locale, part, value) {
|
|
165
|
+
if (!memoParts.has(locale)) {
|
|
166
|
+
const date = new Date(specDate);
|
|
167
|
+
const weekdays = [3, 8, 9, 7, 6, 4, 3];
|
|
168
|
+
const parts2 = ["weekday", "month", "dayPeriod"];
|
|
169
|
+
const partStyles = ["long", "short", "narrow"];
|
|
170
|
+
const formats2 = {};
|
|
171
|
+
for (let i = 0; i < 12; i++) {
|
|
172
|
+
date.setMonth(0 + i);
|
|
173
|
+
if (i in weekdays)
|
|
174
|
+
date.setDate(weekdays[i]);
|
|
175
|
+
date.setUTCHours(8 + i);
|
|
176
|
+
for (const style of partStyles) {
|
|
177
|
+
const segments = new Intl.DateTimeFormat(
|
|
178
|
+
locale,
|
|
179
|
+
parts2.reduce(
|
|
180
|
+
(options, part2) => Object.assign(options, { [part2]: style }),
|
|
181
|
+
{ hour12: true, timeZone: "UTC" }
|
|
182
|
+
)
|
|
183
|
+
).formatToParts(date).map(normStr);
|
|
184
|
+
if (style === "long" || style === "short") {
|
|
185
|
+
const genitiveFormattedParts = new Intl.DateTimeFormat(locale, {
|
|
186
|
+
dateStyle: style === "short" ? "medium" : "long",
|
|
187
|
+
timeZone: "UTC"
|
|
188
|
+
}).formatToParts(date).map(normStr);
|
|
189
|
+
const genitiveMonth = genitiveFormattedParts.find(
|
|
190
|
+
(part2) => part2.type === "month"
|
|
191
|
+
);
|
|
192
|
+
const index = segments.findIndex((part2) => part2.type === "month");
|
|
193
|
+
if (index > -1 && genitiveMonth)
|
|
194
|
+
segments[index] = genitiveMonth;
|
|
195
|
+
}
|
|
196
|
+
segments.forEach((part2) => {
|
|
197
|
+
if (part2.type === "literal")
|
|
198
|
+
return;
|
|
199
|
+
const type = part2.type;
|
|
200
|
+
formats2[type] = Object.assign(formats2[type] || {}, {
|
|
201
|
+
[part2.value]: style
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
memoParts.set(locale, formats2);
|
|
207
|
+
}
|
|
208
|
+
const formats = memoParts.get(locale);
|
|
209
|
+
return formats ? formats[part][value] : void 0;
|
|
210
|
+
}
|
|
211
|
+
export {
|
|
212
|
+
parts
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=parts.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/parts.ts"],"sourcesContent":["import {\n styles,\n normStr,\n tokens,\n memoParts,\n clockAgnostic,\n clock24,\n specDate,\n clock12,\n} from \"./common\"\nimport type {\n ParseOptions,\n Format,\n Part,\n FormatStyle,\n FormatStyleObj,\n FormatPattern,\n NamedFormats,\n NamedFormatOption,\n} from \"./types\"\n/**\n * Given a format string, produce an array of matching \"parts\", each part\n * contains a regular expression and the corresponding\n * Intl.DateTimeFormatPartTypesRegistry key/value.\n * @param format - A format string like MM/DD/YYYY\n * @param locale - The locale to parse for.\n */\nexport function parts(format: Format, locale: string): Part[] {\n if (styles.includes(format as FormatStyle) || typeof format === \"object\") {\n return styleParts(format as FormatStyle | FormatStyleObj, locale)\n }\n let f = format\n let match = 0\n const testPattern = (pattern: FormatPattern) => {\n if (!pattern[2]) pattern[2] = new RegExp(`(.)?(${pattern[0]})`, \"g\")\n if (pattern[2].test(f)) {\n let didAdd = 0\n f = f.replace(pattern[2], (_, prefix, actualMatch) => {\n if (prefix === \"\\\\\") return actualMatch\n return `${typeof prefix === \"string\" ? prefix : \"\"}{!${\n didAdd++ ? match : match++\n }!}`\n })\n return !!didAdd\n }\n return false\n }\n\n function validate(patterns: Part[]): Part[] {\n const parts = patterns.map((part) => part.partName)\n const deduped = new Set(parts)\n if (parts.length > deduped.size) {\n throw new Error(`Cannot reuse format tokens.`)\n }\n return patterns\n }\n\n function createPart(\n hour12: boolean,\n [token, option, exp]: FormatPattern\n ): Part {\n const partName = Object.keys(option)[0] as Intl.DateTimeFormatPartTypes\n const partValue = option[partName] as string\n return {\n option,\n partName,\n partValue,\n token,\n pattern: exp as RegExp,\n hour12,\n }\n }\n\n const found24Patterns = clockAgnostic\n .filter(testPattern)\n .concat(clock24.filter(testPattern))\n .map(createPart.bind(null, false))\n\n // Reset the format before re-checking\n const parts = validate(\n found24Patterns.concat(\n clock12.filter(testPattern).map(createPart.bind(null, true))\n )\n )\n const extractIndex = /^\\{!(\\d+)!\\}$/\n return f\n .split(/(\\{!\\d+!\\})/)\n .map((match: string): Part => {\n const hasIndex = match.match(extractIndex)\n if (hasIndex) {\n return parts[Number(hasIndex[1])]\n }\n return {\n option: { literal: match },\n partName: \"literal\",\n partValue: match,\n token: match,\n pattern: new RegExp(\"\"),\n hour12: false,\n }\n })\n .filter((part) => !(part.partName === \"literal\" && part.partValue === \"\"))\n}\n\n/**\n * Determines the parts in a native date style, like \"full\".\n * @param format - A date style like \"full\" or \"short\"\n * @param locale - The locale string\n */\nfunction styleParts(\n format: FormatStyle | FormatStyleObj,\n locale: string\n): Part[] {\n const options: Intl.DateTimeFormatOptions = {\n timeZone: \"UTC\",\n }\n if (typeof format === \"string\") {\n options.dateStyle = format\n } else {\n if (\"date\" in format) options.dateStyle = format.date\n if (\"time\" in format) options.timeStyle = format.time\n }\n\n const formatter = new Intl.DateTimeFormat(locale, options)\n const segments = formatter.formatToParts(new Date(specDate)).map(normStr)\n const hourTypeSegments = formatter\n .formatToParts(new Date(\"1999-04-05T23:05:01.000Z\"))\n .map(normStr)\n const hourPart = hourTypeSegments.find((segment) => segment.type === \"hour\")\n const hourType = hourPart && hourPart.value === \"23\" ? 24 : 12\n return segments\n .map((part): Part | undefined => {\n const partName = part.type\n const formatPattern = guessPattern(\n part.type,\n part.value,\n locale,\n part.type === \"hour\" ? hourType : undefined,\n options\n )\n if (formatPattern === undefined) return\n const partValue = formatPattern[1][partName]\n if (!partValue) return\n if (!formatPattern[2])\n formatPattern[2] = new RegExp(`${formatPattern[0]}`, \"g\")\n return {\n option: { [partName]: partValue },\n partName,\n partValue,\n token: formatPattern[0],\n pattern: formatPattern[2],\n hour12: hourType === 12,\n }\n })\n .filter((part): part is Part => !!part)\n}\n\n/**\n * Attempts to guess the correct part value type for a given dateStyle. For\n * example a month of 02 would be \"2-digit\".\n *\n * @param partName - The part name to guess for, like 'year' or 'month'\n * @param partValue - The current value, it is assumed this is the smallest denom.\n */\nfunction guessPattern<T extends Intl.DateTimeFormatPartTypes>(\n partName: T,\n partValue: string,\n locale: string,\n hour: T extends \"hour\" ? 12 | 24 : undefined,\n options: Intl.DateTimeFormatOptions\n): FormatPattern | undefined {\n const l = partValue.length\n const n = !isNaN(Number(partValue))\n let style: NamedFormatOption | undefined\n /* eslint-disable @typescript-eslint/no-non-null-assertion */\n switch (partName) {\n case \"year\":\n return l === 2 ? tokens.get(\"YY\") : tokens.get(\"YYYY\")\n case \"month\":\n if (n) return l === 1 ? tokens.get(\"M\") : tokens.get(\"MM\")\n style = partStyle(locale, partName, partValue)\n switch (style) {\n case \"long\":\n return tokens.get(\"MMMM\")\n default:\n return tokens.get(\"MMM\")\n }\n case \"day\":\n return l === 1 ? tokens.get(\"D\") : tokens.get(\"DD\")\n case \"weekday\":\n style = partStyle(locale, partName, partValue)\n switch (style) {\n case \"narrow\":\n return tokens.get(\"d\")\n case \"short\":\n return tokens.get(\"ddd\")\n default:\n return tokens.get(\"dddd\")\n }\n case \"hour\":\n // Need to distinguish the locale’s default as 24 or 12 hour.\n if (hour === 12) return l === 1 ? tokens.get(\"h\") : tokens.get(\"hh\")\n return l === 1 ? tokens.get(\"H\") : tokens.get(\"HH\")\n case \"minute\":\n return l === 1 ? tokens.get(\"m\") : tokens.get(\"mm\")\n case \"second\":\n return l === 1 ? tokens.get(\"s\") : tokens.get(\"ss\")\n case \"dayPeriod\":\n return /^[A-Z]+$/u.test(partValue) ? tokens.get(\"A\") : tokens.get(\"a\")\n case \"literal\":\n return [partValue, { literal: partValue }, new RegExp(\"\")]\n case \"timeZoneName\":\n return options.timeStyle === \"full\" ? tokens.get(\"Z\") : tokens.get(\"ZZ\")\n default:\n return undefined\n }\n /* eslint-enable @typescript-eslint/no-non-null-assertion */\n}\n\n/**\n * Determines what \"style\" a given part is in. For example, if you provide:\n * ```js\n * partStyle('en', 'month', 'Jan')\n * // returns \"short\".\n * ```\n * Part styles are always expected to be \"genitive\" — for use in \"dateStyle\".\n * @param locale - Locale string\n * @param part - The part to attempt a lookup on\n * @param value - The value of a given part.\n */\nfunction partStyle(\n locale: string,\n part: keyof NamedFormats,\n value: string\n): NamedFormatOption | undefined {\n if (!memoParts.has(locale)) {\n const date = new Date(specDate)\n const weekdays = [3, 8, 9, 7, 6, 4, 3]\n const parts = [\"weekday\", \"month\", \"dayPeriod\"]\n const partStyles: NamedFormatOption[] = [\"long\", \"short\", \"narrow\"]\n const formats: Partial<NamedFormats> = {}\n for (let i = 0; i < 12; i++) {\n date.setMonth(0 + i)\n if (i in weekdays) date.setDate(weekdays[i])\n date.setUTCHours(8 + i)\n for (const style of partStyles) {\n const segments = new Intl.DateTimeFormat(\n locale,\n parts.reduce(\n (options, part) => Object.assign(options, { [part]: style }),\n { hour12: true, timeZone: \"UTC\" }\n )\n )\n .formatToParts(date)\n .map(normStr)\n if (style === \"long\" || style === \"short\") {\n const genitiveFormattedParts = new Intl.DateTimeFormat(locale, {\n dateStyle: style === \"short\" ? \"medium\" : \"long\",\n timeZone: \"UTC\",\n })\n .formatToParts(date)\n .map(normStr)\n const genitiveMonth = genitiveFormattedParts.find(\n (part) => part.type === \"month\"\n )\n const index = segments.findIndex((part) => part.type === \"month\")\n if (index > -1 && genitiveMonth) segments[index] = genitiveMonth\n }\n segments.forEach((part) => {\n if (part.type === \"literal\") return\n const type = part.type as keyof NamedFormats\n formats[type] = Object.assign(formats[type] || {}, {\n [part.value]: style,\n })\n })\n }\n }\n memoParts.set(locale, formats as NamedFormats)\n }\n const formats = memoParts.get(locale)\n return formats ? formats[part][value] : undefined\n}\n"],"mappings":"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","names":["parts","match","formats","part"]}
|
package/dist/range.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FormatToken } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns an array of options for a given token in a given locale.
|
|
5
|
+
* @param token - Get the full range of options for a given token
|
|
6
|
+
* @param locale - The locale to fetch the options for.
|
|
7
|
+
*/
|
|
8
|
+
declare function range(token: FormatToken, locale?: string, genitive?: boolean): string[];
|
|
9
|
+
|
|
10
|
+
export { range };
|
package/dist/range.mjs
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// src/range.ts
|
|
2
|
+
import { format } from "./format.mjs";
|
|
3
|
+
import { ap } from "./ap.mjs";
|
|
4
|
+
function range(token, locale = "en", genitive = false) {
|
|
5
|
+
const r = (n, c) => Array(n).fill("").map((_, i) => `${c(i)}`);
|
|
6
|
+
if (token === "M")
|
|
7
|
+
return r(12, (i) => i + 1);
|
|
8
|
+
if (token === "MM")
|
|
9
|
+
return r(12, (i) => {
|
|
10
|
+
const m = i + 1;
|
|
11
|
+
return m < 10 ? `0${m}` : m;
|
|
12
|
+
});
|
|
13
|
+
if (token.startsWith("M"))
|
|
14
|
+
return range("MM").map(
|
|
15
|
+
(m) => format(`2000-${m}-05`, token, locale, genitive)
|
|
16
|
+
);
|
|
17
|
+
if (token.startsWith("d"))
|
|
18
|
+
return r(7, (i) => `0${i + 2}`).map(
|
|
19
|
+
(d) => format(`2022-10-${d}`, token, locale)
|
|
20
|
+
);
|
|
21
|
+
if (token === "a")
|
|
22
|
+
return [ap("am", locale).toLowerCase(), ap("pm", locale).toLowerCase()];
|
|
23
|
+
if (token === "A")
|
|
24
|
+
return [ap("am", locale).toUpperCase(), ap("pm", locale).toUpperCase()];
|
|
25
|
+
if (token.startsWith("Y")) {
|
|
26
|
+
const year = (/* @__PURE__ */ new Date()).getFullYear();
|
|
27
|
+
return r(120, (i) => i + 1).reduce(
|
|
28
|
+
(ranges, i) => {
|
|
29
|
+
if (i !== "120")
|
|
30
|
+
ranges.push(format(`${year + Number(i)}-06-06`, token, locale));
|
|
31
|
+
ranges.unshift(format(`${year - Number(i)}-06-06`, token, locale));
|
|
32
|
+
return ranges;
|
|
33
|
+
},
|
|
34
|
+
[format(`${year}-06-06`, token, locale)]
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
if (token.startsWith("D"))
|
|
38
|
+
return r(31, (i) => `${token === "DD" && i < 9 ? "0" : ""}${i + 1}`);
|
|
39
|
+
if (token.startsWith("H"))
|
|
40
|
+
return r(24, (i) => `${token === "HH" && i < 10 ? "0" : ""}${i}`);
|
|
41
|
+
if (token.startsWith("h"))
|
|
42
|
+
return r(12, (i) => `${token === "hh" && i < 9 ? "0" : ""}${i + 1}`);
|
|
43
|
+
if (token.startsWith("m") || token.startsWith("s"))
|
|
44
|
+
return r(60, (i) => `${token.length > 1 && i < 10 ? "0" : ""}${i}`);
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
range
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=range.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/range.ts"],"sourcesContent":["import { format } from \"./format\"\nimport { ap } from \"./ap\"\nimport type { FormatToken } from \"./types\"\n/**\n * Returns an array of options for a given token in a given locale.\n * @param token - Get the full range of options for a given token\n * @param locale - The locale to fetch the options for.\n */\nexport function range(\n token: FormatToken,\n locale = \"en\",\n genitive = false\n): string[] {\n const r: (n: number, c: (index: number) => string | number) => string[] = (\n n,\n c\n ) =>\n Array(n)\n .fill(\"\")\n .map((_, i) => `${c(i)}`)\n\n if (token === \"M\") return r(12, (i) => i + 1)\n if (token === \"MM\")\n return r(12, (i) => {\n const m = i + 1\n return m < 10 ? `0${m}` : m\n })\n // MMM and MMMM\n if (token.startsWith(\"M\"))\n return range(\"MM\").map((m) =>\n format(`2000-${m}-05`, token, locale, genitive)\n )\n if (token.startsWith(\"d\"))\n return r(7, (i) => `0${i + 2}`).map((d) =>\n format(`2022-10-${d}`, token, locale)\n )\n if (token === \"a\")\n return [ap(\"am\", locale).toLowerCase(), ap(\"pm\", locale).toLowerCase()]\n if (token === \"A\")\n return [ap(\"am\", locale).toUpperCase(), ap(\"pm\", locale).toUpperCase()]\n if (token.startsWith(\"Y\")) {\n const year = new Date().getFullYear()\n return r(120, (i) => i + 1).reduce(\n (ranges, i) => {\n if (i !== \"120\")\n ranges.push(format(`${year + Number(i)}-06-06`, token, locale))\n ranges.unshift(format(`${year - Number(i)}-06-06`, token, locale))\n return ranges\n },\n [format(`${year}-06-06`, token, locale)]\n )\n }\n if (token.startsWith(\"D\"))\n return r(31, (i) => `${token === \"DD\" && i < 9 ? \"0\" : \"\"}${i + 1}`)\n if (token.startsWith(\"H\"))\n return r(24, (i) => `${token === \"HH\" && i < 10 ? \"0\" : \"\"}${i}`)\n if (token.startsWith(\"h\"))\n return r(12, (i) => `${token === \"hh\" && i < 9 ? \"0\" : \"\"}${i + 1}`)\n if (token.startsWith(\"m\") || token.startsWith(\"s\"))\n return r(60, (i) => `${token.length > 1 && i < 10 ? \"0\" : \"\"}${i}`)\n return []\n}\n"],"mappings":";AAAA,SAAS,cAAc;AACvB,SAAS,UAAU;AAOZ,SAAS,MACd,OACA,SAAS,MACT,WAAW,OACD;AACV,QAAM,IAAoE,CACxE,GACA,MAEA,MAAM,CAAC,EACJ,KAAK,EAAE,EACP,IAAI,CAAC,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC,EAAE;AAE5B,MAAI,UAAU;AAAK,WAAO,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC;AAC5C,MAAI,UAAU;AACZ,WAAO,EAAE,IAAI,CAAC,MAAM;AAClB,YAAM,IAAI,IAAI;AACd,aAAO,IAAI,KAAK,IAAI,CAAC,KAAK;AAAA,IAC5B,CAAC;AAEH,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,MAAM,IAAI,EAAE;AAAA,MAAI,CAAC,MACtB,OAAO,QAAQ,CAAC,OAAO,OAAO,QAAQ,QAAQ;AAAA,IAChD;AACF,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,EAAE,EAAE;AAAA,MAAI,CAAC,MACnC,OAAO,WAAW,CAAC,IAAI,OAAO,MAAM;AAAA,IACtC;AACF,MAAI,UAAU;AACZ,WAAO,CAAC,GAAG,MAAM,MAAM,EAAE,YAAY,GAAG,GAAG,MAAM,MAAM,EAAE,YAAY,CAAC;AACxE,MAAI,UAAU;AACZ,WAAO,CAAC,GAAG,MAAM,MAAM,EAAE,YAAY,GAAG,GAAG,MAAM,MAAM,EAAE,YAAY,CAAC;AACxE,MAAI,MAAM,WAAW,GAAG,GAAG;AACzB,UAAM,QAAO,oBAAI,KAAK,GAAE,YAAY;AACpC,WAAO,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE;AAAA,MAC1B,CAAC,QAAQ,MAAM;AACb,YAAI,MAAM;AACR,iBAAO,KAAK,OAAO,GAAG,OAAO,OAAO,CAAC,CAAC,UAAU,OAAO,MAAM,CAAC;AAChE,eAAO,QAAQ,OAAO,GAAG,OAAO,OAAO,CAAC,CAAC,UAAU,OAAO,MAAM,CAAC;AACjE,eAAO;AAAA,MACT;AAAA,MACA,CAAC,OAAO,GAAG,IAAI,UAAU,OAAO,MAAM,CAAC;AAAA,IACzC;AAAA,EACF;AACA,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,IAAI,CAAC,MAAM,GAAG,UAAU,QAAQ,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE;AACrE,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,IAAI,CAAC,MAAM,GAAG,UAAU,QAAQ,IAAI,KAAK,MAAM,EAAE,GAAG,CAAC,EAAE;AAClE,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO,EAAE,IAAI,CAAC,MAAM,GAAG,UAAU,QAAQ,IAAI,IAAI,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE;AACrE,MAAI,MAAM,WAAW,GAAG,KAAK,MAAM,WAAW,GAAG;AAC/C,WAAO,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,SAAS,KAAK,IAAI,KAAK,MAAM,EAAE,GAAG,CAAC,EAAE;AACpE,SAAO,CAAC;AACV;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DateInput } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Inverts the offset and applies it to the given date, returning a new date.
|
|
5
|
+
* @param dateInput - The date to remove the offset from.
|
|
6
|
+
* @param offset - The offset to remove in the +-HHmm or +-HH:mm format.
|
|
7
|
+
*/
|
|
8
|
+
declare function removeOffset(dateInput: DateInput, offset?: string): Date;
|
|
9
|
+
|
|
10
|
+
export { removeOffset };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// src/removeOffset.ts
|
|
2
|
+
import { applyOffset } from "./applyOffset.mjs";
|
|
3
|
+
function removeOffset(dateInput, offset = "+00:00") {
|
|
4
|
+
const positive = offset.slice(0, 1) === "+";
|
|
5
|
+
return applyOffset(
|
|
6
|
+
dateInput,
|
|
7
|
+
offset.replace(positive ? "+" : "-", positive ? "-" : "+")
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
export {
|
|
11
|
+
removeOffset
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=removeOffset.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/removeOffset.ts"],"sourcesContent":["import { applyOffset } from \"./applyOffset\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Inverts the offset and applies it to the given date, returning a new date.\n * @param dateInput - The date to remove the offset from.\n * @param offset - The offset to remove in the +-HHmm or +-HH:mm format.\n */\nexport function removeOffset(dateInput: DateInput, offset = \"+00:00\"): Date {\n const positive = offset.slice(0, 1) === \"+\"\n return applyOffset(\n dateInput,\n offset.replace(positive ? \"+\" : \"-\", positive ? \"-\" : \"+\")\n )\n}\n"],"mappings":";AAAA,SAAS,mBAAmB;AAQrB,SAAS,aAAa,WAAsB,SAAS,UAAgB;AAC1E,QAAM,WAAW,OAAO,MAAM,GAAG,CAAC,MAAM;AACxC,SAAO;AAAA,IACL;AAAA,IACA,OAAO,QAAQ,WAAW,MAAM,KAAK,WAAW,MAAM,GAAG;AAAA,EAC3D;AACF;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DateInput } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if two date objects refer to the same date. Ignores time.
|
|
5
|
+
* @param inputDateA - First date to compare
|
|
6
|
+
* @param inputDateB - Second date to compare
|
|
7
|
+
*/
|
|
8
|
+
declare function sameDay(inputDateA: DateInput, inputDateB: DateInput): boolean;
|
|
9
|
+
|
|
10
|
+
export { sameDay };
|
package/dist/sameDay.mjs
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// src/sameDay.ts
|
|
2
|
+
import { date } from "./date.mjs";
|
|
3
|
+
function sameDay(inputDateA, inputDateB) {
|
|
4
|
+
const a = date(inputDateA);
|
|
5
|
+
const b = date(inputDateB);
|
|
6
|
+
return a.getDate() === b.getDate() && a.getMonth() === b.getMonth() && a.getFullYear() === b.getFullYear();
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
sameDay
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=sameDay.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/sameDay.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Checks if two date objects refer to the same date. Ignores time.\n * @param inputDateA - First date to compare\n * @param inputDateB - Second date to compare\n */\nexport function sameDay(inputDateA: DateInput, inputDateB: DateInput) {\n const a = date(inputDateA)\n const b = date(inputDateB)\n return (\n a.getDate() === b.getDate() &&\n a.getMonth() === b.getMonth() &&\n a.getFullYear() === b.getFullYear()\n )\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAQd,SAAS,QAAQ,YAAuB,YAAuB;AACpE,QAAM,IAAI,KAAK,UAAU;AACzB,QAAM,IAAI,KAAK,UAAU;AACzB,SACE,EAAE,QAAQ,MAAM,EAAE,QAAQ,KAC1B,EAAE,SAAS,MAAM,EAAE,SAAS,KAC5B,EAAE,YAAY,MAAM,EAAE,YAAY;AAEtC;","names":[]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { DateInput } from './types.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checks if two date objects refer to the same time hour. Ignores date.
|
|
5
|
+
* @param inputDateA - First date to compare
|
|
6
|
+
* @param inputDateB - Second date to compare
|
|
7
|
+
*/
|
|
8
|
+
declare function sameHour(inputDateA: DateInput, inputDateB: DateInput): boolean;
|
|
9
|
+
|
|
10
|
+
export { sameHour };
|