@stridge/noctis-intl 1.0.0-beta.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 (82) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +41 -0
  3. package/dist/date/CalendarDate.d.ts +211 -0
  4. package/dist/date/CalendarDate.js +340 -0
  5. package/dist/date/DateFormatter.d.ts +26 -0
  6. package/dist/date/DateFormatter.js +114 -0
  7. package/dist/date/calendars/BuddhistCalendar.d.ts +20 -0
  8. package/dist/date/calendars/BuddhistCalendar.js +33 -0
  9. package/dist/date/calendars/EthiopicCalendar.d.ts +49 -0
  10. package/dist/date/calendars/EthiopicCalendar.js +129 -0
  11. package/dist/date/calendars/GregorianCalendar.d.ts +26 -0
  12. package/dist/date/calendars/GregorianCalendar.js +117 -0
  13. package/dist/date/calendars/HebrewCalendar.d.ts +25 -0
  14. package/dist/date/calendars/HebrewCalendar.js +114 -0
  15. package/dist/date/calendars/IndianCalendar.d.ts +21 -0
  16. package/dist/date/calendars/IndianCalendar.js +75 -0
  17. package/dist/date/calendars/IslamicCalendar.d.ts +55 -0
  18. package/dist/date/calendars/IslamicCalendar.js +162 -0
  19. package/dist/date/calendars/JapaneseCalendar.d.ts +26 -0
  20. package/dist/date/calendars/JapaneseCalendar.js +154 -0
  21. package/dist/date/calendars/PersianCalendar.d.ts +23 -0
  22. package/dist/date/calendars/PersianCalendar.js +63 -0
  23. package/dist/date/calendars/TaiwanCalendar.d.ts +23 -0
  24. package/dist/date/calendars/TaiwanCalendar.js +51 -0
  25. package/dist/date/conversion.d.ts +41 -0
  26. package/dist/date/conversion.js +181 -0
  27. package/dist/date/createCalendar.d.ts +7 -0
  28. package/dist/date/createCalendar.js +30 -0
  29. package/dist/date/manipulation.js +274 -0
  30. package/dist/date/queries.d.ts +92 -0
  31. package/dist/date/queries.js +233 -0
  32. package/dist/date/string.d.ts +36 -0
  33. package/dist/date/string.js +162 -0
  34. package/dist/date/types.d.ts +138 -0
  35. package/dist/date/utils.d.ts +4 -0
  36. package/dist/date/utils.js +6 -0
  37. package/dist/date/weekStartData.js +100 -0
  38. package/dist/date.d.ts +17 -0
  39. package/dist/date.js +16 -0
  40. package/dist/i18n/context.d.ts +17 -0
  41. package/dist/i18n/context.js +13 -0
  42. package/dist/i18n/use-collator.d.ts +8 -0
  43. package/dist/i18n/use-collator.js +19 -0
  44. package/dist/i18n/use-date-formatter.d.ts +14 -0
  45. package/dist/i18n/use-date-formatter.js +25 -0
  46. package/dist/i18n/use-deep-memo.d.ts +8 -0
  47. package/dist/i18n/use-deep-memo.js +15 -0
  48. package/dist/i18n/use-filter.d.ts +17 -0
  49. package/dist/i18n/use-filter.js +49 -0
  50. package/dist/i18n/use-list-formatter.d.ts +5 -0
  51. package/dist/i18n/use-list-formatter.js +11 -0
  52. package/dist/i18n/use-locale.d.ts +7 -0
  53. package/dist/i18n/use-locale.js +13 -0
  54. package/dist/i18n/use-localized-string-formatter.d.ts +13 -0
  55. package/dist/i18n/use-localized-string-formatter.js +30 -0
  56. package/dist/i18n/use-number-formatter.d.ts +14 -0
  57. package/dist/i18n/use-number-formatter.js +15 -0
  58. package/dist/i18n/utils.d.ts +15 -0
  59. package/dist/i18n/utils.js +50 -0
  60. package/dist/index.d.ts +22 -0
  61. package/dist/index.js +21 -0
  62. package/dist/messages/en.d.ts +6 -0
  63. package/dist/messages/en.js +68 -0
  64. package/dist/messages/fa.d.ts +6 -0
  65. package/dist/messages/fa.js +68 -0
  66. package/dist/number/NumberFormatter.d.ts +32 -0
  67. package/dist/number/NumberFormatter.js +135 -0
  68. package/dist/number/NumberParser.d.ts +30 -0
  69. package/dist/number/NumberParser.js +234 -0
  70. package/dist/number.d.ts +3 -0
  71. package/dist/number.js +3 -0
  72. package/dist/react.d.ts +17 -0
  73. package/dist/react.js +17 -0
  74. package/dist/ssr/use-is-ssr.d.ts +8 -0
  75. package/dist/ssr/use-is-ssr.js +15 -0
  76. package/dist/string/LocalizedStringDictionary.d.ts +22 -0
  77. package/dist/string/LocalizedStringDictionary.js +58 -0
  78. package/dist/string/LocalizedStringFormatter.d.ts +22 -0
  79. package/dist/string/LocalizedStringFormatter.js +46 -0
  80. package/dist/string.d.ts +3 -0
  81. package/dist/string.js +3 -0
  82. package/package.json +80 -0
