@formkit/tempo 0.1.2 → 1.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.
Files changed (178) hide show
  1. package/README.md +22 -1
  2. package/dist/add.d.ts +11 -0
  3. package/dist/add.mjs +50 -0
  4. package/dist/add.mjs.map +1 -0
  5. package/dist/addDay.d.ts +4 -3
  6. package/dist/addDay.mjs.map +1 -1
  7. package/dist/addHour.d.ts +4 -3
  8. package/dist/addHour.mjs.map +1 -1
  9. package/dist/addMillisecond.d.ts +10 -0
  10. package/dist/addMillisecond.mjs +11 -0
  11. package/dist/addMillisecond.mjs.map +1 -0
  12. package/dist/addMinute.d.ts +5 -4
  13. package/dist/addMinute.mjs.map +1 -1
  14. package/dist/addMonth.d.ts +5 -5
  15. package/dist/addMonth.mjs +2 -12
  16. package/dist/addMonth.mjs.map +1 -1
  17. package/dist/addSecond.d.ts +4 -3
  18. package/dist/addSecond.mjs.map +1 -1
  19. package/dist/addYear.d.ts +5 -5
  20. package/dist/addYear.mjs +6 -12
  21. package/dist/addYear.mjs.map +1 -1
  22. package/dist/ap.mjs +1 -2
  23. package/dist/ap.mjs.map +1 -1
  24. package/dist/applyOffset.d.ts +5 -5
  25. package/dist/applyOffset.mjs +5 -11
  26. package/dist/applyOffset.mjs.map +1 -1
  27. package/dist/bundle.d.ts +365 -115
  28. package/dist/bundle.mjs +364 -180
  29. package/dist/bundle.mjs.map +1 -1
  30. package/dist/common.d.ts +27 -7
  31. package/dist/common.mjs +47 -42
  32. package/dist/common.mjs.map +1 -1
  33. package/dist/date.d.ts +2 -2
  34. package/dist/date.mjs +1 -3
  35. package/dist/date.mjs.map +1 -1
  36. package/dist/dayEnd.d.ts +3 -3
  37. package/dist/dayEnd.mjs.map +1 -1
  38. package/dist/dayOfYear.d.ts +3 -3
  39. package/dist/dayOfYear.mjs.map +1 -1
  40. package/dist/dayStart.d.ts +3 -3
  41. package/dist/dayStart.mjs +1 -1
  42. package/dist/dayStart.mjs.map +1 -1
  43. package/dist/diff.d.ts +38 -0
  44. package/dist/diff.mjs +86 -0
  45. package/dist/diff.mjs.map +1 -0
  46. package/dist/diffDays.d.ts +12 -5
  47. package/dist/diffDays.mjs +1 -0
  48. package/dist/diffDays.mjs.map +1 -1
  49. package/dist/diffHours.d.ts +12 -5
  50. package/dist/diffHours.mjs +1 -0
  51. package/dist/diffHours.mjs.map +1 -1
  52. package/dist/diffMilliseconds.d.ts +10 -4
  53. package/dist/diffMilliseconds.mjs.map +1 -1
  54. package/dist/diffMinutes.d.ts +11 -3
  55. package/dist/diffMinutes.mjs +5 -1
  56. package/dist/diffMinutes.mjs.map +1 -1
  57. package/dist/diffMonths.d.ts +10 -4
  58. package/dist/diffMonths.mjs.map +1 -1
  59. package/dist/diffSeconds.d.ts +12 -5
  60. package/dist/diffSeconds.mjs +5 -1
  61. package/dist/diffSeconds.mjs.map +1 -1
  62. package/dist/diffWeeks.d.ts +10 -3
  63. package/dist/diffWeeks.mjs.map +1 -1
  64. package/dist/diffYears.d.ts +10 -4
  65. package/dist/diffYears.mjs +4 -1
  66. package/dist/diffYears.mjs.map +1 -1
  67. package/dist/format.mjs +2 -3
  68. package/dist/format.mjs.map +1 -1
  69. package/dist/handleDateOverflow.d.ts +12 -0
  70. package/dist/handleDateOverflow.mjs +18 -0
  71. package/dist/handleDateOverflow.mjs.map +1 -0
  72. package/dist/hourEnd.d.ts +3 -3
  73. package/dist/hourEnd.mjs.map +1 -1
  74. package/dist/hourStart.d.ts +3 -3
  75. package/dist/hourStart.mjs +1 -1
  76. package/dist/hourStart.mjs.map +1 -1
  77. package/dist/index.cjs +380 -183
  78. package/dist/index.cjs.map +1 -1
  79. package/dist/index.d.cts +365 -115
  80. package/dist/index.d.ts +14 -1
  81. package/dist/index.mjs +26 -0
  82. package/dist/index.mjs.map +1 -1
  83. package/dist/isAfter.d.ts +6 -6
  84. package/dist/isAfter.mjs.map +1 -1
  85. package/dist/isBefore.d.ts +5 -5
  86. package/dist/isBefore.mjs.map +1 -1
  87. package/dist/isEqual.d.ts +13 -4
  88. package/dist/isEqual.mjs.map +1 -1
  89. package/dist/isFuture.d.ts +10 -0
  90. package/dist/isFuture.mjs +9 -0
  91. package/dist/isFuture.mjs.map +1 -0
  92. package/dist/isPast.d.ts +10 -0
  93. package/dist/isPast.mjs +9 -0
  94. package/dist/isPast.mjs.map +1 -0
  95. package/dist/iso8601.d.ts +1 -1
  96. package/dist/iso8601.mjs +4 -7
  97. package/dist/iso8601.mjs.map +1 -1
  98. package/dist/minuteEnd.d.ts +3 -3
  99. package/dist/minuteEnd.mjs.map +1 -1
  100. package/dist/minuteStart.d.ts +3 -3
  101. package/dist/minuteStart.mjs +1 -1
  102. package/dist/minuteStart.mjs.map +1 -1
  103. package/dist/monthDays.d.ts +3 -3
  104. package/dist/monthDays.mjs.map +1 -1
  105. package/dist/monthEnd.d.ts +3 -3
  106. package/dist/monthEnd.mjs.map +1 -1
  107. package/dist/monthStart.d.ts +3 -3
  108. package/dist/monthStart.mjs +1 -1
  109. package/dist/monthStart.mjs.map +1 -1
  110. package/dist/nearestDay.d.ts +3 -3
  111. package/dist/nearestDay.mjs +2 -4
  112. package/dist/nearestDay.mjs.map +1 -1
  113. package/dist/offset.d.ts +5 -5
  114. package/dist/offset.mjs +16 -16
  115. package/dist/offset.mjs.map +1 -1
  116. package/dist/parse.mjs +33 -23
  117. package/dist/parse.mjs.map +1 -1
  118. package/dist/parts.mjs +14 -24
  119. package/dist/parts.mjs.map +1 -1
  120. package/dist/range.mjs +1 -2
  121. package/dist/range.mjs.map +1 -1
  122. package/dist/removeOffset.d.ts +4 -4
  123. package/dist/removeOffset.mjs.map +1 -1
  124. package/dist/sameDay.d.ts +8 -2
  125. package/dist/sameDay.mjs.map +1 -1
  126. package/dist/sameHour.d.ts +8 -2
  127. package/dist/sameHour.mjs.map +1 -1
  128. package/dist/sameMillisecond.d.ts +16 -0
  129. package/dist/sameMillisecond.mjs +11 -0
  130. package/dist/sameMillisecond.mjs.map +1 -0
  131. package/dist/sameMinute.d.ts +8 -2
  132. package/dist/sameMinute.mjs.map +1 -1
  133. package/dist/sameMonth.d.ts +16 -0
  134. package/dist/sameMonth.mjs +11 -0
  135. package/dist/sameMonth.mjs.map +1 -0
  136. package/dist/sameSecond.d.ts +8 -2
  137. package/dist/sameSecond.mjs.map +1 -1
  138. package/dist/sameYear.d.ts +8 -2
  139. package/dist/sameYear.mjs.map +1 -1
  140. package/dist/setDayOfMonth.d.ts +11 -0
  141. package/dist/setDayOfMonth.mjs +16 -0
  142. package/dist/setDayOfMonth.mjs.map +1 -0
  143. package/dist/setHour.d.ts +10 -0
  144. package/dist/setHour.mjs +11 -0
  145. package/dist/setHour.mjs.map +1 -0
  146. package/dist/setMilliseconds.d.ts +10 -0
  147. package/dist/setMilliseconds.mjs +11 -0
  148. package/dist/setMilliseconds.mjs.map +1 -0
  149. package/dist/setMinutes.d.ts +10 -0
  150. package/dist/setMinutes.mjs +11 -0
  151. package/dist/setMinutes.mjs.map +1 -0
  152. package/dist/setMonth.d.ts +11 -0
  153. package/dist/setMonth.mjs +9 -0
  154. package/dist/setMonth.mjs.map +1 -0
  155. package/dist/setSeconds.d.ts +10 -0
  156. package/dist/setSeconds.mjs +11 -0
  157. package/dist/setSeconds.mjs.map +1 -0
  158. package/dist/setYear.d.ts +11 -0
  159. package/dist/setYear.mjs +9 -0
  160. package/dist/setYear.mjs.map +1 -0
  161. package/dist/types.d.ts +29 -7
  162. package/dist/tzDate.d.ts +5 -3
  163. package/dist/tzDate.mjs.map +1 -1
  164. package/dist/weekEnd.d.ts +4 -4
  165. package/dist/weekEnd.mjs +1 -1
  166. package/dist/weekEnd.mjs.map +1 -1
  167. package/dist/weekStart.d.ts +4 -4
  168. package/dist/weekStart.mjs +2 -3
  169. package/dist/weekStart.mjs.map +1 -1
  170. package/dist/yearDays.d.ts +3 -3
  171. package/dist/yearDays.mjs.map +1 -1
  172. package/dist/yearEnd.d.ts +3 -3
  173. package/dist/yearEnd.mjs +1 -2
  174. package/dist/yearEnd.mjs.map +1 -1
  175. package/dist/yearStart.d.ts +3 -3
  176. package/dist/yearStart.mjs +2 -3
  177. package/dist/yearStart.mjs.map +1 -1
  178. package/package.json +32 -23
