@pbkware/dot-net-date-number-formatting 0.2.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.
@@ -0,0 +1,101 @@
1
+ import { CommaText, Err, Ok } from "@pbkware/js-utils";
2
+ /**
3
+ * Individual style flags that control date/time parsing behavior.
4
+ *
5
+ * These flags can be combined to create custom parsing rules.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * // Combine individual flags
10
+ * formatter.styles = new Set([
11
+ * DotNetDateTimeStyleId.AllowLeadingWhite,
12
+ * DotNetDateTimeStyleId.AllowTrailingWhite
13
+ * ]);
14
+ * ```
15
+ *
16
+ * @public
17
+ * @category DateTime Styles
18
+ */
19
+ export var DotNetDateTimeStyleId;
20
+ (function (DotNetDateTimeStyleId) {
21
+ /** Allow leading whitespace characters. */
22
+ DotNetDateTimeStyleId["AllowLeadingWhite"] = "AllowLeadingWhite";
23
+ /** Allow trailing whitespace characters. */
24
+ DotNetDateTimeStyleId["AllowTrailingWhite"] = "AllowTrailingWhite";
25
+ /** Allow whitespace within the date/time string. */
26
+ DotNetDateTimeStyleId["AllowInnerWhite"] = "AllowInnerWhite";
27
+ /** Do not use current date for missing date components. */
28
+ DotNetDateTimeStyleId["NoCurrentDateDefault"] = "NoCurrentDateDefault";
29
+ /** Adjust date/time to UTC (not implemented). */
30
+ DotNetDateTimeStyleId["AdjustToUniversal"] = "AdjustToUniversal";
31
+ /** Assume local time zone if not specified (not implemented). */
32
+ DotNetDateTimeStyleId["AssumeLocal"] = "AssumeLocal";
33
+ /** Assume UTC time zone if not specified (not implemented). */
34
+ DotNetDateTimeStyleId["AssumeUniversal"] = "AssumeUniversal";
35
+ /** Preserve DateTimeKind when parsing (not implemented). */
36
+ DotNetDateTimeStyleId["RoundTripKind"] = "RoundTripKind";
37
+ })(DotNetDateTimeStyleId || (DotNetDateTimeStyleId = {}));
38
+ /**
39
+ * Predefined date/time style combinations for common parsing scenarios.
40
+ *
41
+ * @internal
42
+ * @category DateTime Styles
43
+ */
44
+ export const DotNetDateTimeStyles = {
45
+ /** No styles - strict parsing. */
46
+ none: new Set(),
47
+ /**
48
+ * Allow whitespace in date/time strings.
49
+ * Includes: AllowLeadingWhite, AllowTrailingWhite, AllowInnerWhite.
50
+ */
51
+ allowWhiteSpaces: new Set([
52
+ DotNetDateTimeStyleId.AllowLeadingWhite,
53
+ DotNetDateTimeStyleId.AllowTrailingWhite,
54
+ DotNetDateTimeStyleId.AllowInnerWhite,
55
+ ]),
56
+ };
57
+ const isSameSet = (left, right) => {
58
+ if (left.size !== right.size)
59
+ return false;
60
+ for (const value of left) {
61
+ if (!right.has(value))
62
+ return false;
63
+ }
64
+ return true;
65
+ };
66
+ /** @internal */
67
+ export class DotNetDateTimeStylesInfo {
68
+ static toString(styles) {
69
+ return this.toXmlValue(styles);
70
+ }
71
+ static toXmlValue(styles) {
72
+ if (isSameSet(styles, DotNetDateTimeStyles.allowWhiteSpaces)) {
73
+ return "AllowWhiteSpaces";
74
+ }
75
+ return CommaText.fromStringArray(Array.from(styles.values()));
76
+ }
77
+ static tryFromString(value) {
78
+ return this.tryFromXmlValue(value);
79
+ }
80
+ static tryFromXmlValue(value) {
81
+ const normalized = value.trim();
82
+ if (normalized.length === 0 || normalized.toLowerCase() === "none") {
83
+ return new Ok(new Set(DotNetDateTimeStyles.none));
84
+ }
85
+ if (normalized.toLowerCase() === "allowwhitespaces") {
86
+ return new Ok(new Set(DotNetDateTimeStyles.allowWhiteSpaces));
87
+ }
88
+ const commaTextResult = CommaText.tryToStringArray(normalized);
89
+ if (commaTextResult.isErr())
90
+ return commaTextResult.createOuter("Invalid comma-separated styles string");
91
+ const styles = new Set();
92
+ for (const item of commaTextResult.value) {
93
+ const match = Object.values(DotNetDateTimeStyleId).find((x) => x.toLowerCase() === item.toLowerCase());
94
+ if (match === undefined)
95
+ return new Err(`Invalid style: ${item}`);
96
+ styles.add(match);
97
+ }
98
+ return new Ok(styles);
99
+ }
100
+ }
101
+ //# sourceMappingURL=datetime-style.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"datetime-style.js","sourceRoot":"","sources":["../../src/code/datetime-style.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ export * from "./datetime-formatter.js";
2
+ export * from "./datetime-style.js";
3
+ export * from "./locale-settings.js";
4
+ export * from "./number-formatter.js";
5
+ export * from "./number-style.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/code/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC"}
@@ -0,0 +1,404 @@
1
+ import { Err, Ok } from "@pbkware/js-utils";
2
+ const INVARIANT_LOCALE = "en-US";
3
+ function parseDate(value) {
4
+ const date = new Date(value);
5
+ if (Number.isNaN(date.getTime())) {
6
+ return undefined;
7
+ }
8
+ return date;
9
+ }
10
+ function getSeparators(locale) {
11
+ const numberParts = new Intl.NumberFormat(locale, {
12
+ style: "decimal",
13
+ useGrouping: true,
14
+ }).formatToParts(12345.6);
15
+ const currencyParts = new Intl.NumberFormat(locale, {
16
+ style: "currency",
17
+ currency: "USD",
18
+ }).formatToParts(1);
19
+ const dateParts = new Intl.DateTimeFormat(locale, {
20
+ year: "numeric",
21
+ month: "2-digit",
22
+ day: "2-digit",
23
+ }).formatToParts(new Date(2024, 6, 5));
24
+ const timeParts = new Intl.DateTimeFormat(locale, {
25
+ hour: "2-digit",
26
+ minute: "2-digit",
27
+ second: "2-digit",
28
+ hour12: false,
29
+ }).formatToParts(new Date(2024, 6, 5, 13, 24, 35));
30
+ const decimalSeparator = numberParts.find((x) => x.type === "decimal")?.value ?? ".";
31
+ const thousandSeparator = numberParts.find((x) => x.type === "group")?.value ?? ",";
32
+ const currencySymbol = currencyParts.find((x) => x.type === "currency")?.value ?? "$";
33
+ const dateSeparator = dateParts.find((x) => x.type === "literal")?.value ?? "/";
34
+ const timeSeparator = timeParts.find((x) => x.type === "literal")?.value ?? ":";
35
+ return {
36
+ decimalSeparator,
37
+ thousandSeparator,
38
+ currencySymbol,
39
+ dateSeparator,
40
+ timeSeparator,
41
+ };
42
+ }
43
+ /**
44
+ * Represents locale-specific formatting settings for dates, times, and numbers.
45
+ *
46
+ * Provides culture-specific separators and formatting options that determine how
47
+ * numbers, currencies, dates, and times are formatted and parsed.
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * // Use invariant culture (en-US)
52
+ * const invariant = DotNetLocaleSettings.createInvariant();
53
+ *
54
+ * // Use specific locale
55
+ * const french = DotNetLocaleSettings.create('fr-FR');
56
+ * console.log(french.decimalSeparator); // ","
57
+ * console.log(french.thousandSeparator); // " "
58
+ *
59
+ * // Use current system locale
60
+ * const current = DotNetLocaleSettings.current;
61
+ * ```
62
+ *
63
+ * @public
64
+ * @category Locale Settings
65
+ */
66
+ export class DotNetLocaleSettings {
67
+ /**
68
+ * Singleton instance for invariant culture (en-US).
69
+ * Provides consistent formatting across all systems.
70
+ */
71
+ static invariant = DotNetLocaleSettings.createInvariant();
72
+ /**
73
+ * Singleton instance for current system locale.
74
+ * Uses the locale settings from the runtime environment.
75
+ */
76
+ static current = new DotNetLocaleSettings(undefined);
77
+ /** The locale identifier (same as name). */
78
+ id;
79
+ /** The locale name (e.g., "en-US", "fr-FR"). */
80
+ name;
81
+ /** Character used for decimal point (e.g., "." or ","). */
82
+ decimalSeparator;
83
+ /** Character used for thousands grouping (e.g., "," or "." or " "). */
84
+ thousandSeparator;
85
+ /** Currency symbol for this locale (e.g., "$", "€", "£"). */
86
+ currencyString;
87
+ /** Character used between date components (e.g., "/", "-", "."). */
88
+ dateSeparator;
89
+ /** Character used between time components (typically ":"). */
90
+ timeSeparator;
91
+ /** Pre-configured number formatter for floating-point values. */
92
+ defaultFloat;
93
+ /** Pre-configured number formatter for high-precision decimal values. */
94
+ defaultDecimal;
95
+ /** Pre-configured number formatter for currency values. */
96
+ defaultCurrency;
97
+ /**
98
+ * Creates a new DotNetLocaleSettings instance.
99
+ *
100
+ * @param localeName - Optional locale name (e.g., "en-US", "fr-FR").
101
+ * If undefined, uses the system's current locale.
102
+ *
103
+ * @example
104
+ * ```typescript
105
+ * // System locale
106
+ * const settings = new DotNetLocaleSettings(undefined);
107
+ *
108
+ * // Specific locale
109
+ * const french = new DotNetLocaleSettings('fr-FR');
110
+ * ```
111
+ */
112
+ constructor(localeName) {
113
+ this.name = localeName ?? Intl.DateTimeFormat().resolvedOptions().locale;
114
+ this.id = this.name;
115
+ const separators = getSeparators(this.name || INVARIANT_LOCALE);
116
+ this.decimalSeparator = separators.decimalSeparator;
117
+ this.thousandSeparator = separators.thousandSeparator;
118
+ this.currencyString = separators.currencySymbol;
119
+ this.dateSeparator = separators.dateSeparator;
120
+ this.timeSeparator = separators.timeSeparator;
121
+ this.defaultFloat = new Intl.NumberFormat(this.name, {
122
+ useGrouping: false,
123
+ maximumFractionDigits: 20,
124
+ });
125
+ this.defaultCurrency = new Intl.NumberFormat(this.name, {
126
+ style: "currency",
127
+ currency: "USD",
128
+ });
129
+ this.defaultDecimal = new Intl.NumberFormat(this.name, {
130
+ useGrouping: false,
131
+ minimumFractionDigits: 18,
132
+ maximumFractionDigits: 18,
133
+ });
134
+ }
135
+ /**
136
+ * Creates a DotNetLocaleSettings instance for the specified locale.
137
+ *
138
+ * @param localeName - The locale name (e.g., "en-US", "fr-FR", "de-DE").
139
+ * @returns A new DotNetLocaleSettings instance configured for the specified locale.
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const usSettings = DotNetLocaleSettings.create('en-US');
144
+ * const frSettings = DotNetLocaleSettings.create('fr-FR');
145
+ * ```
146
+ */
147
+ static create(localeName) {
148
+ return new DotNetLocaleSettings(localeName);
149
+ }
150
+ /**
151
+ * Creates a DotNetLocaleSettings instance for the invariant culture (en-US).
152
+ * The invariant culture provides consistent formatting across all systems.
153
+ *
154
+ * @returns A new DotNetLocaleSettings instance configured for invariant culture.
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * const settings = DotNetLocaleSettings.createInvariant();
159
+ * console.log(settings.decimalSeparator); // "."
160
+ * console.log(settings.thousandSeparator); // ","
161
+ * ```
162
+ */
163
+ static createInvariant() {
164
+ return new DotNetLocaleSettings(INVARIANT_LOCALE);
165
+ }
166
+ /**
167
+ * Converts a number or bigint to a string using locale-specific formatting.
168
+ *
169
+ * @param value - The number or bigint to format.
170
+ * @param options - Optional Intl.NumberFormatOptions for custom formatting.
171
+ * @returns The formatted number string.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * const settings = DotNetLocaleSettings.create('en-US');
176
+ * settings.numberToStr(1234.56); // "1,234.56"
177
+ * settings.numberToStr(1234.56, { minimumFractionDigits: 2 }); // "1,234.56"
178
+ * ```
179
+ */
180
+ numberToStr(value, options) {
181
+ return new Intl.NumberFormat(this.name, options).format(value);
182
+ }
183
+ /**
184
+ * Converts a Date to a string using locale-specific formatting.
185
+ *
186
+ * @param value - The Date to format.
187
+ * @param options - Optional Intl.DateTimeFormatOptions for custom formatting.
188
+ * @returns The formatted date string.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * const settings = DotNetLocaleSettings.create('en-US');
193
+ * settings.dateToStr(new Date(2024, 6, 5), { dateStyle: 'short' }); // "7/5/2024"
194
+ * ```
195
+ */
196
+ dateToStr(value, options) {
197
+ return new Intl.DateTimeFormat(this.name, options).format(value);
198
+ }
199
+ /**
200
+ * Converts a boolean to a string.
201
+ *
202
+ * @param value - The boolean value.
203
+ * @returns "true" or "false".
204
+ *
205
+ * @example
206
+ * ```typescript
207
+ * settings.boolToStr(true); // "true"
208
+ * settings.boolToStr(false); // "false"
209
+ * ```
210
+ */
211
+ boolToStr(value) {
212
+ return value ? "true" : "false";
213
+ }
214
+ /**
215
+ * Attempts to parse a boolean value from a string.
216
+ *
217
+ * @param value - The string to parse. Accepts: "true", "1", "yes" (case-insensitive) for true,
218
+ * and "false", "0", "no" for false.
219
+ * @returns A Result containing the boolean value if successful, or an error if parsing fails.
220
+ *
221
+ * @example
222
+ * ```typescript
223
+ * settings.tryStrToBool('yes'); // Ok(true)
224
+ * settings.tryStrToBool('false'); // Ok(false)
225
+ * settings.tryStrToBool('invalid'); // Err("Invalid boolean string")
226
+ * ```
227
+ */
228
+ tryStrToBool(value) {
229
+ const normalized = value.trim().toLowerCase();
230
+ if (["true", "1", "yes"].includes(normalized)) {
231
+ return new Ok(true);
232
+ }
233
+ if (["false", "0", "no"].includes(normalized)) {
234
+ return new Ok(false);
235
+ }
236
+ return new Err("Invalid boolean string");
237
+ }
238
+ /**
239
+ * Attempts to parse an integer from a string.
240
+ *
241
+ * @param value - The string to parse. Must contain only digits and an optional leading +/- sign.
242
+ * @returns A Result containing the parsed integer if successful, or an error if parsing fails.
243
+ *
244
+ * @example
245
+ * ```typescript
246
+ * settings.tryStrToInt('123'); // Ok(123)
247
+ * settings.tryStrToInt('-456'); // Ok(-456)
248
+ * settings.tryStrToInt('12.34'); // Err("Invalid integer string")
249
+ * ```
250
+ */
251
+ tryStrToInt(value) {
252
+ if (!/^[+-]?\d+$/.test(value.trim())) {
253
+ return new Err("Invalid integer string");
254
+ }
255
+ const parsed = Number.parseInt(value, 10);
256
+ return Number.isNaN(parsed)
257
+ ? new Err("Invalid integer string")
258
+ : new Ok(parsed);
259
+ }
260
+ /**
261
+ * Attempts to parse a BigInt from a string.
262
+ *
263
+ * @param value - The string to parse. Must contain only digits and an optional leading +/- sign.
264
+ * @returns A Result containing the parsed BigInt if successful, or an error if parsing fails.
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * settings.tryStrToBigInt('12345678901234567890'); // Ok(12345678901234567890n)
269
+ * settings.tryStrToBigInt('-999'); // Ok(-999n)
270
+ * ```
271
+ */
272
+ tryStrToBigInt(value) {
273
+ if (!/^[+-]?\d+$/.test(value.trim())) {
274
+ return new Err("Invalid integer string");
275
+ }
276
+ try {
277
+ return new Ok(BigInt(value.trim()));
278
+ }
279
+ catch {
280
+ return new Err("Invalid integer string");
281
+ }
282
+ }
283
+ /**
284
+ * Attempts to parse a number from a string using locale-specific formatting.
285
+ * Handles currency symbols, thousands separators, and locale-specific decimal separators.
286
+ *
287
+ * @param value - The string to parse.
288
+ * @returns A Result containing the parsed number if successful, or an error if parsing fails.
289
+ *
290
+ * @example
291
+ * ```typescript
292
+ * const usSettings = DotNetLocaleSettings.create('en-US');
293
+ * usSettings.tryStrToNumber('1,234.56'); // Ok(1234.56)
294
+ * usSettings.tryStrToNumber('$1,234.56'); // Ok(1234.56)
295
+ *
296
+ * const frSettings = DotNetLocaleSettings.create('fr-FR');
297
+ * frSettings.tryStrToNumber('1 234,56'); // Ok(1234.56)
298
+ * ```
299
+ */
300
+ tryStrToNumber(value) {
301
+ const normalized = value
302
+ .trim()
303
+ .replaceAll(this.currencyString, "")
304
+ .replaceAll(this.thousandSeparator, "")
305
+ .replace(this.decimalSeparator, ".");
306
+ const parsed = Number.parseFloat(normalized);
307
+ return Number.isNaN(parsed)
308
+ ? new Err("Invalid float string")
309
+ : new Ok(parsed);
310
+ }
311
+ /**
312
+ * Attempts to parse a Date from a string.
313
+ *
314
+ * @param value - The string to parse. Accepts various date formats understood by JavaScript Date constructor.
315
+ * @returns A Result containing the parsed Date if successful, or an error if parsing fails.
316
+ *
317
+ * @example
318
+ * ```typescript
319
+ * settings.tryStrToDate('2024-07-05'); // Ok(Date)
320
+ * settings.tryStrToDate('July 5, 2024'); // Ok(Date)
321
+ * settings.tryStrToDate('invalid'); // Err("Invalid date string")
322
+ * ```
323
+ */
324
+ tryStrToDate(value) {
325
+ const parsed = parseDate(value.trim());
326
+ return parsed === undefined
327
+ ? new Err("Invalid date string")
328
+ : new Ok(parsed);
329
+ }
330
+ /**
331
+ * Convert a single character to uppercase using culture-specific rules.
332
+ * Handles special cases like Turkish 'i' → 'İ' vs standard 'i' → 'I'.
333
+ *
334
+ * @param char - The character to convert to uppercase.
335
+ * @returns The uppercased character.
336
+ *
337
+ * @example
338
+ * ```typescript
339
+ * const usSettings = DotNetLocaleSettings.create('en-US');
340
+ * usSettings.toUpperChar('i'); // "I"
341
+ *
342
+ * const trSettings = DotNetLocaleSettings.create('tr-TR');
343
+ * trSettings.toUpperChar('i'); // "İ" (Turkish dotted I)
344
+ * ```
345
+ */
346
+ toUpperChar(char) {
347
+ if (char.length === 0) {
348
+ return char;
349
+ }
350
+ // For single character conversion, use Intl.Collator with locale-specific rules
351
+ // Most locales follow standard Unicode case mapping
352
+ const single = char[0];
353
+ // Turkish locale has special rules for 'i' and 'ı'
354
+ if (this.name.startsWith("tr")) {
355
+ // Turkish lowercase: i (U+0069) -> Turkish uppercase: İ (U+0130)
356
+ // Turkish lowercase: ı (U+0131) -> Turkish uppercase: I (U+0049)
357
+ if (single === "i") {
358
+ return "İ";
359
+ }
360
+ if (single === "ı") {
361
+ return "I";
362
+ }
363
+ }
364
+ // For other locales, use standard toUpperCase
365
+ return single.toUpperCase();
366
+ }
367
+ /**
368
+ * Convert a single character to lowercase using culture-specific rules.
369
+ * Handles special cases like Turkish 'I' → 'ı' vs Turkish 'İ' → 'i'.
370
+ *
371
+ * @param char - The character to convert to lowercase.
372
+ * @returns The lowercased character.
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * const usSettings = DotNetLocaleSettings.create('en-US');
377
+ * usSettings.toLowerChar('I'); // "i"
378
+ *
379
+ * const trSettings = DotNetLocaleSettings.create('tr-TR');
380
+ * trSettings.toLowerChar('I'); // "ı" (Turkish dotless i)
381
+ * trSettings.toLowerChar('İ'); // "i" (Turkish dotted i)
382
+ * ```
383
+ */
384
+ toLowerChar(char) {
385
+ if (char.length === 0) {
386
+ return char;
387
+ }
388
+ const single = char[0];
389
+ // Turkish locale has special rules for 'I' and 'İ'
390
+ if (this.name.startsWith("tr")) {
391
+ // Turkish uppercase: I (U+0049) -> Turkish lowercase: ı (U+0131)
392
+ // Turkish uppercase: İ (U+0130) -> Turkish lowercase: i (U+0069)
393
+ if (single === "I") {
394
+ return "ı";
395
+ }
396
+ if (single === "İ") {
397
+ return "i";
398
+ }
399
+ }
400
+ // For other locales, use standard toLowerCase
401
+ return single.toLowerCase();
402
+ }
403
+ }
404
+ //# sourceMappingURL=locale-settings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-settings.js","sourceRoot":"","sources":["../../src/code/locale-settings.ts"],"names":[],"mappings":"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"}