@zthun/helpful-fn 9.11.5 → 9.11.7

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,29 @@
1
+ /**
2
+ * Attempts to cast the candidate to an enumeration value.
3
+ *
4
+ * @param enumeration -
5
+ * The enumeration type.
6
+ * @param candidate -
7
+ * The candidate to cast to the enum type.
8
+ *
9
+ * @returns
10
+ * The candidate if candidate represents the enumeration type,
11
+ * or undefined in the case that it does not.
12
+ */
13
+ export declare function castEnum<TEnum extends Record<string, string | number>>(enumeration: TEnum, candidate: unknown): TEnum[keyof TEnum] | undefined;
14
+ /**
15
+ * Attempts to cast the candidate to an enumeration value.
16
+ *
17
+ * @param enumeration -
18
+ * The enumeration type.
19
+ * @param candidate -
20
+ * The candidate to cast to the enum type.
21
+ * @param fallback -
22
+ * The fallback to use in the case that candidate
23
+ * cannot represent the enumeration type.
24
+ *
25
+ * @returns
26
+ * The candidate if candidate represents the enumeration type,
27
+ * or fallback in the case that it does not.
28
+ */
29
+ export declare function castEnum<TEnum extends Record<string, string | number>>(enumeration: TEnum, candidate: unknown, fallback: TEnum[keyof TEnum]): TEnum[keyof TEnum];
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Attempts to cast candidate to a number.
3
+ *
4
+ * This method assumes you want an actual number and
5
+ * not NaN. In the case that candidate results in
6
+ * NaN, then the fallback condition applies.
7
+ *
8
+ * @param candidate -
9
+ * The candidate to cast.
10
+ *
11
+ * @returns
12
+ * The casted number or undefined in the cast
13
+ * that casting candidate would result in NaN.
14
+ */
15
+ export declare function castNumber(candidate: unknown): number | undefined;
16
+ /**
17
+ * Attempts to cast candidate to a number.
18
+ *
19
+ * This method assumes you want an actual number and
20
+ * not NaN. In the case that candidate results in
21
+ * NaN, then the fallback condition applies.
22
+ *
23
+ * @param candidate -
24
+ * The candidate to cast.
25
+ * @param fallback -
26
+ * The fallback value in the case that the result
27
+ * of casting candidate would result in NaN
28
+ *
29
+ * @returns
30
+ * The casted number or fallback in the cast
31
+ * that casting candidate would result in NaN.
32
+ */
33
+ export declare function castNumber(candidate: unknown, fallback: number): number;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Returns the users current culture (locale).
3
+ *
4
+ * @returns
5
+ * The current locale.
6
+ */
7
+ export declare function culture(): string;
8
+ /**
9
+ * Returns all supported cultures.
10
+ *
11
+ * @returns
12
+ * A list of currently supported culture codes.
13
+ */
14
+ export declare function cultures(): string[];
@@ -0,0 +1,17 @@
1
+ import { enAU, enCA, enGB, enIE, enIN, enNZ, enUS, enZA, ja } from 'date-fns/locale';
2
+ /**
3
+ * Supported locales from date-fns.
4
+ *
5
+ * This should not be exported. This is an internal helper.
6
+ */
7
+ export declare const LocaleLookup: {
8
+ [enAU.code]: import('date-fns/locale').Locale;
9
+ [enCA.code]: import('date-fns/locale').Locale;
10
+ [enGB.code]: import('date-fns/locale').Locale;
11
+ [enIE.code]: import('date-fns/locale').Locale;
12
+ [enIN.code]: import('date-fns/locale').Locale;
13
+ [enNZ.code]: import('date-fns/locale').Locale;
14
+ [enUS.code]: import('date-fns/locale').Locale;
15
+ [enZA.code]: import('date-fns/locale').Locale;
16
+ [ja.code]: import('date-fns/locale').Locale;
17
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * The index offsets for the original roman calendar months.
3
+ *
4
+ * This is helpful when creating dates from numbers
5
+ * since it's easy to be off by 1 when specifying
6
+ * a month index.
7
+ */
8
+ export declare enum ZCalendarMonth {
9
+ January = 0,
10
+ February = 1,
11
+ March = 2,
12
+ April = 3,
13
+ May = 4,
14
+ June = 5,
15
+ July = 6,
16
+ August = 7,
17
+ September = 8,
18
+ October = 9,
19
+ November = 10,
20
+ December = 11
21
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Represents a value for a date time object.
3
+ */
4
+ export type ZDateTime = string | Date | number | null | undefined;
5
+ /**
6
+ * Options for performing operations on a {@link ZDateTime} object.
7
+ */
8
+ export type ZDateTimeOptions<T> = {
9
+ /**
10
+ * The string format to output.
11
+ */
12
+ format?: string;
13
+ /**
14
+ * A list of supported formats when guessing a date.
15
+ *
16
+ * If this is falsy, then the standard formats in
17
+ * {@link ZDateFormats} is used.
18
+ */
19
+ supportedFormats?: string[];
20
+ /**
21
+ * The culture language to use.
22
+ *
23
+ * If this is not specified, then you can assume
24
+ * that the user's system culture is used.
25
+ */
26
+ culture?: string;
27
+ /**
28
+ * The timezone to force.
29
+ *
30
+ * If this is not specified, then you can assume the
31
+ * user's current timezone.
32
+ */
33
+ timeZone?: string;
34
+ /**
35
+ * An optional fallback value for invalid date formats or bad parsing.
36
+ */
37
+ fallback?: T;
38
+ };
@@ -0,0 +1,52 @@
1
+ import { ZDateTime, ZDateTimeOptions } from '../date/date-time.mjs';
2
+ /**
3
+ * Basic date formats that are common for storage and usage.
4
+ */
5
+ export declare enum ZDateFormats {
6
+ /**
7
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format with date only.
8
+ *
9
+ * Using this should imply midnight user timezone.
10
+ */
11
+ IsoDateOnly = "yyyy-MM-dd",
12
+ /**
13
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format with time only.
14
+ */
15
+ IsoTimeOnly = "HH:mm:ss.SSS",
16
+ /**
17
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format without timezone specifier.
18
+ */
19
+ IsoNoTimeZone = "yyyy-MM-dd'T'HH:mm:ss.SSS",
20
+ /**
21
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format.
22
+ */
23
+ Iso = "yyyy-MM-dd'T'HH:mm:ss.SSSXX",
24
+ /**
25
+ * Users local date (locale specific).
26
+ */
27
+ LocalDate = "P",
28
+ /**
29
+ * User local time (locale specific).
30
+ */
31
+ LocalTime = "p",
32
+ /**
33
+ * Date and time formatted with user specific locale.
34
+ */
35
+ LocalDateTime = "Pp"
36
+ }
37
+ /**
38
+ * Formats a given value.
39
+ *
40
+ * @param value -
41
+ * The value to format.
42
+ * @param options -
43
+ * The given options for the format.
44
+ *
45
+ * @returns
46
+ * If value is null or undefined, then the empty string is returned.
47
+ * If value is a string, then the date is guessed from the string and
48
+ * reformatted to the format specified by options. Otherwise,
49
+ * the date or number specified by value is formatted to the culture,
50
+ * timezone, and format specified in the options.
51
+ */
52
+ export declare function formatDateTime(value: ZDateTime, options?: ZDateTimeOptions<string>): string;
@@ -0,0 +1,11 @@
1
+ import { ZDateTime, ZDateTimeOptions } from '../date/date-time.mjs';
2
+ /**
3
+ * Similar to {@link parseDateTime} but tries multiple supported formats.
4
+ *
5
+ * @param value -
6
+ * The value to parse that may result in a date.
7
+ * @param options -
8
+ * The options for guessing the date. These will be forwarded to parse
9
+ * for processing.
10
+ */
11
+ export declare function guessDateTime(value: ZDateTime, options?: ZDateTimeOptions<Date | null>): Date | null;
@@ -0,0 +1,21 @@
1
+ import { ZDateTime, ZDateTimeOptions } from '../date/date-time.mjs';
2
+ /**
3
+ * Parses a string value back to a date format.
4
+ *
5
+ *
6
+ * @param value -
7
+ * The value to parse
8
+ * @param options -
9
+ * The options to parse with. The most important option here is format.
10
+ * If the format is not specified, then the standard zoned ISO 8601
11
+ * format is used. The timezone is also used in the case the date
12
+ * does not supply it for string values. If the timezone is not specified
13
+ * then the users timezone is assumed. Finally, the cultural local will
14
+ * default to the users current culture if not specified.
15
+ *
16
+ * @returns
17
+ * The date object parsed from the value. Returns null
18
+ * if the value parsed with the given options results in an
19
+ * invalid date.
20
+ */
21
+ export declare function parseDateTime(value: ZDateTime, options?: ZDateTimeOptions<Date | null>): Date | null;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Returns the user's current timezone.
3
+ *
4
+ * @returns
5
+ * The users current timezone.
6
+ */
7
+ export declare function userTimeZone(): string;
8
+ /**
9
+ * Returns the list of all supported timezones.
10
+ *
11
+ * @returns
12
+ * A list of all timezone values.
13
+ */
14
+ export declare function timeZones(): string[];
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Gets whether the candidate can represent an enumeration object of type TEnum.
3
+ *
4
+ * This is mostly helpful for type guarding value options in a type.
5
+ *
6
+ * @param enumeration -
7
+ * The enumeration object that contains the values.
8
+ * @param candidate -
9
+ * The candidate to check.
10
+ *
11
+ * @returns
12
+ * True if candidate can represents one of the white listed
13
+ * object values in enumeration.
14
+ */
15
+ export declare function isEnum<TEnum extends Record<string, string | number>>(enumeration: TEnum, candidate: unknown): candidate is TEnum[keyof TEnum];
package/dist/index.cjs CHANGED
@@ -3,6 +3,9 @@
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  const uuid = require('uuid');
6
+ const locale = require('date-fns/locale');
7
+ const tz = require('@date-fns/tz');
8
+ const dateFns = require('date-fns');
6
9
 
7
10
  /**
8
11
  * Represents a targeted point along a y axis.
@@ -118,6 +121,41 @@ function _define_property$6(obj, key, value) {
118
121
  }
119
122
  }
120
123
 
124
+ /**
125
+ * Gets whether the candidate can represent an enumeration object of type TEnum.
126
+ *
127
+ * This is mostly helpful for type guarding value options in a type.
128
+ *
129
+ * @param enumeration -
130
+ * The enumeration object that contains the values.
131
+ * @param candidate -
132
+ * The candidate to check.
133
+ *
134
+ * @returns
135
+ * True if candidate can represents one of the white listed
136
+ * object values in enumeration.
137
+ */ function isEnum(enumeration, candidate) {
138
+ return candidate != null && (typeof candidate === "string" || typeof candidate === "number") && Object.values(enumeration).includes(candidate);
139
+ }
140
+
141
+ /**
142
+ * Attempts to cast the candidate to an enumeration value.
143
+ *
144
+ * @param enumeration -
145
+ * The enumeration type.
146
+ * @param candidate -
147
+ * The candidate to cast to the enum type.
148
+ * @param fallback -
149
+ * The fallback to use in the case that candidate
150
+ * cannot represent the enumeration type.
151
+ *
152
+ * @returns
153
+ * The candidate if candidate represents the enumeration type,
154
+ * or fallback in the case that it does not.
155
+ */ function castEnum(enumeration, candidate, fallback) {
156
+ return isEnum(enumeration, candidate) ? candidate : fallback;
157
+ }
158
+
121
159
  /**
122
160
  * Puts a . in front of name if one is not already there.
123
161
  *
@@ -160,6 +198,44 @@ function _define_property$6(obj, key, value) {
160
198
  return `.${normalized}`;
161
199
  }
162
200
 
201
+ /**
202
+ * Attempts to cast candidate to a number.
203
+ *
204
+ * This method assumes you want an actual number and
205
+ * not NaN. In the case that candidate results in
206
+ * NaN, then the fallback condition applies.
207
+ *
208
+ * @param candidate -
209
+ * The candidate to cast.
210
+ *
211
+ * @returns
212
+ * The casted number or undefined in the cast
213
+ * that casting candidate would result in NaN.
214
+ */ /**
215
+ * Attempts to cast candidate to a number.
216
+ *
217
+ * This method assumes you want an actual number and
218
+ * not NaN. In the case that candidate results in
219
+ * NaN, then the fallback condition applies.
220
+ *
221
+ * @param candidate -
222
+ * The candidate to cast.
223
+ * @param fallback -
224
+ * The fallback value in the case that the result
225
+ * of casting candidate would result in NaN
226
+ *
227
+ * @returns
228
+ * The casted number or fallback in the cast
229
+ * that casting candidate would result in NaN.
230
+ */ function castNumber(candidate, fallback) {
231
+ try {
232
+ const casted = Number(candidate);
233
+ return Number.isNaN(casted) ? fallback : casted;
234
+ } catch {
235
+ return fallback;
236
+ }
237
+ }
238
+
163
239
  /**
164
240
  * Calculates the total number of buckets you need to
165
241
  * store a number of items where each bucket can hold a
@@ -301,6 +377,187 @@ function _define_property$6(obj, key, value) {
301
377
  * ```
302
378
  */ const createGuid = uuid.v4;
303
379
 
380
+ /**
381
+ * Supported locales from date-fns.
382
+ *
383
+ * This should not be exported. This is an internal helper.
384
+ */ const LocaleLookup = {
385
+ [locale.enAU.code]: locale.enAU,
386
+ [locale.enCA.code]: locale.enCA,
387
+ [locale.enGB.code]: locale.enGB,
388
+ [locale.enIE.code]: locale.enIE,
389
+ [locale.enIN.code]: locale.enIN,
390
+ [locale.enNZ.code]: locale.enNZ,
391
+ [locale.enUS.code]: locale.enUS,
392
+ [locale.enZA.code]: locale.enZA,
393
+ [locale.ja.code]: locale.ja
394
+ };
395
+
396
+ /**
397
+ * Returns the users current culture (locale).
398
+ *
399
+ * @returns
400
+ * The current locale.
401
+ */ function culture() {
402
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale;
403
+ return locale;
404
+ }
405
+ /**
406
+ * Returns all supported cultures.
407
+ *
408
+ * @returns
409
+ * A list of currently supported culture codes.
410
+ */ function cultures() {
411
+ return Object.keys(LocaleLookup);
412
+ }
413
+
414
+ /**
415
+ * Returns the user's current timezone.
416
+ *
417
+ * @returns
418
+ * The users current timezone.
419
+ */ function userTimeZone() {
420
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
421
+ }
422
+ /**
423
+ * Returns the list of all supported timezones.
424
+ *
425
+ * @returns
426
+ * A list of all timezone values.
427
+ */ function timeZones() {
428
+ return Intl.supportedValuesOf("timeZone");
429
+ }
430
+
431
+ /**
432
+ * Parses a string value back to a date format.
433
+ *
434
+ *
435
+ * @param value -
436
+ * The value to parse
437
+ * @param options -
438
+ * The options to parse with. The most important option here is format.
439
+ * If the format is not specified, then the standard zoned ISO 8601
440
+ * format is used. The timezone is also used in the case the date
441
+ * does not supply it for string values. If the timezone is not specified
442
+ * then the users timezone is assumed. Finally, the cultural local will
443
+ * default to the users current culture if not specified.
444
+ *
445
+ * @returns
446
+ * The date object parsed from the value. Returns null
447
+ * if the value parsed with the given options results in an
448
+ * invalid date.
449
+ */ function parseDateTime(value, options = {}) {
450
+ const { fallback = null } = options;
451
+ if (value == null) {
452
+ return fallback;
453
+ }
454
+ if (typeof value === "number") {
455
+ const candidate = new Date(value);
456
+ return Number.isNaN(candidate.getTime()) ? fallback : candidate;
457
+ }
458
+ if (value instanceof Date) {
459
+ return Number.isNaN(value.getTime()) ? fallback : value;
460
+ }
461
+ const { format = ZDateFormats.Iso, culture: culture$1 = culture(), timeZone = userTimeZone() } = options;
462
+ const locale = LocaleLookup[culture$1];
463
+ const reference = new tz.TZDate(dateFns.startOfToday()).withTimeZone(timeZone);
464
+ const result = dateFns.parse(value, format, reference, {
465
+ locale
466
+ });
467
+ return Number.isNaN(result.getTime()) ? fallback : result;
468
+ }
469
+
470
+ /**
471
+ * Similar to {@link parseDateTime} but tries multiple supported formats.
472
+ *
473
+ * @param value -
474
+ * The value to parse that may result in a date.
475
+ * @param options -
476
+ * The options for guessing the date. These will be forwarded to parse
477
+ * for processing.
478
+ */ function guessDateTime(value, options = {}) {
479
+ const { fallback = null } = options;
480
+ if (value == null) {
481
+ return fallback;
482
+ }
483
+ const { supportedFormats = Object.values(ZDateFormats) } = options;
484
+ for (const fmt of supportedFormats){
485
+ const inner = {
486
+ ...options
487
+ };
488
+ inner.format = fmt;
489
+ const result = parseDateTime(value, inner);
490
+ if (result != null) {
491
+ return result;
492
+ }
493
+ }
494
+ return fallback;
495
+ }
496
+
497
+ /**
498
+ * Basic date formats that are common for storage and usage.
499
+ */ var ZDateFormats = /*#__PURE__*/ function(ZDateFormats) {
500
+ /**
501
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format with date only.
502
+ *
503
+ * Using this should imply midnight user timezone.
504
+ */ ZDateFormats["IsoDateOnly"] = "yyyy-MM-dd";
505
+ /**
506
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format with time only.
507
+ */ ZDateFormats["IsoTimeOnly"] = "HH:mm:ss.SSS";
508
+ /**
509
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format without timezone specifier.
510
+ */ ZDateFormats["IsoNoTimeZone"] = "yyyy-MM-dd'T'HH:mm:ss.SSS";
511
+ /**
512
+ * Standard {@link https://en.wikipedia.org/wiki/ISO_8601 | ISO-8601} format.
513
+ */ ZDateFormats["Iso"] = "yyyy-MM-dd'T'HH:mm:ss.SSSXX";
514
+ /**
515
+ * Users local date (locale specific).
516
+ */ ZDateFormats["LocalDate"] = "P";
517
+ /**
518
+ * User local time (locale specific).
519
+ */ ZDateFormats["LocalTime"] = "p";
520
+ /**
521
+ * Date and time formatted with user specific locale.
522
+ */ ZDateFormats["LocalDateTime"] = "Pp";
523
+ return ZDateFormats;
524
+ }({});
525
+ /**
526
+ * Formats a given value.
527
+ *
528
+ * @param value -
529
+ * The value to format.
530
+ * @param options -
531
+ * The given options for the format.
532
+ *
533
+ * @returns
534
+ * If value is null or undefined, then the empty string is returned.
535
+ * If value is a string, then the date is guessed from the string and
536
+ * reformatted to the format specified by options. Otherwise,
537
+ * the date or number specified by value is formatted to the culture,
538
+ * timezone, and format specified in the options.
539
+ */ function formatDateTime(value, options = {}) {
540
+ const { format = "Pp", culture: culture$1 = culture(), timeZone = userTimeZone(), fallback = "" } = options;
541
+ let date;
542
+ if (value == null) {
543
+ date = null;
544
+ } else if (typeof value === "string") {
545
+ date = guessDateTime(value, {
546
+ ...options,
547
+ fallback: null
548
+ });
549
+ } else {
550
+ date = new Date(value);
551
+ }
552
+ if (date == null || Number.isNaN(date.getTime())) {
553
+ return fallback;
554
+ }
555
+ const withTz = new tz.TZDate(date, timeZone);
556
+ return dateFns.formatDate(withTz, format, {
557
+ locale: LocaleLookup[culture$1]
558
+ });
559
+ }
560
+
304
561
  /**
305
562
  * Does replacement of interpolation, ${}, tokens in a string.
306
563
  *
@@ -1801,6 +2058,7 @@ function _define_property(obj, key, value) {
1801
2058
 
1802
2059
  exports.$global = $global;
1803
2060
  exports.ZAssert = ZAssert;
2061
+ exports.ZDateFormats = ZDateFormats;
1804
2062
  exports.ZDeserializeJson = ZDeserializeJson;
1805
2063
  exports.ZDeserializeTry = ZDeserializeTry;
1806
2064
  exports.ZHorizontalAnchor = ZHorizontalAnchor;
@@ -1812,21 +2070,28 @@ exports.ZRectangle = ZRectangle;
1812
2070
  exports.ZSerializeJson = ZSerializeJson;
1813
2071
  exports.ZVerticalAnchor = ZVerticalAnchor;
1814
2072
  exports.bash = bash;
2073
+ exports.castEnum = castEnum;
1815
2074
  exports.castExtension = castExtension;
2075
+ exports.castNumber = castNumber;
1816
2076
  exports.commaJoinDefined = commaJoinDefined;
1817
2077
  exports.countBuckets = countBuckets;
1818
2078
  exports.createError = createError;
1819
2079
  exports.createGuid = createGuid;
1820
2080
  exports.css = css;
1821
2081
  exports.cssJoinDefined = cssJoinDefined;
2082
+ exports.culture = culture;
2083
+ exports.cultures = cultures;
1822
2084
  exports.detokenize = detokenize;
1823
2085
  exports.firstDefined = firstDefined;
1824
2086
  exports.firstTruthy = firstTruthy;
1825
2087
  exports.firstWhere = firstWhere;
2088
+ exports.formatDateTime = formatDateTime;
1826
2089
  exports.gib = gib;
1827
2090
  exports.gibibytes = gibibytes;
2091
+ exports.guessDateTime = guessDateTime;
1828
2092
  exports.html = html;
1829
2093
  exports.isEmptyObject = isEmptyObject;
2094
+ exports.isEnum = isEnum;
1830
2095
  exports.javascript = javascript;
1831
2096
  exports.joinDefined = joinDefined;
1832
2097
  exports.js = js;
@@ -1837,6 +2102,7 @@ exports.md = md;
1837
2102
  exports.mebibytes = mebibytes;
1838
2103
  exports.mib = mib;
1839
2104
  exports.optional = optional;
2105
+ exports.parseDateTime = parseDateTime;
1840
2106
  exports.pebibytes = pebibytes;
1841
2107
  exports.peel = peel;
1842
2108
  exports.peelBetween = peelBetween;
@@ -1856,10 +2122,12 @@ exports.spaceJoinDefined = spaceJoinDefined;
1856
2122
  exports.tag = tag;
1857
2123
  exports.tebibytes = tebibytes;
1858
2124
  exports.tib = tib;
2125
+ exports.timeZones = timeZones;
1859
2126
  exports.tryFallback = tryFallback;
1860
2127
  exports.tryFallbackAsync = tryFallbackAsync;
1861
2128
  exports.tryJsonParse = tryJsonParse;
1862
2129
  exports.ts = ts;
1863
2130
  exports.typescript = typescript;
2131
+ exports.userTimeZone = userTimeZone;
1864
2132
  exports.zsh = zsh;
1865
2133
  //# sourceMappingURL=index.cjs.map