package/dist/common.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { NamedFormats, FormatPattern, FormatStyle, DateInput, Part, FilledPart, Format } from './types.js';
1
+ import { NamedFormats, FormatPattern, FormatStyle, MaybeDateInput, Part, FilledPart, Format } from './types.js';
2
2
 
3
3
  /**
4
4
  * A date to use for determining various spec details.
@@ -28,6 +28,10 @@ declare const clock24: FormatPattern[];
28
28
  * 12 hour format patterns.
29
29
  */
30
30
  declare const clock12: FormatPattern[];
31
+ /**
32
+ * Fractional seconds patterns.
33
+ */
34
+ declare const fractionalSeconds: FormatPattern[];
31
35
  /**
32
36
  * Tokens that have a fixed length.
33
37
  */
@@ -42,9 +46,10 @@ declare const fixedLength: {
42
46
  ss: number;
43
47
  };
44
48
  /**
45
- * token Z can have variable length depending on the actual value, so it's
49
+ * Determines the length of a timezone offset string.
50
+ * Supports offsets with optional seconds component.
46
51
  */
47
- declare function fixedLengthByOffset(offsetString: string): 6 | 5;
52
+ declare function fixedLengthByOffset(offsetString: string): 9 | 8 | 6 | 5;
48
53
  /**
49
54
  * Tokens that are genitive — in that they can have "possession" when used in
50
55
  * a date phrase, "March’s 4th day" (but not in english).
@@ -85,19 +90,33 @@ declare const four: (n: number) => string;
85
90
  declare function normStr(part: Intl.DateTimeFormatPart): Intl.DateTimeFormatPart;
86
91
  /**
87
92
  * Returns the parts filled with pertinent values.
88
- * @param inputDate - The date to fill parts for
93
+ * @param [inputDate] - The date to fill parts for
89
94
  * @param parts - An array of parts to fill
90
95
  * @param locale - The locale to fill with.
91
96
  * @param genitive - Whether to use genitive tokens values or not.
92
97
  * @param offset - The explicit offset to fill with (ignores the date’s true offset).
93
98
  */
94
- declare function fill(inputDate: DateInput, parts: Part[], locale: string, genitive?: boolean, offset?: string | null): FilledPart[];
99
+ declare function fill(inputDate: MaybeDateInput, parts: Part[], locale: string, genitive?: boolean, offset?: string | null): FilledPart[];
100
+ /**
101
+ * Converts total seconds to an ISO8601 compatible offset (+04:00 or +0400).
102
+ * Only includes seconds in output if they are non-zero.
103
+ * @param totalSecs - The total offset in seconds (can be negative).
104
+ * @param token - "Z" for +HH:mm[:ss] or "ZZ" for +HHmm[ss]
105
+ */
106
+ declare function secsToOffset(totalSecs: number, token?: string): string;
95
107
  /**
96
108
  * Converts minutes (300) to an ISO8601 compatible offset (+0400 or +04:00).
97
109
  * @param timeDiffInMins - The difference in minutes between two timezones.
98
110
  * @returns
99
111
  */
100
112
  declare function minsToOffset(timeDiffInMins: number, token?: string): string;
113
+ /**
114
+ * Converts an offset (-05:32:11 or -053211) to total seconds.
115
+ * Supports offsets with optional seconds component.
116
+ * @param offset - The offset to convert to seconds.
117
+ * @param token - The timezone token format.
118
+ */
119
+ declare function offsetToSecs(offset: string, token: TimezoneToken): number;
101
120
  /**
102
121
  * Converts an offset (-0500) to minutes (-300).
103
122
  * @param offset - The offset to convert to minutes.
@@ -106,7 +125,8 @@ declare function minsToOffset(timeDiffInMins: number, token?: string): string;
106
125
  declare function offsetToMins(offset: string, token: TimezoneToken): number;
107
126
  /**
108
127
  * Validates that an offset is valid according to the format:
109
- * [+-]HHmm or [+-]HH:mm
128
+ * [+-]HH:mm or [+-]HH:mm:ss (Z token)
129
+ * [+-]HHmm or [+-]HHmmss (ZZ token)
110
130
  * @param offset - The offset to validate.
111
131
  * @param token - The timezone token format.
112
132
  */
@@ -134,4 +154,4 @@ declare function validate(parts: Part[]): Part[] | never;
134
154
  */
135
155
  declare function getOffsetFormat(format: Format): TimezoneToken;
136
156
 
137
- export { type TimezoneToken, clock12, clock24, clockAgnostic, dayPeriodMap, escapeTokens, fill, fixedLength, fixedLengthByOffset, four, genitiveTokens, getOffsetFormat, isNumeric, memoParts, minsToOffset, normStr, offsetToMins, specDate, styles, tokens, two, validOffset, validate };
157
+ export { type TimezoneToken, clock12, clock24, clockAgnostic, dayPeriodMap, escapeTokens, fill, fixedLength, fixedLengthByOffset, four, fractionalSeconds, genitiveTokens, getOffsetFormat, isNumeric, memoParts, minsToOffset, normStr, offsetToMins, offsetToSecs, secsToOffset, specDate, styles, tokens, two, validOffset, validate };
package/dist/common.mjs CHANGED
@@ -32,6 +32,9 @@ var clock12 = [
32
32
  ["a", { dayPeriod: "narrow" }],
33
33
  ["A", { dayPeriod: "narrow" }]
34
34
  ];