@@ -0,0 +1,340 @@
1
+ import { GregorianCalendar } from "./calendars/GregorianCalendar.js";
2
+ import { add, addTime, addZoned, constrain, constrainTime, cycleDate, cycleTime, cycleZoned, set, setTime, setZoned, subtract, subtractTime, subtractZoned } from "./manipulation.js";
3
+ import { compareDate, compareTime } from "./queries.js";
4
+ import { toCalendarDateTime, toDate, toZoned, zonedToDate } from "./conversion.js";
5
+ import { dateTimeToString, dateToString, timeToString, zonedDateTimeToString } from "./string.js";
6
+ //#region src/date/CalendarDate.ts
7
+ function shiftArgs(args) {
8
+ let calendar = typeof args[0] === "object" ? args.shift() : new GregorianCalendar();
9
+ let era;
10
+ if (typeof args[0] === "string") era = args.shift();
11
+ else {
12
+ let eras = calendar.getEras();
13
+ era = eras[eras.length - 1];
14
+ }
15
+ let year = args.shift();
16
+ let month = args.shift();
17
+ let day = args.shift();
18
+ return [
19
+ calendar,
20
+ era,
21
+ year,
22
+ month,
23
+ day
24
+ ];
25
+ }
26
+ /** A CalendarDate represents a date without any time components in a specific calendar system. */
27
+ var CalendarDate = class CalendarDate {
28
+ #type;
29
+ /** The calendar system associated with this date, e.g. Gregorian. */
30
+ calendar;
31
+ /** The calendar era for this date, e.g. "BC" or "AD". */
32
+ era;
33
+ /** The year of this date within the era. */
34
+ year;
35
+ /**
36
+ * The month number within the year. Note that some calendar systems such as Hebrew
37
+ * may have a variable number of months per year. Therefore, month numbers may not
38
+ * always correspond to the same month names in different years.
39
+ */
40
+ month;
41
+ /** The day number within the month. */
42
+ day;
43
+ constructor(...args) {
44
+ let [calendar, era, year, month, day] = shiftArgs(args);
45
+ this.calendar = calendar;
46
+ this.era = era;
47
+ this.year = year;
48
+ this.month = month;
49
+ this.day = day;
50
+ constrain(this);
51
+ }
52
+ /** Returns a copy of this date. */
53
+ copy() {
54
+ if (this.era) return new CalendarDate(this.calendar, this.era, this.year, this.month, this.day);
55
+ else return new CalendarDate(this.calendar, this.year, this.month, this.day);
56
+ }
57
+ /** Returns a new `CalendarDate` with the given duration added to it. */
58
+ add(duration) {
59
+ return add(this, duration);
60
+ }
61
+ /** Returns a new `CalendarDate` with the given duration subtracted from it. */
62
+ subtract(duration) {
63
+ return subtract(this, duration);
64
+ }
65
+ /**
66
+ * Returns a new `CalendarDate` with the given fields set to the provided values. Other fields
67
+ * will be constrained accordingly.
68
+ */
69
+ set(fields) {
70
+ return set(this, fields);
71
+ }
72
+ /**
73
+ * Returns a new `CalendarDate` with the given field adjusted by a specified amount.
74
+ * When the resulting value reaches the limits of the field, it wraps around.
75
+ */
76
+ cycle(field, amount, options) {
77
+ return cycleDate(this, field, amount, options);
78
+ }
79
+ /**
80
+ * Converts the date to a native JavaScript Date object, with the time set to midnight in the
81
+ * given time zone.
82
+ */
83
+ toDate(timeZone) {
84
+ return toDate(this, timeZone);
85
+ }
86
+ /** Converts the date to an ISO 8601 formatted string. */
87
+ toString() {
88
+ return dateToString(this);
89
+ }
90
+ /**
91
+ * Compares this date with another. A negative result indicates that this date is before the given
92
+ * one, and a positive date indicates that it is after.
93
+ */
94
+ compare(b) {
95
+ return compareDate(this, b);
96
+ }
97
+ };
98
+ /** A Time represents a clock time without any date components. */
99
+ var Time = class Time {
100
+ #type;
101
+ /** The hour, numbered from 0 to 23. */
102
+ hour;
103
+ /** The minute in the hour. */
104
+ minute;
105
+ /** The second in the minute. */
106
+ second;
107
+ /** The millisecond in the second. */
108
+ millisecond;
109
+ constructor(hour = 0, minute = 0, second = 0, millisecond = 0) {
110
+ this.hour = hour;
111
+ this.minute = minute;
112
+ this.second = second;
113
+ this.millisecond = millisecond;
114
+ constrainTime(this);
115
+ }
116
+ /** Returns a copy of this time. */
117
+ copy() {
118
+ return new Time(this.hour, this.minute, this.second, this.millisecond);
119
+ }
120
+ /** Returns a new `Time` with the given duration added to it. */
121
+ add(duration) {
122
+ return addTime(this, duration);
123
+ }
124
+ /** Returns a new `Time` with the given duration subtracted from it. */
125
+ subtract(duration) {
126
+ return subtractTime(this, duration);
127
+ }
128
+ /**
129
+ * Returns a new `Time` with the given fields set to the provided values. Other fields will be
130
+ * constrained accordingly.
131
+ */
132
+ set(fields) {
133
+ return setTime(this, fields);
134
+ }
135
+ /**
136
+ * Returns a new `Time` with the given field adjusted by a specified amount.
137
+ * When the resulting value reaches the limits of the field, it wraps around.
138
+ */
139
+ cycle(field, amount, options) {
140
+ return cycleTime(this, field, amount, options);
141
+ }
142
+ /** Converts the time to an ISO 8601 formatted string. */
143
+ toString() {
144
+ return timeToString(this);
145
+ }
146
+ /**
147
+ * Compares this time with another. A negative result indicates that this time is before the given
148
+ * one, and a positive time indicates that it is after.
149
+ */
150
+ compare(b) {
151
+ return compareTime(this, b);
152
+ }
153
+ };
154
+ /** A CalendarDateTime represents a date and time without a time zone, in a specific calendar system. */
155
+ var CalendarDateTime = class CalendarDateTime {
156
+ #type;
157
+ /** The calendar system associated with this date, e.g. Gregorian. */
158
+ calendar;
159
+ /** The calendar era for this date, e.g. "BC" or "AD". */
160
+ era;
161
+ /** The year of this date within the era. */
162
+ year;
163
+ /**
164
+ * The month number within the year. Note that some calendar systems such as Hebrew
165
+ * may have a variable number of months per year. Therefore, month numbers may not
166
+ * always correspond to the same month names in different years.
167
+ */
168
+ month;
169
+ /** The day number within the month. */
170
+ day;
171
+ /** The hour in the day, numbered from 0 to 23. */
172
+ hour;
173
+ /** The minute in the hour. */
174
+ minute;
175
+ /** The second in the minute. */
176
+ second;
177
+ /** The millisecond in the second. */
178
+ millisecond;
179
+ constructor(...args) {
180
+ let [calendar, era, year, month, day] = shiftArgs(args);
181
+ this.calendar = calendar;
182
+ this.era = era;
183
+ this.year = year;
184
+ this.month = month;
185
+ this.day = day;
186
+ this.hour = args.shift() || 0;
187
+ this.minute = args.shift() || 0;
188
+ this.second = args.shift() || 0;
189
+ this.millisecond = args.shift() || 0;
190
+ constrain(this);
191
+ }
192
+ /** Returns a copy of this date. */
193
+ copy() {
194
+ if (this.era) return new CalendarDateTime(this.calendar, this.era, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
195
+ else return new CalendarDateTime(this.calendar, this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
196
+ }
197
+ /** Returns a new `CalendarDateTime` with the given duration added to it. */
198
+ add(duration) {
199
+ return add(this, duration);
200
+ }
201
+ /** Returns a new `CalendarDateTime` with the given duration subtracted from it. */
202
+ subtract(duration) {
203
+ return subtract(this, duration);
204
+ }
205
+ /**
206
+ * Returns a new `CalendarDateTime` with the given fields set to the provided values. Other fields
207
+ * will be constrained accordingly.
208
+ */
209
+ set(fields) {
210
+ return set(setTime(this, fields), fields);
211
+ }
212
+ /**
213
+ * Returns a new `CalendarDateTime` with the given field adjusted by a specified amount.
214
+ * When the resulting value reaches the limits of the field, it wraps around.
215
+ */
216
+ cycle(field, amount, options) {
217
+ switch (field) {
218
+ case "era":
219
+ case "year":
220
+ case "month":
221
+ case "day": return cycleDate(this, field, amount, options);
222
+ default: return cycleTime(this, field, amount, options);
223
+ }
224
+ }
225
+ /** Converts the date to a native JavaScript Date object in the given time zone. */
226
+ toDate(timeZone, disambiguation) {
227
+ return toDate(this, timeZone, disambiguation);
228
+ }
229
+ /** Converts the date to an ISO 8601 formatted string. */
230
+ toString() {
231
+ return dateTimeToString(this);
232
+ }
233
+ /**
234
+ * Compares this date with another. A negative result indicates that this date is before the given
235
+ * one, and a positive date indicates that it is after.
236
+ */
237
+ compare(b) {
238
+ let res = compareDate(this, b);
239
+ if (res === 0) return compareTime(this, toCalendarDateTime(b));
240
+ return res;
241
+ }
242
+ };
243
+ /** A ZonedDateTime represents a date and time in a specific time zone and calendar system. */
244
+ var ZonedDateTime = class ZonedDateTime {
245
+ #type;
246
+ /** The calendar system associated with this date, e.g. Gregorian. */
247
+ calendar;
248
+ /** The calendar era for this date, e.g. "BC" or "AD". */
249
+ era;
250
+ /** The year of this date within the era. */
251
+ year;
252
+ /**
253
+ * The month number within the year. Note that some calendar systems such as Hebrew
254
+ * may have a variable number of months per year. Therefore, month numbers may not
255
+ * always correspond to the same month names in different years.
256
+ */
257
+ month;
258
+ /** The day number within the month. */
259
+ day;
260
+ /** The hour in the day, numbered from 0 to 23. */
261
+ hour;
262
+ /** The minute in the hour. */
263
+ minute;
264
+ /** The second in the minute. */
265
+ second;
266
+ /** The millisecond in the second. */
267
+ millisecond;
268
+ /** The IANA time zone identifier that this date and time is represented in. */
269
+ timeZone;
270
+ /** The UTC offset for this time, in milliseconds. */
271
+ offset;
272
+ constructor(...args) {
273
+ let [calendar, era, year, month, day] = shiftArgs(args);
274
+ let timeZone = args.shift();
275
+ let offset = args.shift();
276
+ this.calendar = calendar;
277
+ this.era = era;
278
+ this.year = year;
279
+ this.month = month;
280
+ this.day = day;
281
+ this.timeZone = timeZone;
282
+ this.offset = offset;
283
+ this.hour = args.shift() || 0;
284
+ this.minute = args.shift() || 0;
285
+ this.second = args.shift() || 0;
286
+ this.millisecond = args.shift() || 0;
287
+ constrain(this);
288
+ }
289
+ /** Returns a copy of this date. */
290
+ copy() {
291
+ if (this.era) return new ZonedDateTime(this.calendar, this.era, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond);
292
+ else return new ZonedDateTime(this.calendar, this.year, this.month, this.day, this.timeZone, this.offset, this.hour, this.minute, this.second, this.millisecond);
293
+ }
294
+ /** Returns a new `ZonedDateTime` with the given duration added to it. */
295
+ add(duration) {
296
+ return addZoned(this, duration);
297
+ }
298
+ /** Returns a new `ZonedDateTime` with the given duration subtracted from it. */
299
+ subtract(duration) {
300
+ return subtractZoned(this, duration);
301
+ }
302
+ /**
303
+ * Returns a new `ZonedDateTime` with the given fields set to the provided values. Other fields
304
+ * will be constrained accordingly.
305
+ */
306
+ set(fields, disambiguation) {
307
+ return setZoned(this, fields, disambiguation);
308
+ }
309
+ /**
310
+ * Returns a new `ZonedDateTime` with the given field adjusted by a specified amount.
311
+ * When the resulting value reaches the limits of the field, it wraps around.
312
+ */
313
+ cycle(field, amount, options) {
314
+ return cycleZoned(this, field, amount, options);
315
+ }
316
+ /** Converts the date to a native JavaScript Date object. */
317
+ toDate() {
318
+ return zonedToDate(this);
319
+ }
320
+ /**
321
+ * Converts the date to an ISO 8601 formatted string, including the UTC offset and time zone
322
+ * identifier.
323
+ */
324
+ toString() {
325
+ return zonedDateTimeToString(this);
326
+ }
327
+ /** Converts the date to an ISO 8601 formatted string in UTC. */
328
+ toAbsoluteString() {
329
+ return this.toDate().toISOString();
330
+ }
331
+ /**
332
+ * Compares this date with another. A negative result indicates that this date is before the given
333
+ * one, and a positive date indicates that it is after.
334
+ */
335
+ compare(b) {
336
+ return this.toDate().getTime() - toZoned(b, this.timeZone).toDate().getTime();
337
+ }
338
+ };
339
+ //#endregion
340
+ export { CalendarDate, CalendarDateTime, Time, ZonedDateTime };
@@ -0,0 +1,26 @@
1
+ //#region src/date/DateFormatter.d.ts
2
+ interface DateRangeFormatPart extends Intl.DateTimeFormatPart {
3
+ source: "startRange" | "endRange" | "shared";
4
+ }
5
+ /** A wrapper around Intl.DateTimeFormat that fixes various browser bugs, and polyfills new features. */
6
+ declare class DateFormatter implements Intl.DateTimeFormat {
7
+ private formatter;
8
+ private options;
9
+ private resolvedHourCycle;
10
+ constructor(locale: string, options?: Intl.DateTimeFormatOptions);
11
+ /**
12
+ * Formats a date as a string according to the locale and format options passed to the
13
+ * constructor.
14
+ */
15
+ format(value: Date): string;
16
+ /** Formats a date to an array of parts such as separators, numbers, punctuation, and more. */
17
+ formatToParts(value: Date): Intl.DateTimeFormatPart[];
18
+ /** Formats a date range as a string. */
19
+ formatRange(start: Date, end: Date): string;
20
+ /** Formats a date range as an array of parts. */
21
+ formatRangeToParts(start: Date, end: Date): DateRangeFormatPart[];
22
+ /** Returns the resolved formatting options based on the values passed to the constructor. */
23
+ resolvedOptions(): Intl.ResolvedDateTimeFormatOptions;
24
+ }
25
+ //#endregion
26
+ export { DateFormatter };
@@ -0,0 +1,114 @@
1
+ //#region src/date/DateFormatter.ts
2
+ let formatterCache = /* @__PURE__ */ new Map();
3
+ /** A wrapper around Intl.DateTimeFormat that fixes various browser bugs, and polyfills new features. */
4
+ var DateFormatter = class {
5
+ formatter;
6
+ options;
7
+ resolvedHourCycle;
8
+ constructor(locale, options = {}) {
9
+ this.formatter = getCachedDateFormatter(locale, options);
10
+ this.options = options;
11
+ }
12
+ /**
13
+ * Formats a date as a string according to the locale and format options passed to the
14
+ * constructor.
15
+ */
16
+ format(value) {
17
+ return this.formatter.format(value);
18
+ }
19
+ /** Formats a date to an array of parts such as separators, numbers, punctuation, and more. */
20
+ formatToParts(value) {
21
+ return this.formatter.formatToParts(value);
22
+ }
23
+ /** Formats a date range as a string. */
24
+ formatRange(start, end) {
25
+ if (typeof this.formatter.formatRange === "function") return this.formatter.formatRange(start, end);
26
+ if (end < start) throw new RangeError("End date must be >= start date");
27
+ return `${this.formatter.format(start)} – ${this.formatter.format(end)}`;
28
+ }
29
+ /** Formats a date range as an array of parts. */
30
+ formatRangeToParts(start, end) {
31
+ if (typeof this.formatter.formatRangeToParts === "function") return this.formatter.formatRangeToParts(start, end);
32
+ if (end < start) throw new RangeError("End date must be >= start date");
33
+ let startParts = this.formatter.formatToParts(start);
34
+ let endParts = this.formatter.formatToParts(end);
35
+ return [
36
+ ...startParts.map((p) => ({
37
+ ...p,
38
+ source: "startRange"
39
+ })),
40
+ {
41
+ type: "literal",
42
+ value: " – ",
43
+ source: "shared"
44
+ },
45
+ ...endParts.map((p) => ({
46
+ ...p,
47
+ source: "endRange"
48
+ }))
49
+ ];
50
+ }
51
+ /** Returns the resolved formatting options based on the values passed to the constructor. */
52
+ resolvedOptions() {
53
+ let resolvedOptions = this.formatter.resolvedOptions();
54
+ if (hasBuggyResolvedHourCycle()) {
55
+ if (!this.resolvedHourCycle) this.resolvedHourCycle = getResolvedHourCycle(resolvedOptions.locale, this.options);
56
+ resolvedOptions.hourCycle = this.resolvedHourCycle;
57
+ resolvedOptions.hour12 = this.resolvedHourCycle === "h11" || this.resolvedHourCycle === "h12";
58
+ }
59
+ if (resolvedOptions.calendar === "ethiopic-amete-alem") resolvedOptions.calendar = "ethioaa";
60
+ return resolvedOptions;
61
+ }
62
+ };
63
+ const hour12Preferences = {
64
+ true: { ja: "h11" },
65
+ false: {}
66
+ };
67
+ function getCachedDateFormatter(locale, options = {}) {
68
+ if (typeof options.hour12 === "boolean" && hasBuggyHour12Behavior()) {
69
+ options = { ...options };
70
+ let pref = hour12Preferences[String(options.hour12)][locale.split("-")[0]];
71
+ let defaultHourCycle = options.hour12 ? "h12" : "h23";
72
+ options.hourCycle = pref ?? defaultHourCycle;
73
+ delete options.hour12;
74
+ }
75
+ let cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
76
+ if (formatterCache.has(cacheKey)) return formatterCache.get(cacheKey);
77
+ let numberFormatter = new Intl.DateTimeFormat(locale, options);
78
+ formatterCache.set(cacheKey, numberFormatter);
79
+ return numberFormatter;
80
+ }
81
+ let _hasBuggyHour12Behavior = null;
82
+ function hasBuggyHour12Behavior() {
83
+ if (_hasBuggyHour12Behavior == null) _hasBuggyHour12Behavior = new Intl.DateTimeFormat("en-US", {
84
+ hour: "numeric",
85
+ hour12: false
86
+ }).format(new Date(2020, 2, 3, 0)) === "24";
87
+ return _hasBuggyHour12Behavior;
88
+ }
89
+ let _hasBuggyResolvedHourCycle = null;
90
+ function hasBuggyResolvedHourCycle() {
91
+ if (_hasBuggyResolvedHourCycle == null) _hasBuggyResolvedHourCycle = new Intl.DateTimeFormat("fr", {
92
+ hour: "numeric",
93
+ hour12: false
94
+ }).resolvedOptions().hourCycle === "h12";
95
+ return _hasBuggyResolvedHourCycle;
96
+ }
97
+ function getResolvedHourCycle(locale, options) {
98
+ if (!options.timeStyle && !options.hour) return;
99
+ locale = locale.replace(/(-u-)?-nu-[a-zA-Z0-9]+/, "");
100
+ locale += (locale.includes("-u-") ? "" : "-u") + "-nu-latn";
101
+ let formatter = getCachedDateFormatter(locale, {
102
+ ...options,
103
+ timeZone: void 0
104
+ });
105
+ let min = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 0)).find((p) => p.type === "hour").value, 10);
106
+ let max = parseInt(formatter.formatToParts(new Date(2020, 2, 3, 23)).find((p) => p.type === "hour").value, 10);
107
+ if (min === 0 && max === 23) return "h23";
108
+ if (min === 24 && max === 23) return "h24";
109
+ if (min === 0 && max === 11) return "h11";
110
+ if (min === 12 && max === 11) return "h12";
111
+ throw new Error("Unexpected hour cycle result");
112
+ }
113
+ //#endregion
114
+ export { DateFormatter };
@@ -0,0 +1,20 @@
1
+ import { CalendarDate } from "../CalendarDate.js";
2
+ import { AnyCalendarDate, CalendarIdentifier } from "../types.js";
3
+ import { GregorianCalendar } from "./GregorianCalendar.js";
4
+
5
+ //#region src/date/calendars/BuddhistCalendar.d.ts
6
+ /**
7
+ * The Buddhist calendar is the same as the Gregorian calendar, but counts years
8
+ * starting from the birth of Buddha in 543 BC (Gregorian). It supports only one
9
+ * era, identified as 'BE'.
10
+ */
11
+ declare class BuddhistCalendar extends GregorianCalendar {
12
+ identifier: CalendarIdentifier;
13
+ fromJulianDay(jd: number): CalendarDate;
14
+ toJulianDay(date: AnyCalendarDate): number;
15
+ getEras(): string[];
16
+ getDaysInMonth(date: AnyCalendarDate): number;
17
+ balanceDate(): void;
18
+ }
19
+ //#endregion
20
+ export { BuddhistCalendar };
@@ -0,0 +1,33 @@
1
+ import { GregorianCalendar, fromExtendedYear, getExtendedYear } from "./GregorianCalendar.js";
2
+ import { CalendarDate } from "../CalendarDate.js";
3
+ //#region src/date/calendars/BuddhistCalendar.ts
4
+ const BUDDHIST_ERA_START = -543;
5
+ /**
6
+ * The Buddhist calendar is the same as the Gregorian calendar, but counts years
7
+ * starting from the birth of Buddha in 543 BC (Gregorian). It supports only one
8
+ * era, identified as 'BE'.
9
+ */
10
+ var BuddhistCalendar = class extends GregorianCalendar {
11
+ identifier = "buddhist";
12
+ fromJulianDay(jd) {
13
+ let gregorianDate = super.fromJulianDay(jd);
14
+ let year = getExtendedYear(gregorianDate.era, gregorianDate.year);
15
+ return new CalendarDate(this, year - BUDDHIST_ERA_START, gregorianDate.month, gregorianDate.day);
16
+ }
17
+ toJulianDay(date) {
18
+ return super.toJulianDay(toGregorian(date));
19
+ }
20
+ getEras() {
21
+ return ["BE"];
22
+ }
23
+ getDaysInMonth(date) {
24
+ return super.getDaysInMonth(toGregorian(date));
25
+ }
26
+ balanceDate() {}
27
+ };
28
+ function toGregorian(date) {
29
+ let [era, year] = fromExtendedYear(date.year + BUDDHIST_ERA_START);
30
+ return new CalendarDate(era, year, date.month, date.day);
31
+ }
32
+ //#endregion
33
+ export { BuddhistCalendar };
@@ -0,0 +1,49 @@
1
+ import { CalendarDate } from "../CalendarDate.js";
2
+ import { AnyCalendarDate, Calendar, CalendarIdentifier } from "../types.js";
3
+ import { Mutable } from "../utils.js";
4
+
5
+ //#region src/date/calendars/EthiopicCalendar.d.ts
6
+ /**
7
+ * The Ethiopic calendar system is the official calendar used in Ethiopia.
8
+ * It includes 12 months of 30 days each, plus 5 or 6 intercalary days depending
9
+ * on whether it is a leap year. Two eras are supported: 'AA' and 'AM'.
10
+ */
11
+ declare class EthiopicCalendar implements Calendar {
12
+ identifier: CalendarIdentifier;
13
+ fromJulianDay(jd: number): CalendarDate;
14
+ toJulianDay(date: AnyCalendarDate): number;
15
+ getDaysInMonth(date: AnyCalendarDate): number;
16
+ getMonthsInYear(): number;
17
+ getDaysInYear(date: AnyCalendarDate): number;
18
+ getMaximumMonthsInYear(): number;
19
+ getMaximumDaysInMonth(): number;
20
+ getYearsInEra(date: AnyCalendarDate): number;
21
+ getEras(): string[];
22
+ }
23
+ /**
24
+ * The Ethiopic (Amete Alem) calendar is the same as the modern Ethiopic calendar,
25
+ * except years were measured from a different epoch. Only one era is supported: 'AA'.
26
+ */
27
+ declare class EthiopicAmeteAlemCalendar extends EthiopicCalendar {
28
+ identifier: CalendarIdentifier;
29
+ fromJulianDay(jd: number): CalendarDate;
30
+ getEras(): string[];
31
+ getYearsInEra(): number;
32
+ }
33
+ /**
34
+ * The Coptic calendar is similar to the Ethiopic calendar.
35
+ * It includes 12 months of 30 days each, plus 5 or 6 intercalary days depending
36
+ * on whether it is a leap year. Two eras are supported: 'BCE' and 'CE'.
37
+ */
38
+ declare class CopticCalendar extends EthiopicCalendar {
39
+ identifier: CalendarIdentifier;
40
+ fromJulianDay(jd: number): CalendarDate;
41
+ toJulianDay(date: AnyCalendarDate): number;
42
+ getDaysInMonth(date: AnyCalendarDate): number;
43
+ isInverseEra(date: AnyCalendarDate): boolean;
44
+ balanceDate(date: Mutable<AnyCalendarDate>): void;
45
+ getEras(): string[];
46
+ getYearsInEra(date: AnyCalendarDate): number;
47
+ }
48
+ //#endregion
49
+ export { CopticCalendar, EthiopicAmeteAlemCalendar, EthiopicCalendar };