35
+ var fractionalSeconds = [
36
+ ["SSS", { fractionalSecond: "3-digit" }]
37
+ ];
35
38
  var fixedLength = {
36
39
  DD: 2,
37
40
  HH: 2,
@@ -43,6 +46,12 @@ var fixedLength = {
43
46
  ss: 2
44
47
  };
45
48
  function fixedLengthByOffset(offsetString) {
49
+ if (/^[+-]\d{2}:\d{2}:\d{2}/.test(offsetString)) {
50
+ return 9;
51
+ }
52
+ if (/^[+-]\d{6}/.test(offsetString)) {
53
+ return 8;
54
+ }
46
55
  if (/^[+-]\d{2}:\d{2}/.test(offsetString)) {
47
56
  return 6;
48
57
  }
@@ -53,17 +62,12 @@ function fixedLengthByOffset(offsetString) {
53
62
  }
54
63
  var genitiveTokens = ["MMMM", "MMM", "dddd", "ddd"];
55
64
  var tokens = /* @__PURE__ */ new Map(
56
- /* @__PURE__ */ [...clockAgnostic, ...clock24, ...clock12].map((format) => {
65
+ /* @__PURE__ */ [...clockAgnostic, ...clock24, ...clock12, ...fractionalSeconds].map((format) => {
57
66
  return [format[0], format];
58
67
  })
59
68
  );
60
69
  var dayPeriodMap = /* @__PURE__ */ new Map();
61
- var styles = [
62
- "full",
63
- "long",
64
- "medium",
65
- "short"
66
- ];
70
+ var styles = ["full", "long", "medium", "short"];
67
71
  var two = (n) => String(n).padStart(2, "0");
68
72
  var four = (n) => String(n).padStart(2, "0");
69
73
  function normStr(part) {
@@ -76,8 +80,7 @@ function fill(inputDate, parts, locale, genitive = false, offset = null) {
76
80
  const partMap = createPartMap(inputDate, parts, locale, genitive);
77
81
  const d = date(inputDate);
78
82
  function value({ partName, partValue, token }) {
79
- if (partName === "literal")
80
- return partValue;
83
+ if (partName === "literal") return partValue;
81
84
  const value2 = partMap[partName];
82
85
  if (partName === "hour" && token === "H") {
83
86
  return value2.replace(/^0/, "") || "0";
@@ -89,6 +92,9 @@ function fill(inputDate, parts, locale, genitive = false, offset = null) {
89
92
  const p = ap(d.getUTCHours() < 12 ? "am" : "pm", locale);
90
93
  return token === "A" ? p.toUpperCase() : p.toLowerCase();
91
94
  }
95
+ if (partName === "fractionalSecond") {
96
+ return String(d.getUTCMilliseconds()).padStart(3, "0");
97
+ }
92
98
  if (partName === "timeZoneName") {
93
99
  return offset != null ? offset : minsToOffset(-1 * d.getTimezoneOffset(), token);
94
100
  }
@@ -114,8 +120,7 @@ function createPartMap(inputDate, parts, locale, genitive = false) {
114
120
  preciseLocale,
115
121
  requestedParts.reduce(
116
122
  (options, part) => {
117
- if (part.partName === "literal")
118
- return options;
123
+ if (part.partName === "literal") return options;
119
124
  if (genitive && genitiveTokens.includes(part.token)) {
120
125
  genitiveParts.push(part);
121
126
  }
@@ -142,9 +147,7 @@ function createPartMap(inputDate, parts, locale, genitive = false) {
142
147
  }).formatToParts(d).map(normStr);
143
148
  break;
144
149
  }
145
- const genitiveFormattedPart = formattedParts.find(
146
- (p) => p.type === part.partName
147
- );
150
+ const genitiveFormattedPart = formattedParts.find((p) => p.type === part.partName);
148
151
  const index = valueParts.findIndex((p) => p.type === part.partName);
149
152
  if (genitiveFormattedPart && index > -1) {
150
153
  valueParts[index] = genitiveFormattedPart;
@@ -152,50 +155,51 @@ function createPartMap(inputDate, parts, locale, genitive = false) {
152
155
  }
153
156
  }
154
157
  }
155
- if (hour12.length)
156
- addValues(hour12, true);
157
- if (hour24.length)
158
- addValues(hour24);
158
+ if (hour12.length) addValues(hour12, true);
159
+ if (hour24.length) addValues(hour24);
159
160
  return valueParts.reduce((map, part) => {
160
161
  map[part.type] = part.value;
161
162
  return map;
162
163
  }, {});
163
164
  }
164
- function minsToOffset(timeDiffInMins, token = "Z") {
165
- const hours = String(Math.floor(Math.abs(timeDiffInMins / 60))).padStart(
166
- 2,
167
- "0"
168
- );
169
- const mins = String(Math.abs(timeDiffInMins % 60)).padStart(2, "0");
170
- const sign = timeDiffInMins < 0 ? "-" : "+";
165
+ function secsToOffset(totalSecs, token = "Z") {
166
+ const sign = totalSecs < 0 ? "-" : "+";
167
+ const absSecs = Math.abs(totalSecs);
168
+ const hours = String(Math.floor(absSecs / 3600)).padStart(2, "0");
169
+ const mins = String(Math.floor(absSecs % 3600 / 60)).padStart(2, "0");
170
+ const secs = Math.round(absSecs % 60);
171
171
  if (token === "ZZ") {
172
- return `${sign}${hours}${mins}`;
172
+ return secs === 0 ? `${sign}${hours}${mins}` : `${sign}${hours}${mins}${String(secs).padStart(2, "0")}`;
173
173
  }
174
- return `${sign}${hours}:${mins}`;
174
+ return secs === 0 ? `${sign}${hours}:${mins}` : `${sign}${hours}:${mins}:${String(secs).padStart(2, "0")}`;
175
175
  }
176
- function offsetToMins(offset, token) {
176
+ function minsToOffset(timeDiffInMins, token = "Z") {
177
+ return secsToOffset(timeDiffInMins * 60, token);
178
+ }
179
+ function offsetToSecs(offset, token) {
177
180
  validOffset(offset, token);
178
- const [_, sign, hours, mins] = offset.match(
179
- /([+-])([0-3][0-9]):?([0-6][0-9])/
180
- );
181
- const offsetInMins = Number(hours) * 60 + Number(mins);
182
- return sign === "+" ? offsetInMins : -offsetInMins;
181
+ const match = offset.match(/([+-])([0-3][0-9]):?([0-5][0-9])(?::?([0-5][0-9]))?/);
182
+ const [_, sign, hours, mins, secs = "0"] = match;
183
+ const totalSecs = Number(hours) * 3600 + Number(mins) * 60 + Number(secs);
184
+ return sign === "+" ? totalSecs : -totalSecs;
185
+ }
186
+ function offsetToMins(offset, token) {
187
+ return Math.round(offsetToSecs(offset, token) / 60);
183
188
  }
184
189
  function validOffset(offset, token = "Z") {
185
190
  const valid = ((token2) => {
186
191
  switch (token2) {
187
192
  case "Z":
188
- return /^([+-])[0-3][0-9]:[0-6][0-9]$/.test(offset);
193
+ return /^([+-])[0-3][0-9]:[0-5][0-9](?::[0-5][0-9])?$/.test(offset);
189
194
  case "ZZ":
190
- return /^([+-])[0-3][0-9][0-6][0-9]$/.test(offset);
195
+ return /^([+-])[0-3][0-9][0-5][0-9](?:[0-5][0-9])?$/.test(offset);
191
196
  }
192
197
  })(token);
193
- if (!valid)
194
- throw new Error(`Invalid offset: ${offset}`);
198
+ if (!valid) throw new Error(`Invalid offset: ${offset}`);
195
199
  return offset;
196
200
  }
197
201
  function escapeTokens(str) {
198
- return clockAgnostic.concat(clock24).concat(clock12).sort((a, b) => a[0].length > b[0].length ? 1 : -1).reduce((target, part) => {
202
+ return clockAgnostic.concat(clock24).concat(clock12).concat(fractionalSeconds).sort((a, b) => a[0].length > b[0].length ? 1 : -1).reduce((target, part) => {
199
203
  return target.replace(part[0], `\\${part[0]}`);
200
204
  }, str);
201
205
  }
@@ -209,10 +213,8 @@ function validate(parts) {
209
213
  throw new Error(`Numbers in format (${part.partValue}).`);
210
214
  }
211
215
  if (lastPart && lastPart.partName !== "literal" && part.partName !== "literal") {
212
- if (!(lastPart.token in fixedLength) && !(part.token in fixedLength) && !(isNumeric(lastPart) && part.token.toLowerCase() === "a")) {
213
- throw new Error(
214
- `Illegal adjacent tokens (${lastPart.token}, ${part.token})`
215
- );
216
+ if (!(lastPart.token in fixedLength) && !(part.token in fixedLength) && !(isNumeric(lastPart) && part.token.toLowerCase() === "a") && lastPart.token !== "SSS") {
217
+ throw new Error(`Illegal adjacent tokens (${lastPart.token}, ${part.token})`);
216
218
  }
217
219
  }
218
220
  lastPart = part;
@@ -235,6 +237,7 @@ export {
235
237
  fixedLength,
236
238
  fixedLengthByOffset,
237
239
  four,
240
+ fractionalSeconds,
238
241
  genitiveTokens,
239
242
  getOffsetFormat,
240
243
  isNumeric,
@@ -242,6 +245,8 @@ export {
242
245
  minsToOffset,
243
246
  normStr,
244
247
  offsetToMins,
248
+ offsetToSecs,
249
+ secsToOffset,
245
250
  specDate,
246
251
  styles,
247
252
  tokens,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/common.ts"],"sourcesContent":["import { date } from \"./date\"\nimport { ap } from \"./ap\"\nimport type {\n DateInput,\n NamedFormats,\n FormatPattern,\n FormatStyle,\n Part,\n FilledPart,\n Format,\n} from \"./types\"\n\n/**\n * A date to use for determining various spec details.\n */\nexport const specDate = \"1999-03-04T02:05:01.000Z\"\n\n/**\n * A cache of Intl tokens and their respective formats.\n */\nexport const memoParts: Map<string, NamedFormats> = new Map()\n\n/**\n * Clock agnostic time format patterns.\n */\nexport const clockAgnostic: FormatPattern[] = [\n [\"YYYY\", { year: \"numeric\" }],\n [\"YY\", { year: \"2-digit\" }],\n [\"MMMM\", { month: \"long\" }],\n [\"MMM\", { month: \"short\" }],\n [\"MM\", { month: \"2-digit\" }],\n [\"M\", { month: \"numeric\" }],\n [\"DD\", { day: \"2-digit\" }],\n [\"D\", { day: \"numeric\" }],\n [\"dddd\", { weekday: \"long\" }],\n [\"ddd\", { weekday: \"short\" }],\n [\"d\", { weekday: \"narrow\" }],\n [\"mm\", { minute: \"2-digit\" }],\n [\"m\", { minute: \"numeric\" }],\n [\"ss\", { second: \"2-digit\" }],\n [\"s\", { second: \"numeric\" }],\n [\"ZZ\", { timeZoneName: \"long\" }],\n [\"Z\", { timeZoneName: \"short\" }],\n]\n\n/**\n * Timezone tokens.\n */\nconst timeZoneTokens = [\"Z\", \"ZZ\"] as const\n\n/**\n * Timezone token type.\n */\nexport type TimezoneToken = (typeof timeZoneTokens)[number]\n\n/**\n * 24 hour click format patterns.\n */\nexport const clock24: FormatPattern[] = [\n [\"HH\", { hour: \"2-digit\" }],\n [\"H\", { hour: \"numeric\" }],\n]\n\n/**\n * 12 hour format patterns.\n */\nexport const clock12: FormatPattern[] = [\n [\"hh\", { hour: \"2-digit\" }],\n [\"h\", { hour: \"numeric\" }],\n [\"a\", { dayPeriod: \"narrow\" }],\n [\"A\", { dayPeriod: \"narrow\" }],\n]\n\n/**\n * Tokens that have a fixed length.\n */\nexport const fixedLength = {\n DD: 2,\n HH: 2,\n MM: 2,\n YY: 2,\n YYYY: 4,\n hh: 2,\n mm: 2,\n ss: 2,\n}\n\n/**\n * token Z can have variable length depending on the actual value, so it's\n */\nexport function fixedLengthByOffset(offsetString: string): 6 | 5 {\n // starts with [+-]xx:xx\n if (/^[+-]\\d{2}:\\d{2}/.test(offsetString)) {\n return 6\n }\n\n // starts with [+-]xxxx\n if (/^[+-]\\d{4}/.test(offsetString)) {\n return 5\n }\n\n throw new Error(\"Invalid offset format\")\n}\n\n/**\n * Tokens that are genitive — in that they can have \"possession\" when used in\n * a date phrase, \"March’s 4th day\" (but not in english).\n *\n * When computing a range for these, the range can be either genitive or not.\n * The same is true for parsing dates containing these tokens.\n */\nexport const genitiveTokens = [\"MMMM\", \"MMM\", \"dddd\", \"ddd\"]\n\n/**\n * A map of FormatPattern tuples to their respective token.\n */\nexport const tokens = /* @__PURE__ */ new Map(\n /* @__PURE__ */ [...clockAgnostic, ...clock24, ...clock12].map((format) => {\n return [format[0], format]\n })\n)\n\n/**\n * A map of locale’s am/pm.\n */\nexport const dayPeriodMap: Map<string, { am?: string; pm?: string }> = new Map()\n\n/**\n * An array of all available date styles.\n */\nexport const styles: ReadonlyArray<FormatStyle> = [\n \"full\",\n \"long\",\n \"medium\",\n \"short\",\n]\n\n/**\n * Creates a leading zero string of 2 digits.\n * @param n - A number.\n */\nexport const two = (n: number) => String(n).padStart(2, \"0\")\n/**\n * Creates a leading zero string of 4 digits.\n * @param n - A number.\n */\nexport const four = (n: number) => String(n).padStart(2, \"0\")\n\n/**\n * Normalizes a given part to NFKC.\n * @param part - The part to normalize.\n */\nexport function normStr(\n part: Intl.DateTimeFormatPart\n): Intl.DateTimeFormatPart {\n if (part.type === \"literal\") {\n part.value = part.value.normalize(\"NFKC\")\n }\n return part\n}\n\n/**\n * Returns the parts filled with pertinent values.\n * @param inputDate - The date to fill parts for\n * @param parts - An array of parts to fill\n * @param locale - The locale to fill with.\n * @param genitive - Whether to use genitive tokens values or not.\n * @param offset - The explicit offset to fill with (ignores the date’s true offset).\n */\nexport function fill(\n inputDate: DateInput,\n parts: Part[],\n locale: string,\n genitive = false,\n offset: string | null = null\n): FilledPart[] {\n const partMap = createPartMap(inputDate, parts, locale, genitive)\n const d = date(inputDate)\n\n /**\n * Not all values get returned \"properly\" as our tokens would suggest. For\n * example, at times Intl returns leading zeros when it shouldn't. This fn\n * is used to clean up those irregular values.\n * @param param - Part\n */\n function value({ partName, partValue, token }: Part) {\n if (partName === \"literal\") return partValue\n const value = partMap[partName]\n if (partName === \"hour\" && token === \"H\") {\n return value.replace(/^0/, \"\") || \"0\"\n }\n if ([\"mm\", \"ss\", \"MM\"].includes(token) && value.length === 1) {\n // Some tokens are supposed to have leading zeros, but Intl doesn't\n // always return them, depending on the locale and the format.\n return `0${value}`\n }\n if (partName === \"dayPeriod\") {\n const p = ap(d.getUTCHours() < 12 ? \"am\" : \"pm\", locale)\n return token === \"A\" ? p.toUpperCase() : p.toLowerCase()\n }\n if (partName === \"timeZoneName\") {\n return offset ?? minsToOffset(-1 * d.getTimezoneOffset(), token)\n }\n return value\n }\n\n return parts.map((part): FilledPart => {\n return {\n ...part,\n value: value(part),\n }\n })\n}\n\n/**\n * Creates a map of part names to their respective values.\n * @param inputDate - The date to format\n * @param parts - The individual parts the need to be formatted.\n * @param locale - The locale to format the parts with.\n * @param genitive - Whether to use genitive tokens values or not.\n */\nfunction createPartMap(\n inputDate: DateInput,\n parts: Part[],\n locale: string,\n genitive = false\n): Record<keyof Intl.DateTimeFormatPartTypesRegistry, string> {\n const d = date(inputDate)\n const hour12 = parts.filter((part) => part.hour12)\n const hour24 = parts.filter((part) => !part.hour12)\n const valueParts: Intl.DateTimeFormatPart[] = []\n const genitiveParts: Part[] = []\n\n function addValues(requestedParts: Part[], hour12 = false) {\n const preciseLocale = `${locale}-u-hc-${hour12 ? \"h12\" : \"h23\"}`\n valueParts.push(\n ...new Intl.DateTimeFormat(\n preciseLocale,\n requestedParts.reduce(\n (options, part) => {\n if (part.partName === \"literal\") return options\n // Side effect! Genitive parts get shoved into a separate array.\n if (genitive && genitiveTokens.includes(part.token)) {\n genitiveParts.push(part)\n }\n return Object.assign(options, part.option)\n },\n { timeZone: \"UTC\" } as Intl.DateTimeFormatOptions\n )\n )\n .formatToParts(d)\n .map(normStr)\n )\n if (genitive && genitiveParts.length) {\n for (const part of genitiveParts) {\n let formattedParts: Intl.DateTimeFormatPart[] = []\n switch (part.token) {\n case \"MMMM\":\n formattedParts = new Intl.DateTimeFormat(preciseLocale, {\n dateStyle: \"long\",\n timeZone: \"UTC\",\n })\n .formatToParts(d)\n .map(normStr)\n break\n case \"MMM\":\n formattedParts = new Intl.DateTimeFormat(preciseLocale, {\n dateStyle: \"medium\",\n timeZone: \"UTC\",\n })\n .formatToParts(d)\n .map(normStr)\n break\n }\n const genitiveFormattedPart = formattedParts.find(\n (p) => p.type === part.partName\n )\n const index = valueParts.findIndex((p) => p.type === part.partName)\n if (genitiveFormattedPart && index > -1) {\n valueParts[index] = genitiveFormattedPart\n }\n }\n }\n }\n\n if (hour12.length) addValues(hour12, true)\n if (hour24.length) addValues(hour24)\n\n return valueParts.reduce((map, part) => {\n map[part.type] = part.value\n return map\n }, {} as Record<keyof Intl.DateTimeFormatPartTypesRegistry, string>)\n}\n\n/**\n * Converts minutes (300) to an ISO8601 compatible offset (+0400 or +04:00).\n * @param timeDiffInMins - The difference in minutes between two timezones.\n * @returns\n */\nexport function minsToOffset(\n timeDiffInMins: number,\n token: string = \"Z\"\n): string {\n const hours = String(Math.floor(Math.abs(timeDiffInMins / 60))).padStart(\n 2,\n \"0\"\n )\n const mins = String(Math.abs(timeDiffInMins % 60)).padStart(2, \"0\")\n const sign = timeDiffInMins < 0 ? \"-\" : \"+\"\n\n if (token === \"ZZ\") {\n return `${sign}${hours}${mins}`\n }\n\n return `${sign}${hours}:${mins}`\n}\n\n/**\n * Converts an offset (-0500) to minutes (-300).\n * @param offset - The offset to convert to minutes.\n * @param token - The timezone token format.\n */\nexport function offsetToMins(offset: string, token: TimezoneToken): number {\n validOffset(offset, token)\n const [_, sign, hours, mins] = offset.match(\n /([+-])([0-3][0-9]):?([0-6][0-9])/\n )!\n const offsetInMins = Number(hours) * 60 + Number(mins)\n return sign === \"+\" ? offsetInMins : -offsetInMins\n}\n\n/**\n * Validates that an offset is valid according to the format:\n * [+-]HHmm or [+-]HH:mm\n * @param offset - The offset to validate.\n * @param token - The timezone token format.\n */\nexport function validOffset(offset: string, token: TimezoneToken = \"Z\") {\n const valid = ((token: TimezoneToken): boolean => {\n switch (token) {\n case \"Z\":\n return /^([+-])[0-3][0-9]:[0-6][0-9]$/.test(offset)\n case \"ZZ\":\n return /^([+-])[0-3][0-9][0-6][0-9]$/.test(offset)\n }\n })(token)\n\n if (!valid) throw new Error(`Invalid offset: ${offset}`)\n return offset\n}\n\n/**\n * Given a string of tokens, escape any characters that are tokens.\n * @param str - The string to escape tokens in.\n * @returns The escaped string.\n */\nexport function escapeTokens(str: string): string {\n return clockAgnostic\n .concat(clock24)\n .concat(clock12)\n .sort((a, b) => (a[0].length > b[0].length ? 1 : -1))\n .reduce((target, part) => {\n return target.replace(part[0], `\\\\${part[0]}`)\n }, str)\n}\n\n/**\n * Checks if a given part should have a numeric value.\n * @param part - A part to check\n */\nexport function isNumeric(part: Part) {\n return [\"numeric\", \"2-digit\"].includes(part.partValue)\n}\n\n/**\n * Validates that an array of Parts can be parsed.\n * @param parts - Parts to validate for parsing ability.\n */\nexport function validate(parts: Part[]): Part[] | never {\n let lastPart: Part | undefined = undefined\n for (const part of parts) {\n if (part.partName === \"literal\" && !isNaN(parseFloat(part.partValue))) {\n throw new Error(`Numbers in format (${part.partValue}).`)\n }\n if (\n lastPart &&\n lastPart.partName !== \"literal\" &&\n part.partName !== \"literal\"\n ) {\n if (\n !(lastPart.token in fixedLength) &&\n !(part.token in fixedLength) &&\n !(isNumeric(lastPart) && part.token.toLowerCase() === \"a\")\n ) {\n throw new Error(\n `Illegal adjacent tokens (${lastPart.token}, ${part.token})`\n )\n }\n }\n lastPart = part\n }\n return parts\n}\n\n/**\n * Returns the timezone token format from a given format.\n * @param format - The format to check.\n * @returns The timezone token format (\"Z\" or \"ZZ\").\n */\nexport function getOffsetFormat(format: Format): TimezoneToken {\n if (typeof format === \"string\") {\n return format.includes(\"ZZ\") ? \"ZZ\" : \"Z\"\n }\n return \"time\" in format && format.time === \"full\" ? \"Z\" : \"ZZ\"\n}\n"],"mappings":"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","names":["value","hour12","token"]}
1
+ {"version":3,"sources":["../src/common.ts"],"sourcesContent":["import { date } from \"./date\"\nimport { ap } from \"./ap\"\nimport type {\n DateInput,\n NamedFormats,\n FormatPattern,\n FormatStyle,\n Part,\n FilledPart,\n Format,\n MaybeDateInput,\n ExtendedPartTypes,\n} from \"./types\"\n\n/**\n * A date to use for determining various spec details.\n */\nexport const specDate = \"1999-03-04T02:05:01.000Z\"\n\n/**\n * A cache of Intl tokens and their respective formats.\n */\nexport const memoParts: Map<string, NamedFormats> = new Map()\n\n/**\n * Clock agnostic time format patterns.\n */\nexport const clockAgnostic: FormatPattern[] = [\n [\"YYYY\", { year: \"numeric\" }],\n [\"YY\", { year: \"2-digit\" }],\n [\"MMMM\", { month: \"long\" }],\n [\"MMM\", { month: \"short\" }],\n [\"MM\", { month: \"2-digit\" }],\n [\"M\", { month: \"numeric\" }],\n [\"DD\", { day: \"2-digit\" }],\n [\"D\", { day: \"numeric\" }],\n [\"dddd\", { weekday: \"long\" }],\n [\"ddd\", { weekday: \"short\" }],\n [\"d\", { weekday: \"narrow\" }],\n [\"mm\", { minute: \"2-digit\" }],\n [\"m\", { minute: \"numeric\" }],\n [\"ss\", { second: \"2-digit\" }],\n [\"s\", { second: \"numeric\" }],\n [\"ZZ\", { timeZoneName: \"long\" }],\n [\"Z\", { timeZoneName: \"short\" }],\n]\n\n/**\n * Timezone tokens.\n */\nconst timeZoneTokens = [\"Z\", \"ZZ\"] as const\n\n/**\n * Timezone token type.\n */\nexport type TimezoneToken = (typeof timeZoneTokens)[number]\n\n/**\n * 24 hour click format patterns.\n */\nexport const clock24: FormatPattern[] = [\n [\"HH\", { hour: \"2-digit\" }],\n [\"H\", { hour: \"numeric\" }],\n]\n\n/**\n * 12 hour format patterns.\n */\nexport const clock12: FormatPattern[] = [\n [\"hh\", { hour: \"2-digit\" }],\n [\"h\", { hour: \"numeric\" }],\n [\"a\", { dayPeriod: \"narrow\" }],\n [\"A\", { dayPeriod: \"narrow\" }],\n]\n\n/**\n * Fractional seconds patterns.\n */\nexport const fractionalSeconds: FormatPattern[] = [\n [\"SSS\", { fractionalSecond: \"3-digit\" }],\n]\n\n/**\n * Tokens that have a fixed length.\n */\nexport const fixedLength = {\n DD: 2,\n HH: 2,\n MM: 2,\n YY: 2,\n YYYY: 4,\n hh: 2,\n mm: 2,\n ss: 2,\n}\n\n/**\n * Determines the length of a timezone offset string.\n * Supports offsets with optional seconds component.\n */\nexport function fixedLengthByOffset(offsetString: string): 9 | 8 | 6 | 5 {\n // starts with [+-]xx:xx:xx (9 chars, Z format with seconds)\n if (/^[+-]\\d{2}:\\d{2}:\\d{2}/.test(offsetString)) {\n return 9\n }\n\n // starts with [+-]xxxxxx (8 chars, ZZ format with seconds)\n if (/^[+-]\\d{6}/.test(offsetString)) {\n return 8\n }\n\n // starts with [+-]xx:xx (6 chars, Z format)\n if (/^[+-]\\d{2}:\\d{2}/.test(offsetString)) {\n return 6\n }\n\n // starts with [+-]xxxx (5 chars, ZZ format)\n if (/^[+-]\\d{4}/.test(offsetString)) {\n return 5\n }\n\n throw new Error(\"Invalid offset format\")\n}\n\n/**\n * Tokens that are genitive — in that they can have \"possession\" when used in\n * a date phrase, \"March’s 4th day\" (but not in english).\n *\n * When computing a range for these, the range can be either genitive or not.\n * The same is true for parsing dates containing these tokens.\n */\nexport const genitiveTokens = [\"MMMM\", \"MMM\", \"dddd\", \"ddd\"]\n\n/**\n * A map of FormatPattern tuples to their respective token.\n */\nexport const tokens = /* @__PURE__ */ new Map(\n /* @__PURE__ */ [...clockAgnostic, ...clock24, ...clock12, ...fractionalSeconds].map((format) => {\n return [format[0], format]\n })\n)\n\n/**\n * A map of locale’s am/pm.\n */\nexport const dayPeriodMap: Map<string, { am?: string; pm?: string }> = new Map()\n\n/**\n * An array of all available date styles.\n */\nexport const styles: ReadonlyArray<FormatStyle> = [\"full\", \"long\", \"medium\", \"short\"]\n\n/**\n * Creates a leading zero string of 2 digits.\n * @param n - A number.\n */\nexport const two = (n: number) => String(n).padStart(2, \"0\")\n/**\n * Creates a leading zero string of 4 digits.\n * @param n - A number.\n */\nexport const four = (n: number) => String(n).padStart(2, \"0\")\n\n/**\n * Normalizes a given part to NFKC.\n * @param part - The part to normalize.\n */\nexport function normStr(part: Intl.DateTimeFormatPart): Intl.DateTimeFormatPart {\n if (part.type === \"literal\") {\n part.value = part.value.normalize(\"NFKC\")\n }\n return part\n}\n\n/**\n * Returns the parts filled with pertinent values.\n * @param [inputDate] - The date to fill parts for\n * @param parts - An array of parts to fill\n * @param locale - The locale to fill with.\n * @param genitive - Whether to use genitive tokens values or not.\n * @param offset - The explicit offset to fill with (ignores the date’s true offset).\n */\nexport function fill(\n inputDate: MaybeDateInput,\n parts: Part[],\n locale: string,\n genitive = false,\n offset: string | null = null\n): FilledPart[] {\n const partMap = createPartMap(inputDate, parts, locale, genitive)\n const d = date(inputDate)\n\n /**\n * Not all values get returned \"properly\" as our tokens would suggest. For\n * example, at times Intl returns leading zeros when it shouldn't. This fn\n * is used to clean up those irregular values.\n * @param param - Part\n */\n function value({ partName, partValue, token }: Part) {\n if (partName === \"literal\") return partValue\n const value = partMap[partName]\n if (partName === \"hour\" && token === \"H\") {\n return value.replace(/^0/, \"\") || \"0\"\n }\n if ([\"mm\", \"ss\", \"MM\"].includes(token) && value.length === 1) {\n // Some tokens are supposed to have leading zeros, but Intl doesn't\n // always return them, depending on the locale and the format.\n return `0${value}`\n }\n if (partName === \"dayPeriod\") {\n const p = ap(d.getUTCHours() < 12 ? \"am\" : \"pm\", locale)\n return token === \"A\" ? p.toUpperCase() : p.toLowerCase()\n }\n if (partName === \"fractionalSecond\") {\n return String(d.getUTCMilliseconds()).padStart(3, \"0\")\n }\n if (partName === \"timeZoneName\") {\n return offset ?? minsToOffset(-1 * d.getTimezoneOffset(), token)\n }\n return value\n }\n\n return parts.map((part): FilledPart => {\n return {\n ...part,\n value: value(part),\n }\n })\n}\n\n/**\n * Creates a map of part names to their respective values.\n * @param [inputDate] - The date to format\n * @param parts - The individual parts the need to be formatted.\n * @param locale - The locale to format the parts with.\n * @param genitive - Whether to use genitive tokens values or not.\n */\nfunction createPartMap(\n inputDate: MaybeDateInput,\n parts: Part[],\n locale: string,\n genitive = false\n): Record<ExtendedPartTypes, string> {\n const d = date(inputDate)\n const hour12 = parts.filter((part) => part.hour12)\n const hour24 = parts.filter((part) => !part.hour12)\n const valueParts: Intl.DateTimeFormatPart[] = []\n const genitiveParts: Part[] = []\n\n function addValues(requestedParts: Part[], hour12 = false) {\n const preciseLocale = `${locale}-u-hc-${hour12 ? \"h12\" : \"h23\"}`\n valueParts.push(\n ...new Intl.DateTimeFormat(\n preciseLocale,\n requestedParts.reduce(\n (options, part) => {\n if (part.partName === \"literal\") return options\n // Side effect! Genitive parts get shoved into a separate array.\n if (genitive && genitiveTokens.includes(part.token)) {\n genitiveParts.push(part)\n }\n return Object.assign(options, part.option)\n },\n { timeZone: \"UTC\" } as Intl.DateTimeFormatOptions\n )\n )\n .formatToParts(d)\n .map(normStr)\n )\n if (genitive && genitiveParts.length) {\n for (const part of genitiveParts) {\n let formattedParts: Intl.DateTimeFormatPart[] = []\n switch (part.token) {\n case \"MMMM\":\n formattedParts = new Intl.DateTimeFormat(preciseLocale, {\n dateStyle: \"long\",\n timeZone: \"UTC\",\n })\n .formatToParts(d)\n .map(normStr)\n break\n case \"MMM\":\n formattedParts = new Intl.DateTimeFormat(preciseLocale, {\n dateStyle: \"medium\",\n timeZone: \"UTC\",\n })\n .formatToParts(d)\n .map(normStr)\n break\n }\n const genitiveFormattedPart = formattedParts.find((p) => p.type === part.partName)\n const index = valueParts.findIndex((p) => p.type === part.partName)\n if (genitiveFormattedPart && index > -1) {\n valueParts[index] = genitiveFormattedPart\n }\n }\n }\n }\n\n if (hour12.length) addValues(hour12, true)\n if (hour24.length) addValues(hour24)\n\n return valueParts.reduce((map, part) => {\n map[part.type as ExtendedPartTypes] = part.value\n return map\n }, {} as Record<ExtendedPartTypes, string>)\n}\n\n/**\n * Converts total seconds to an ISO8601 compatible offset (+04:00 or +0400).\n * Only includes seconds in output if they are non-zero.\n * @param totalSecs - The total offset in seconds (can be negative).\n * @param token - \"Z\" for +HH:mm[:ss] or \"ZZ\" for +HHmm[ss]\n */\nexport function secsToOffset(totalSecs: number, token: string = \"Z\"): string {\n const sign = totalSecs < 0 ? \"-\" : \"+\"\n const absSecs = Math.abs(totalSecs)\n const hours = String(Math.floor(absSecs / 3600)).padStart(2, \"0\")\n const mins = String(Math.floor((absSecs % 3600) / 60)).padStart(2, \"0\")\n const secs = Math.round(absSecs % 60)\n\n if (token === \"ZZ\") {\n return secs === 0\n ? `${sign}${hours}${mins}`\n : `${sign}${hours}${mins}${String(secs).padStart(2, \"0\")}`\n }\n return secs === 0\n ? `${sign}${hours}:${mins}`\n : `${sign}${hours}:${mins}:${String(secs).padStart(2, \"0\")}`\n}\n\n/**\n * Converts minutes (300) to an ISO8601 compatible offset (+0400 or +04:00).\n * @param timeDiffInMins - The difference in minutes between two timezones.\n * @returns\n */\nexport function minsToOffset(timeDiffInMins: number, token: string = \"Z\"): string {\n return secsToOffset(timeDiffInMins * 60, token)\n}\n\n/**\n * Converts an offset (-05:32:11 or -053211) to total seconds.\n * Supports offsets with optional seconds component.\n * @param offset - The offset to convert to seconds.\n * @param token - The timezone token format.\n */\nexport function offsetToSecs(offset: string, token: TimezoneToken): number {\n validOffset(offset, token)\n const match = offset.match(/([+-])([0-3][0-9]):?([0-5][0-9])(?::?([0-5][0-9]))?/)!\n const [_, sign, hours, mins, secs = \"0\"] = match\n const totalSecs = Number(hours) * 3600 + Number(mins) * 60 + Number(secs)\n return sign === \"+\" ? totalSecs : -totalSecs\n}\n\n/**\n * Converts an offset (-0500) to minutes (-300).\n * @param offset - The offset to convert to minutes.\n * @param token - The timezone token format.\n */\nexport function offsetToMins(offset: string, token: TimezoneToken): number {\n return Math.round(offsetToSecs(offset, token) / 60)\n}\n\n/**\n * Validates that an offset is valid according to the format:\n * [+-]HH:mm or [+-]HH:mm:ss (Z token)\n * [+-]HHmm or [+-]HHmmss (ZZ token)\n * @param offset - The offset to validate.\n * @param token - The timezone token format.\n */\nexport function validOffset(offset: string, token: TimezoneToken = \"Z\") {\n const valid = ((token: TimezoneToken): boolean => {\n switch (token) {\n case \"Z\":\n return /^([+-])[0-3][0-9]:[0-5][0-9](?::[0-5][0-9])?$/.test(offset)\n case \"ZZ\":\n return /^([+-])[0-3][0-9][0-5][0-9](?:[0-5][0-9])?$/.test(offset)\n }\n })(token)\n\n if (!valid) throw new Error(`Invalid offset: ${offset}`)\n return offset\n}\n\n/**\n * Given a string of tokens, escape any characters that are tokens.\n * @param str - The string to escape tokens in.\n * @returns The escaped string.\n */\nexport function escapeTokens(str: string): string {\n return clockAgnostic\n .concat(clock24)\n .concat(clock12)\n .concat(fractionalSeconds)\n .sort((a, b) => (a[0].length > b[0].length ? 1 : -1))\n .reduce((target, part) => {\n return target.replace(part[0], `\\\\${part[0]}`)\n }, str)\n}\n\n/**\n * Checks if a given part should have a numeric value.\n * @param part - A part to check\n */\nexport function isNumeric(part: Part) {\n return [\"numeric\", \"2-digit\"].includes(part.partValue)\n}\n\n/**\n * Validates that an array of Parts can be parsed.\n * @param parts - Parts to validate for parsing ability.\n */\nexport function validate(parts: Part[]): Part[] | never {\n let lastPart: Part | undefined = undefined\n for (const part of parts) {\n if (part.partName === \"literal\" && !isNaN(parseFloat(part.partValue))) {\n throw new Error(`Numbers in format (${part.partValue}).`)\n }\n if (lastPart && lastPart.partName !== \"literal\" && part.partName !== \"literal\") {\n if (\n !(lastPart.token in fixedLength) &&\n !(part.token in fixedLength) &&\n !(isNumeric(lastPart) && part.token.toLowerCase() === \"a\") &&\n lastPart.token !== \"SSS\" // SSS can be followed by anything (greedy digit consumer)\n ) {\n throw new Error(`Illegal adjacent tokens (${lastPart.token}, ${part.token})`)\n }\n }\n lastPart = part\n }\n return parts\n}\n\n/**\n * Returns the timezone token format from a given format.\n * @param format - The format to check.\n * @returns The timezone token format (\"Z\" or \"ZZ\").\n */\nexport function getOffsetFormat(format: Format): TimezoneToken {\n if (typeof format === \"string\") {\n return format.includes(\"ZZ\") ? \"ZZ\" : \"Z\"\n }\n return \"time\" in format && format.time === \"full\" ? \"Z\" : \"ZZ\"\n}\n"],"mappings":"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","names":["value","hour12","token"]}
package/dist/date.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { DateInput } from './types.js';
1
+ import { MaybeDateInput } from './types.js';
2
2
 
3
3
  /**
4
4
  * A date to parse.
5
5
  * @param date - A Date object or an ISO 8601 date.
6
6
  */
7
- declare function date(date?: DateInput): Date;
7
+ declare function date(date?: MaybeDateInput): Date;
8
8
 
9
9
  export { date };
package/dist/date.mjs CHANGED
@@ -12,9 +12,7 @@ function date(date2) {
12
12
  date2 = /* @__PURE__ */ new Date();
13
13
  }
14
14
  if (date2 instanceof Date) {
15
- const d = new Date(date2);
16
- d.setMilliseconds(0);
17
- return d;
15
+ return new Date(date2);
18
16
  }
19
17
  date2 = date2.trim();
20
18
  if (iso8601(date2)) {
package/dist/date.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/date.ts"],"sourcesContent":["import { iso8601, iso8601Match } from \"./iso8601\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Normalizes a \"short\" date like 2012-01-01 to 2012-01-01T00:00:00 to prevent\n * automatic coercion to UTC.\n * @param date - A string representation of the date.\n */\nfunction normalize(date: string) {\n const matches = date.match(iso8601Match)\n if (matches && typeof matches[4] === \"undefined\") {\n return (date += \"T00:00:00\")\n }\n return date\n}\n\n/**\n * A date to parse.\n * @param date - A Date object or an ISO 8601 date.\n */\nexport function date(date?: DateInput): Date {\n if (!date) {\n date = new Date()\n }\n if (date instanceof Date) {\n const d = new Date(date)\n d.setMilliseconds(0)\n return d\n }\n date = date.trim()\n if (iso8601(date)) {\n return new Date(normalize(date))\n }\n throw new Error(`Non ISO 8601 compliant date (${date}).`)\n}\n"],"mappings":";AAAA,SAAS,SAAS,oBAAoB;AAQtC,SAAS,UAAUA,OAAc;AAC/B,QAAM,UAAUA,MAAK,MAAM,YAAY;AACvC,MAAI,WAAW,OAAO,QAAQ,CAAC,MAAM,aAAa;AAChD,WAAQA,SAAQ;AAAA,EAClB;AACA,SAAOA;AACT;AAMO,SAAS,KAAKA,OAAwB;AAC3C,MAAI,CAACA,OAAM;AACT,IAAAA,QAAO,oBAAI,KAAK;AAAA,EAClB;AACA,MAAIA,iBAAgB,MAAM;AACxB,UAAM,IAAI,IAAI,KAAKA,KAAI;AACvB,MAAE,gBAAgB,CAAC;AACnB,WAAO;AAAA,EACT;AACA,EAAAA,QAAOA,MAAK,KAAK;AACjB,MAAI,QAAQA,KAAI,GAAG;AACjB,WAAO,IAAI,KAAK,UAAUA,KAAI,CAAC;AAAA,EACjC;AACA,QAAM,IAAI,MAAM,gCAAgCA,KAAI,IAAI;AAC1D;","names":["date"]}
1
+ {"version":3,"sources":["../src/date.ts"],"sourcesContent":["import { iso8601, iso8601Match } from \"./iso8601\"\nimport type { MaybeDateInput } from \"./types\"\n\n/**\n * Normalizes a \"short\" date like 2012-01-01 to 2012-01-01T00:00:00 to prevent\n * automatic coercion to UTC.\n * @param date - A string representation of the date.\n */\nfunction normalize(date: string) {\n const matches = date.match(iso8601Match)\n if (matches && typeof matches[4] === \"undefined\") {\n return (date += \"T00:00:00\")\n }\n return date\n}\n\n/**\n * A date to parse.\n * @param date - A Date object or an ISO 8601 date.\n */\nexport function date(date?: MaybeDateInput): Date {\n if (!date) {\n date = new Date()\n }\n if (date instanceof Date) {\n return new Date(date)\n }\n date = date.trim()\n if (iso8601(date)) {\n return new Date(normalize(date))\n }\n throw new Error(`Non ISO 8601 compliant date (${date}).`)\n}\n"],"mappings":";AAAA,SAAS,SAAS,oBAAoB;AAQtC,SAAS,UAAUA,OAAc;AAC/B,QAAM,UAAUA,MAAK,MAAM,YAAY;AACvC,MAAI,WAAW,OAAO,QAAQ,CAAC,MAAM,aAAa;AAChD,WAAQA,SAAQ;AAAA,EAClB;AACA,SAAOA;AACT;AAMO,SAAS,KAAKA,OAA6B;AAChD,MAAI,CAACA,OAAM;AACT,IAAAA,QAAO,oBAAI,KAAK;AAAA,EAClB;AACA,MAAIA,iBAAgB,MAAM;AACxB,WAAO,IAAI,KAAKA,KAAI;AAAA,EACtB;AACA,EAAAA,QAAOA,MAAK,KAAK;AACjB,MAAI,QAAQA,KAAI,GAAG;AACjB,WAAO,IAAI,KAAK,UAAUA,KAAI,CAAC;AAAA,EACjC;AACA,QAAM,IAAI,MAAM,gCAAgCA,KAAI,IAAI;AAC1D;","names":["date"]}
package/dist/dayEnd.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { DateInput } from './types.js';
1
+ import { MaybeDateInput } from './types.js';
2
2
 
3
3
  /**
4
4
  * Returns a Date object for end of the given day.
5
- * @param inputDate - A string or Date object
5
+ * @param [inputDate] - A string, Date object or nothing for the current day
6
6
  */
7
- declare function dayEnd(inputDate: DateInput): Date;
7
+ declare function dayEnd(inputDate?: MaybeDateInput): Date;
8
8
 
9
9
  export { dayEnd };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dayEnd.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Returns a Date object for end of the given day.\n * @param inputDate - A string or Date object\n */\nexport function dayEnd(inputDate: DateInput): Date {\n const d = date(inputDate)\n d.setHours(23, 59, 59, 999)\n return d\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAOd,SAAS,OAAO,WAA4B;AACjD,QAAM,IAAI,KAAK,SAAS;AACxB,IAAE,SAAS,IAAI,IAAI,IAAI,GAAG;AAC1B,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/dayEnd.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { MaybeDateInput } from \"./types\"\n\n/**\n * Returns a Date object for end of the given day.\n * @param [inputDate] - A string, Date object or nothing for the current day\n */\nexport function dayEnd(inputDate?: MaybeDateInput): Date {\n const d = date(inputDate)\n d.setHours(23, 59, 59, 999)\n return d\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAOd,SAAS,OAAO,WAAkC;AACvD,QAAM,IAAI,KAAK,SAAS;AACxB,IAAE,SAAS,IAAI,IAAI,IAAI,GAAG;AAC1B,SAAO;AACT;","names":[]}
@@ -1,10 +1,10 @@
1
- import { DateInput } from './types.js';
1
+ import { MaybeDateInput } from './types.js';
2
2
 
3
3
  /**
4
4
  * Gets the what day of the year a given date is. For example, August 1st is
5
5
  * the 213th day of the year on non- years and 214th on leap years.
6
- * @param inputDate - The input date.
6
+ * @param [inputDate] - The input date or nothing for the current day.
7
7
  */
8
- declare function dayOfYear(inputDate: DateInput): number;
8
+ declare function dayOfYear(inputDate?: MaybeDateInput): number;
9
9
 
10
10
  export { dayOfYear };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dayOfYear.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Gets the what day of the year a given date is. For example, August 1st is\n * the 213th day of the year on non- years and 214th on leap years.\n * @param inputDate - The input date.\n */\nexport function dayOfYear(inputDate: DateInput): number {\n const d = date(inputDate)\n return Math.round(\n (new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0).getTime() -\n new Date(d.getFullYear(), 0, 0).getTime()) /\n 86400000\n )\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAQd,SAAS,UAAU,WAA8B;AACtD,QAAM,IAAI,KAAK,SAAS;AACxB,SAAO,KAAK;AAAA,KACT,IAAI,KAAK,EAAE,YAAY,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,GAAG,GAAG,CAAC,EAAE,QAAQ,IAClE,IAAI,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,EAAE,QAAQ,KACxC;AAAA,EACJ;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/dayOfYear.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { MaybeDateInput } from \"./types\"\n\n/**\n * Gets the what day of the year a given date is. For example, August 1st is\n * the 213th day of the year on non- years and 214th on leap years.\n * @param [inputDate] - The input date or nothing for the current day.\n */\nexport function dayOfYear(inputDate?: MaybeDateInput): number {\n const d = date(inputDate)\n return Math.round(\n (new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0, 0).getTime() -\n new Date(d.getFullYear(), 0, 0).getTime()) /\n 86400000\n )\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAQd,SAAS,UAAU,WAAoC;AAC5D,QAAM,IAAI,KAAK,SAAS;AACxB,SAAO,KAAK;AAAA,KACT,IAAI,KAAK,EAAE,YAAY,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ,GAAG,GAAG,CAAC,EAAE,QAAQ,IAClE,IAAI,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC,EAAE,QAAQ,KACxC;AAAA,EACJ;AACF;","names":[]}
@@ -1,9 +1,9 @@
1
- import { DateInput } from './types.js';
1
+ import { MaybeDateInput } from './types.js';
2
2
 
3
3
  /**
4
4
  * Returns a Date object for start of the given day.
5
- * @param inputDate - A string or Date object
5
+ * @param [inputDate] - A string, Date object or nothing for the current day
6
6
  */
7
- declare function dayStart(inputDate: DateInput): Date;
7
+ declare function dayStart(inputDate?: MaybeDateInput): Date;
8
8
 
9
9
  export { dayStart };
package/dist/dayStart.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import { date } from "./date.mjs";
3
3
  function dayStart(inputDate) {
4
4
  const d = date(inputDate);
5
- d.setHours(0, 0, 0);
5
+ d.setHours(0, 0, 0, 0);
6
6
  return d;
7
7
  }
8
8
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/dayStart.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { DateInput } from \"./types\"\n\n/**\n * Returns a Date object for start of the given day.\n * @param inputDate - A string or Date object\n */\nexport function dayStart(inputDate: DateInput): Date {\n const d = date(inputDate)\n d.setHours(0, 0, 0)\n return d\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAOd,SAAS,SAAS,WAA4B;AACnD,QAAM,IAAI,KAAK,SAAS;AACxB,IAAE,SAAS,GAAG,GAAG,CAAC;AAClB,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/dayStart.ts"],"sourcesContent":["import { date } from \"./date\"\nimport type { MaybeDateInput } from \"./types\"\n\n/**\n * Returns a Date object for start of the given day.\n * @param [inputDate] - A string, Date object or nothing for the current day\n */\nexport function dayStart(inputDate?: MaybeDateInput): Date {\n const d = date(inputDate)\n d.setHours(0, 0, 0, 0)\n return d\n}\n"],"mappings":";AAAA,SAAS,YAAY;AAOd,SAAS,SAAS,WAAkC;AACzD,QAAM,IAAI,KAAK,SAAS;AACxB,IAAE,SAAS,GAAG,GAAG,GAAG,CAAC;AACrB,SAAO;AACT;","names":[]}
package/dist/diff.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { Duration, DateInput, MaybeDateInput } from './types.js';
2
+
3
+ type DurationKey = keyof Duration;
4
+ /**
5
+ * Options for `diff` function
6
+ */
7
+ interface DiffOptions {
8
+ /**
9
+ * whether the difference should be absolute (not negative)
10
+ */
11
+ abs?: boolean;
12
+ /**
13
+ * units you want to skip, for example weeks
14
+ */
15
+ skip?: DurationKey[] | Set<DurationKey>;
16
+ }
17
+ /**
18
+ * Returns the difference between 2 dates in an object
19
+ * @param dateA - A date to compare with the right date
20
+ * @param [dateB] - A date to compare with the left date or nothing to compare with the current time
21
+ * @param [options] additional options
22
+ * @param [options.skip] units you want skip
23
+ * @param [options.abs] whether the difference should be absolute
24
+ * @returns an object which could be used with `Intl.DurationFormat.format'`
25
+ */
26
+ declare function diff(dateA: DateInput, dateB?: MaybeDateInput, options?: DiffOptions): Duration;
27
+ /**
28
+ * Returns the difference between 2 dates in an object
29
+ * @param [dateA] - A date to compare with the right date or null to compare with the current time
30
+ * @param dateB - A date to compare with the left date
31
+ * @param [options] additional options
32
+ * @param [options.skip] units you want skip
33
+ * @param [options.abs] whether the difference should be absolute
34
+ * @returns an object which could be used with `Intl.DurationFormat.format'`
35
+ */
36
+ declare function diff(dateA: MaybeDateInput, dateB: DateInput, options?: DiffOptions): Duration;
37
+
38
+ export { type DiffOptions, diff };
package/dist/diff.mjs ADDED
@@ -0,0 +1,86 @@
1
+ // src/diff.ts
2
+ import { addDay } from "./addDay.mjs";
3
+ import { addHour } from "./addHour.mjs";
4
+ import { addMinute } from "./addMinute.mjs";
5
+ import { addMonth } from "./addMonth.mjs";
6
+ import { addSecond } from "./addSecond.mjs";
7
+ import { addYear } from "./addYear.mjs";
8
+ import { date } from "./date.mjs";
9
+ import { diffDays } from "./diffDays.mjs";
10
+ import { diffHours } from "./diffHours.mjs";
11
+ import { diffMilliseconds } from "./diffMilliseconds.mjs";
12
+ import { diffMinutes } from "./diffMinutes.mjs";
13
+ import { diffMonths } from "./diffMonths.mjs";
14
+ import { diffSeconds } from "./diffSeconds.mjs";
15
+ import { diffWeeks } from "./diffWeeks.mjs";
16
+ import { diffYears } from "./diffYears.mjs";
17
+ function negateDuration(duration) {
18
+ const negated = {};
19
+ for (const unit of Object.keys(duration)) {
20
+ negated[unit] = -duration[unit];
21
+ }
22
+ return negated;
23
+ }
24
+ function calendarDiff(current, target, diffUnit, addUnit) {
25
+ let amount = diffUnit(current, target);
26
+ let next = addUnit(current, -amount);
27
+ while (amount > 0 && next < target) {
28
+ amount--;
29
+ next = addUnit(current, -amount);
30
+ }
31
+ return [amount, next];
32
+ }
33
+ function diff(dateA, dateB, options) {
34
+ let a = date(dateA);
35
+ let b = date(dateB);
36
+ if (a < b) {
37
+ const duration2 = diff(b, a, options);
38
+ return (options == null ? void 0 : options.abs) ? duration2 : negateDuration(duration2);
39
+ }
40
+ const skip = new Set(options == null ? void 0 : options.skip);
41
+ const duration = {};
42
+ if (!skip.has("years")) {
43
+ const [years, next] = calendarDiff(a, b, diffYears, addYear);
44
+ a = next;
45
+ if (years) duration.years = years;
46
+ }
47
+ if (!skip.has("months")) {
48
+ const [months, next] = calendarDiff(a, b, diffMonths, addMonth);
49
+ a = next;
50
+ if (months) duration.months = months;
51
+ }
52
+ if (!skip.has("weeks")) {
53
+ const weeks = diffWeeks(a, b);
54
+ a = addDay(a, -(weeks * 7));
55
+ if (weeks) duration.weeks = weeks;
56
+ }
57
+ if (!skip.has("days")) {
58
+ const days = diffDays(a, b);
59
+ a = addDay(a, -days);
60
+ if (days) duration.days = days;
61
+ }
62
+ if (!skip.has("hours")) {
63
+ const hours = diffHours(a, b);
64
+ a = addHour(a, -hours);
65
+ if (hours) duration.hours = hours;
66
+ }
67
+ if (!skip.has("minutes")) {
68
+ const minutes = diffMinutes(a, b);
69
+ a = addMinute(a, -minutes);
70
+ if (minutes) duration.minutes = minutes;
71
+ }
72
+ if (!skip.has("seconds")) {
73
+ const seconds = diffSeconds(a, b);
74
+ a = addSecond(a, -seconds);
75
+ if (seconds) duration.seconds = seconds;
76
+ }
77
+ if (!skip.has("milliseconds")) {
78
+ const ms = diffMilliseconds(a, b);
79
+ if (ms) duration.milliseconds = ms;
80
+ }
81
+ return duration;
82
+ }
83
+ export {
84
+ diff
85
+ };
86
+ //# sourceMappingURL=diff.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/diff.ts"],"sourcesContent":["import { addDay } from \"./addDay\"\nimport { addHour } from \"./addHour\"\nimport { addMinute } from \"./addMinute\"\nimport { addMonth } from \"./addMonth\"\nimport { addSecond } from \"./addSecond\"\nimport { addYear } from \"./addYear\"\nimport { date } from \"./date\"\nimport { diffDays } from \"./diffDays\"\nimport { diffHours } from \"./diffHours\"\nimport { diffMilliseconds } from \"./diffMilliseconds\"\nimport { diffMinutes } from \"./diffMinutes\"\nimport { diffMonths } from \"./diffMonths\"\nimport { diffSeconds } from \"./diffSeconds\"\nimport { diffWeeks } from \"./diffWeeks\"\nimport { diffYears } from \"./diffYears\"\nimport type { DateInput, Duration, MaybeDateInput } from \"./types\"\n\ntype DurationKey = keyof Duration\n\nfunction negateDuration(duration: Duration): Duration {\n const negated: Duration = {}\n for (const unit of Object.keys(duration) as DurationKey[]) {\n negated[unit] = -duration[unit]!\n }\n return negated\n}\n\nfunction calendarDiff(\n current: Date,\n target: Date,\n diffUnit: (dateA: Date, dateB: Date) => number,\n addUnit: (date: Date, count: number) => Date\n): [number, Date] {\n let amount = diffUnit(current, target)\n let next = addUnit(current, -amount)\n while (amount > 0 && next < target) {\n amount--\n next = addUnit(current, -amount)\n }\n return [amount, next]\n}\n\n/**\n * Options for `diff` function\n */\nexport interface DiffOptions {\n /**\n * whether the difference should be absolute (not negative)\n */\n abs?: boolean\n /**\n * units you want to skip, for example weeks\n */\n skip?: DurationKey[] | Set<DurationKey>\n}\n\n/**\n * Returns the difference between 2 dates in an object\n * @param dateA - A date to compare with the right date\n * @param [dateB] - A date to compare with the left date or nothing to compare with the current time\n * @param [options] additional options\n * @param [options.skip] units you want skip\n * @param [options.abs] whether the difference should be absolute\n * @returns an object which could be used with `Intl.DurationFormat.format'`\n */\nexport function diff(\n dateA: DateInput,\n dateB?: MaybeDateInput,\n options?: DiffOptions\n): Duration\n\n/**\n * Returns the difference between 2 dates in an object\n * @param [dateA] - A date to compare with the right date or null to compare with the current time\n * @param dateB - A date to compare with the left date\n * @param [options] additional options\n * @param [options.skip] units you want skip\n * @param [options.abs] whether the difference should be absolute\n * @returns an object which could be used with `Intl.DurationFormat.format'`\n */\nexport function diff(\n dateA: MaybeDateInput,\n dateB: DateInput,\n options?: DiffOptions\n): Duration\n\nexport function diff(\n dateA: MaybeDateInput,\n dateB?: MaybeDateInput,\n options?: DiffOptions\n): Duration {\n let a = date(dateA)\n let b = date(dateB)\n\n if (a < b) {\n const duration = diff(b, a, options)\n return options?.abs ? duration : negateDuration(duration)\n }\n\n const skip = new Set(options?.skip)\n const duration: Duration = {}\n\n if (!skip.has(\"years\")) {\n const [years, next] = calendarDiff(a, b, diffYears, addYear)\n a = next\n if (years) duration.years = years\n }\n\n if (!skip.has(\"months\")) {\n const [months, next] = calendarDiff(a, b, diffMonths, addMonth)\n a = next\n if (months) duration.months = months\n }\n\n if (!skip.has(\"weeks\")) {\n const weeks = diffWeeks(a, b)\n a = addDay(a, -(weeks * 7))\n if (weeks) duration.weeks = weeks\n }\n\n if (!skip.has(\"days\")) {\n const days = diffDays(a, b)\n a = addDay(a, -days)\n if (days) duration.days = days\n }\n\n if (!skip.has(\"hours\")) {\n const hours = diffHours(a, b)\n a = addHour(a, -hours)\n if (hours) duration.hours = hours\n }\n\n if (!skip.has(\"minutes\")) {\n const minutes = diffMinutes(a, b)\n a = addMinute(a, -minutes)\n if (minutes) duration.minutes = minutes\n }\n\n if (!skip.has(\"seconds\")) {\n const seconds = diffSeconds(a, b)\n a = addSecond(a, -seconds)\n if (seconds) duration.seconds = seconds\n }\n\n if (!skip.has(\"milliseconds\")) {\n const ms = diffMilliseconds(a, b)\n // removing ms isn't needed as it's the last\n if (ms) duration.milliseconds = ms\n }\n return duration\n}\n"],"mappings":";AAAA,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC,SAAS,mBAAmB;AAC5B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAK1B,SAAS,eAAe,UAA8B;AACpD,QAAM,UAAoB,CAAC;AAC3B,aAAW,QAAQ,OAAO,KAAK,QAAQ,GAAoB;AACzD,YAAQ,IAAI,IAAI,CAAC,SAAS,IAAI;AAAA,EAChC;AACA,SAAO;AACT;AAEA,SAAS,aACP,SACA,QACA,UACA,SACgB;AAChB,MAAI,SAAS,SAAS,SAAS,MAAM;AACrC,MAAI,OAAO,QAAQ,SAAS,CAAC,MAAM;AACnC,SAAO,SAAS,KAAK,OAAO,QAAQ;AAClC;AACA,WAAO,QAAQ,SAAS,CAAC,MAAM;AAAA,EACjC;AACA,SAAO,CAAC,QAAQ,IAAI;AACtB;AA8CO,SAAS,KACd,OACA,OACA,SACU;AACV,MAAI,IAAI,KAAK,KAAK;AAClB,MAAI,IAAI,KAAK,KAAK;AAElB,MAAI,IAAI,GAAG;AACT,UAAMA,YAAW,KAAK,GAAG,GAAG,OAAO;AACnC,YAAO,mCAAS,OAAMA,YAAW,eAAeA,SAAQ;AAAA,EAC1D;AAEA,QAAM,OAAO,IAAI,IAAI,mCAAS,IAAI;AAClC,QAAM,WAAqB,CAAC;AAE5B,MAAI,CAAC,KAAK,IAAI,OAAO,GAAG;AACtB,UAAM,CAAC,OAAO,IAAI,IAAI,aAAa,GAAG,GAAG,WAAW,OAAO;AAC3D,QAAI;AACJ,QAAI,MAAO,UAAS,QAAQ;AAAA,EAC9B;AAEA,MAAI,CAAC,KAAK,IAAI,QAAQ,GAAG;AACvB,UAAM,CAAC,QAAQ,IAAI,IAAI,aAAa,GAAG,GAAG,YAAY,QAAQ;AAC9D,QAAI;AACJ,QAAI,OAAQ,UAAS,SAAS;AAAA,EAChC;AAEA,MAAI,CAAC,KAAK,IAAI,OAAO,GAAG;AACtB,UAAM,QAAQ,UAAU,GAAG,CAAC;AAC5B,QAAI,OAAO,GAAG,EAAE,QAAQ,EAAE;AAC1B,QAAI,MAAO,UAAS,QAAQ;AAAA,EAC9B;AAEA,MAAI,CAAC,KAAK,IAAI,MAAM,GAAG;AACrB,UAAM,OAAO,SAAS,GAAG,CAAC;AAC1B,QAAI,OAAO,GAAG,CAAC,IAAI;AACnB,QAAI,KAAM,UAAS,OAAO;AAAA,EAC5B;AAEA,MAAI,CAAC,KAAK,IAAI,OAAO,GAAG;AACtB,UAAM,QAAQ,UAAU,GAAG,CAAC;AAC5B,QAAI,QAAQ,GAAG,CAAC,KAAK;AACrB,QAAI,MAAO,UAAS,QAAQ;AAAA,EAC9B;AAEA,MAAI,CAAC,KAAK,IAAI,SAAS,GAAG;AACxB,UAAM,UAAU,YAAY,GAAG,CAAC;AAChC,QAAI,UAAU,GAAG,CAAC,OAAO;AACzB,QAAI,QAAS,UAAS,UAAU;AAAA,EAClC;AAEA,MAAI,CAAC,KAAK,IAAI,SAAS,GAAG;AACxB,UAAM,UAAU,YAAY,GAAG,CAAC;AAChC,QAAI,UAAU,GAAG,CAAC,OAAO;AACzB,QAAI,QAAS,UAAS,UAAU;AAAA,EAClC;AAEA,MAAI,CAAC,KAAK,IAAI,cAAc,GAAG;AAC7B,UAAM,KAAK,iBAAiB,GAAG,CAAC;AAEhC,QAAI,GAAI,UAAS,eAAe;AAAA,EAClC;AACA,SAAO;AACT;","names":["duration"]}