@zelgadis87/utils-core 5.3.3 → 5.3.5

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.
@@ -549,6 +549,22 @@ declare class TimeInstant extends TimeBase<TimeInstant> {
549
549
  }
550
550
  declare function isTimeInstant(x: unknown): x is TimeInstant;
551
551
 
552
+ declare function parseTimeInstantComponents(dateString: string, pattern: string, config?: {
553
+ locale?: string;
554
+ timeZone?: string;
555
+ }): Partial<TTimeInstantParameters>;
556
+ type TBasicTimePattern = 'y' | 'yy' | 'yyyy' | 'M' | 'MM' | 'd' | 'dd' | 'H' | 'HH' | 'm' | 'mm' | 's' | 'ss' | 'S' | 'SS' | 'SSS' | 'yyyy-MM-dd' | 'yyyy-MM-dd HH:mm' | 'yyyy-MM-dd HH:mm:ss' | 'yyyy-MM-dd HH:mm:ss.SSS' | 'yyyy/MM/dd' | 'yyyy/MM/dd HH:mm' | 'yyyy/MM/dd HH:mm:ss' | 'yyyy/MM/dd HH:mm:ss.SSS' | 'MM/dd/yyyy' | 'MM/dd/yyyy HH:mm' | 'MM/dd/yyyy HH:mm:ss' | 'MM/dd/yyyy HH:mm:ss.SSS' | 'dd/MM/yyyy' | 'dd/MM/yyyy HH:mm' | 'dd/MM/yyyy HH:mm:ss' | 'dd/MM/yyyy HH:mm:ss.SSS' | 'HH:mm:ss' | 'HH:mm';
557
+ /**
558
+ * Parses a date string using only basic patterns that don't require Intl.
559
+ * This is a safer alternative to parseTimeInstantComponents that works even when Intl is not available.
560
+ *
561
+ * @param dateString The date string to parse
562
+ * @param pattern A basic pattern that doesn't require Intl (strongly typed)
563
+ * @returns Partial time instant parameters that were parsed from the string
564
+ * @throws Error if the string doesn't match the pattern or contains invalid values
565
+ */
566
+ declare function parseTimeInstantBasicComponents(dateString: string, pattern: TBasicTimePattern, ignoreIntlAvailability?: boolean): Partial<TTimeInstantParameters>;
567
+
552
568
  declare class TimeDuration extends TimeBase<TimeDuration> {
553
569
  protected constructor(value: number, unit: TimeUnit);
554
570
  protected create(value: number, unit: TimeUnit): TimeDuration;
@@ -762,13 +778,14 @@ declare function indexByNumberWith<V, R = V>(arr: V[], keyGetter: TFunction<V, n
762
778
  declare function indexBySymbolWith<V, R = V>(arr: V[], keyGetter: TFunction<V, symbol>, valueMapper?: TFunction<V, R>): Record<symbol, R>;
763
779
  declare function indexByWith<K extends string | number | symbol, V, R = V>(arr: V[], keyGetter: TFunction<V, K>, valueMapper?: TFunction<V, R>): Record<K, R>;
764
780
 
765
- declare function average(arr: TReadableArray<number>): number;
781
+ declare function average(arr: TReadableArray<number>): TMaybe<number>;
782
+ declare function averageBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): TMaybe<number>;
766
783
  declare function sum(arr: TReadableArray<number>): number;
767
784
  declare function sumBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): number;
768
- declare function min(arr: TReadableArray<number>): number;
769
- declare function minBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): number;
770
- declare function max(arr: TReadableArray<number>): number;
771
- declare function maxBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): number;
785
+ declare function min(arr: TReadableArray<number>): TMaybe<number>;
786
+ declare function minBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): TMaybe<number>;
787
+ declare function max(arr: TReadableArray<number>): TMaybe<number>;
788
+ declare function maxBy<T>(arr: TReadableArray<T>, getter: (t: T) => number): TMaybe<number>;
772
789
 
773
790
  declare function uniq<T>(arr: T[]): T[];
774
791
  declare function uniqBy<T, K>(arr: T[], getter: TFunction<T, K>): T[];
@@ -791,7 +808,28 @@ declare function isArray<const T>(t: unknown): t is Array<T>;
791
808
  */
792
809
  declare function upsert<T>(arr: ReadonlyArray<T>, item: T, isEqual: TBiPredicate<T>): Array<T>;
793
810
  declare function range(start: number, end: number): Array<number>;
811
+ /**
812
+ * Creates an array of the specified length, where each element is filled with the given value.
813
+ * @param length - The length of the array to create. Must be a non-negative integer.
814
+ * @param value - The value to fill each element with.
815
+ * @returns A new array with all elements set to the given value.
816
+ * @throws {RangeError} If length is negative, not an integer, or NaN.
817
+ * @example
818
+ * ```ts
819
+ * fill(3, 'a'); // ['a', 'a', 'a']
820
+ * fill(0, 42); // []
821
+ * fill(5, null); // [null, null, null, null, null]
822
+ * ```
823
+ */
794
824
  declare function fill<T>(length: number, value: T): Array<T>;
825
+ /**
826
+ * Creates an array of the specified length, where each element is generated by the provided generator function.
827
+ * @param length - The length of the array to create. Must be a non-negative integer.
828
+ * @param generator - A function that takes an index and returns the value for that position.
829
+ * @returns A new array with elements generated by the generator function.
830
+ * @throws {RangeError} If length is negative or not an integer.
831
+ */
832
+ declare function fillWith<T>(length: number, generator: TFunction<number, T>): Array<T>;
795
833
  declare function extendArray<T extends Record<string | number | symbol, unknown>, X extends Record<string | number | symbol, unknown>>(arr: TReadableArray<T>, props: X): Array<(T & X)>;
796
834
  declare function extendArrayWith<T extends Record<string | number | symbol, unknown>, X extends Record<string | number | symbol, unknown>>(arr: TReadableArray<T>, propsFn: (t: T) => X): Array<(T & X)>;
797
835
  declare function reverse<T>(arr: TReadableArray<T>): Array<T>;
@@ -1406,5 +1444,5 @@ declare class DataUpgrader<X extends TUpgradable, XLatest extends X> implements
1406
1444
  }
1407
1445
  declare function isUpgradable(obj: TJsonSerializable): obj is TUpgradable;
1408
1446
 
1409
- export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomId, randomNumberInInterval, range, repeat, reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
1410
- export type { ICancelable, ICancelablePromise, IDataUpgrader, TAccumulator, TAllKeysOptional, TAnyFunction, TArrayable, TAsyncAnyFunction, TAsyncBiConsumer, TAsyncBiFunction, TAsyncBiPredicate, TAsyncConsumer, TAsyncFunction, TAsyncOperation, TAsyncOperationTuple, TAsyncPredicate, TAsyncProducer, TAsyncValidation, TAsyncVoidFunction, TBiConsumer, TBiFunction, TBiPredicate, TComparisonDirection, TComparisonFunction, TComparisonResult, TConditionalOptionalType, TConditionalParameter, TConditionalParameterOptions, TConsumer, TCssDeclarationRulesDictionary, TCssSelectorDeclarationRulesDictionary, TDayOfMonth, TDayOfWeek, TDigit, TDigit1_9, TEmpty, TEmptyArray, TEmptyObject, TEmptyOptional, TFourDigits, TFourDigitsMillisecond, TFourDigitsYear, TFunction, THasNever, THourOfDay, THtmlString, TIdentityFunction, TIntervalHandle, TIsEmptyObject, TIso8601DateString, TIso8601DateUtcString, TJsonArray, TJsonObject, TJsonPrimitive, TJsonSerializable, TKeysOfType, TLoggerOpts, TMaybe, TMillisecondOfSecond, TMinuteOfHour, TMonth, TMonthName, TNegativeNumber, TNumber0_10, TNumber0_100, TNumber0_1000, TNumber0_15, TNumber0_20, TNumber0_5, TNumber1_10, TNumericFloatingPointString, TNumericString, TOneDigit, TOperation, TOperationTuple, TOptional, TOptionalKeysForType, TOptionsWithoutDefaults, TParseInt, TParseableInt, TPositiveNumber, TPredefinedTimeDuration, TPredicate, TPresentOptional, TPrettify, TPrimitive, TProducer, TPromisable, TReadableArray, TRelativeUrl, TReplaceType, TRequiredKeysForType, TSecondOfMinute, TSorter, TSorterBuilder, TStrictComparisonResult, TThreeDigits, TThreeDigitsMillisecond, TTimeInUnits, TTimeoutHandle, TTransformer, TTwoDigits, TTwoDigitsDate, TTwoDigitsHour, TTwoDigitsMinute, TTwoDigitsMonth, TTwoDigitsSecond, TTypePredicate, TUpToFourDigits, TUpToThreeDigits, TUpToTwoDigits, TUpgradable, TUrl, TValidTimeDuration, TValidation, TVoidFunction, TWeekNumber, TWithExtras, TWithRequiredProperties, TWithRequiredProperty, TYear, TZero };
1447
+ export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomId, randomNumberInInterval, range, repeat, reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
1448
+ export type { ICancelable, ICancelablePromise, IDataUpgrader, TAccumulator, TAllKeysOptional, TAnyFunction, TArrayable, TAsyncAnyFunction, TAsyncBiConsumer, TAsyncBiFunction, TAsyncBiPredicate, TAsyncConsumer, TAsyncFunction, TAsyncOperation, TAsyncOperationTuple, TAsyncPredicate, TAsyncProducer, TAsyncValidation, TAsyncVoidFunction, TBasicTimePattern, TBiConsumer, TBiFunction, TBiPredicate, TComparisonDirection, TComparisonFunction, TComparisonResult, TConditionalOptionalType, TConditionalParameter, TConditionalParameterOptions, TConsumer, TCssDeclarationRulesDictionary, TCssSelectorDeclarationRulesDictionary, TDayOfMonth, TDayOfWeek, TDigit, TDigit1_9, TEmpty, TEmptyArray, TEmptyObject, TEmptyOptional, TFourDigits, TFourDigitsMillisecond, TFourDigitsYear, TFunction, THasNever, THourOfDay, THtmlString, TIdentityFunction, TIntervalHandle, TIsEmptyObject, TIso8601DateString, TIso8601DateUtcString, TJsonArray, TJsonObject, TJsonPrimitive, TJsonSerializable, TKeysOfType, TLoggerOpts, TMaybe, TMillisecondOfSecond, TMinuteOfHour, TMonth, TMonthName, TNegativeNumber, TNumber0_10, TNumber0_100, TNumber0_1000, TNumber0_15, TNumber0_20, TNumber0_5, TNumber1_10, TNumericFloatingPointString, TNumericString, TOneDigit, TOperation, TOperationTuple, TOptional, TOptionalKeysForType, TOptionsWithoutDefaults, TParseInt, TParseableInt, TPositiveNumber, TPredefinedTimeDuration, TPredicate, TPresentOptional, TPrettify, TPrimitive, TProducer, TPromisable, TReadableArray, TRelativeUrl, TReplaceType, TRequiredKeysForType, TSecondOfMinute, TSorter, TSorterBuilder, TStrictComparisonResult, TThreeDigits, TThreeDigitsMillisecond, TTimeInUnits, TTimeoutHandle, TTransformer, TTwoDigits, TTwoDigitsDate, TTwoDigitsHour, TTwoDigitsMinute, TTwoDigitsMonth, TTwoDigitsSecond, TTypePredicate, TUpToFourDigits, TUpToThreeDigits, TUpToTwoDigits, TUpgradable, TUrl, TValidTimeDuration, TValidation, TVoidFunction, TWeekNumber, TWithExtras, TWithRequiredProperties, TWithRequiredProperty, TYear, TZero };
package/.rollup/index.mjs CHANGED
@@ -445,9 +445,14 @@ function indexByWith(arr, keyGetter, valueMapper = v => v) {
445
445
  }
446
446
 
447
447
  function average(arr) {
448
+ if (arr.length === 0)
449
+ return null;
448
450
  const f = 1 / arr.length;
449
451
  return arr.reduce((tot, cur) => tot + (cur * f), 0);
450
452
  }
453
+ function averageBy(arr, getter) {
454
+ return average(arr.map(getter));
455
+ }
451
456
  function sum(arr) {
452
457
  return arr.reduce((tot, cur) => tot + cur, 0);
453
458
  }
@@ -456,7 +461,7 @@ function sumBy(arr, getter) {
456
461
  }
457
462
  function min(arr) {
458
463
  if (arr.length === 0)
459
- throw new Error('Cannot calculate value on empty array');
464
+ return null;
460
465
  return arr.reduce((min, cur) => cur < min ? cur : min);
461
466
  }
462
467
  function minBy(arr, getter) {
@@ -464,7 +469,7 @@ function minBy(arr, getter) {
464
469
  }
465
470
  function max(arr) {
466
471
  if (arr.length === 0)
467
- throw new Error('Cannot calculate value on empty array');
472
+ return null;
468
473
  return arr.reduce((max, cur) => cur > max ? cur : max);
469
474
  }
470
475
  function maxBy(arr, getter) {
@@ -619,9 +624,36 @@ function range(start, end) {
619
624
  let length = (end - start) + 1;
620
625
  return new Array(length).fill(1).map((_, i) => start + i);
621
626
  }
627
+ /**
628
+ * Creates an array of the specified length, where each element is filled with the given value.
629
+ * @param length - The length of the array to create. Must be a non-negative integer.
630
+ * @param value - The value to fill each element with.
631
+ * @returns A new array with all elements set to the given value.
632
+ * @throws {RangeError} If length is negative, not an integer, or NaN.
633
+ * @example
634
+ * ```ts
635
+ * fill(3, 'a'); // ['a', 'a', 'a']
636
+ * fill(0, 42); // []
637
+ * fill(5, null); // [null, null, null, null, null]
638
+ * ```
639
+ */
622
640
  function fill(length, value) {
641
+ if (!Number.isInteger(length) || length < 0)
642
+ throw new RangeError(`Length must be a non-negative integer. Got: ${length}`);
623
643
  return new Array(length).fill(value);
624
644
  }
645
+ /**
646
+ * Creates an array of the specified length, where each element is generated by the provided generator function.
647
+ * @param length - The length of the array to create. Must be a non-negative integer.
648
+ * @param generator - A function that takes an index and returns the value for that position.
649
+ * @returns A new array with elements generated by the generator function.
650
+ * @throws {RangeError} If length is negative or not an integer.
651
+ */
652
+ function fillWith(length, generator) {
653
+ if (!Number.isInteger(length) || length < 0)
654
+ throw new RangeError(`Length must be a non-negative integer. Got: ${length}`);
655
+ return Array.from({ length }, (_, i) => generator(i));
656
+ }
625
657
  function extendArray(arr, props) {
626
658
  return arr.map((t) => ({
627
659
  ...t,
@@ -2139,8 +2171,8 @@ class TimeInstant extends TimeBase {
2139
2171
  return timeInstantBuilder();
2140
2172
  }
2141
2173
  static fromIso8601(str) {
2142
- // Regex to capture: YYYY-MM-DDTHH:mm:ss.sssZ or YYYY-MM-DDTHH:mm:ss.sss±HH:mm
2143
- const iso8601Regex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})(Z|[+-]\d{2}:\d{2})?$/;
2174
+ // Regex to capture: YYYY-MM-DDTHH:mm:ss[.sss]Z or YYYY-MM-DDTHH:mm:ss[.sss]±HH:mm
2175
+ const iso8601Regex = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3})|)(Z|[+-]\d{2}:\d{2})?$/;
2144
2176
  const match = str.match(iso8601Regex);
2145
2177
  if (!match) {
2146
2178
  throw new Error('Invalid ISO 8601 date format: ' + str);
@@ -2153,7 +2185,7 @@ class TimeInstant extends TimeBase {
2153
2185
  const hours = parseInt(hourStr, 10);
2154
2186
  const minutes = parseInt(minuteStr, 10);
2155
2187
  const seconds = parseInt(secondStr, 10);
2156
- const milliseconds = parseInt(millisecondStr, 10);
2188
+ const milliseconds = millisecondStr ? parseInt(millisecondStr, 10) : 0;
2157
2189
  // Validate each component using standalone validation functions
2158
2190
  if (!isValidYear(year))
2159
2191
  throw new Error('Invalid year in: ' + str);
@@ -2589,6 +2621,216 @@ function parseTimeInstantComponents(dateString, pattern, config = {}) {
2589
2621
  }
2590
2622
  return result;
2591
2623
  }
2624
+ /**
2625
+ * Parses a date string using only basic patterns that don't require Intl.
2626
+ * This is a safer alternative to parseTimeInstantComponents that works even when Intl is not available.
2627
+ *
2628
+ * @param dateString The date string to parse
2629
+ * @param pattern A basic pattern that doesn't require Intl (strongly typed)
2630
+ * @returns Partial time instant parameters that were parsed from the string
2631
+ * @throws Error if the string doesn't match the pattern or contains invalid values
2632
+ */
2633
+ function parseTimeInstantBasicComponents(dateString, pattern, ignoreIntlAvailability = false) {
2634
+ // Check if Intl is available, if so warn the user about the existing function
2635
+ const isIntlAvailable = typeof Intl !== 'undefined' && typeof Intl.DateTimeFormat !== 'undefined';
2636
+ if (isIntlAvailable && !ignoreIntlAvailability)
2637
+ console.warn('Intl is available, use parseTimeInstantComponents instead of parseTimeInstantBasicComponents.');
2638
+ const result = {};
2639
+ let patternIndex = 0;
2640
+ let dateStringIndex = 0;
2641
+ // Helper function to check if a character is a pattern token
2642
+ const isPatternChar = (char) => ['y', 'M', 'd', 'H', 'm', 's', 'S'].includes(char);
2643
+ // Token extraction rules dictionary
2644
+ const tokenRules = {
2645
+ '': { maxLength: undefined }, // Default rule
2646
+ 'H': {
2647
+ maxLength: 2,
2648
+ validator: (value) => /^\d{1,2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 23,
2649
+ description: 'Hour (0-23, 1-2 digits)'
2650
+ },
2651
+ 'HH': {
2652
+ maxLength: 2,
2653
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 23,
2654
+ description: 'Hour (00-23, exactly 2 digits)'
2655
+ },
2656
+ 'M': {
2657
+ maxLength: 2,
2658
+ validator: (value) => /^\d{1,2}$/.test(value) && parseInt(value, 10) >= 1 && parseInt(value, 10) <= 12,
2659
+ description: 'Month (1-12, 1-2 digits)'
2660
+ },
2661
+ 'MM': {
2662
+ maxLength: 2,
2663
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 1 && parseInt(value, 10) <= 12,
2664
+ description: 'Month (01-12, exactly 2 digits)'
2665
+ },
2666
+ 'd': {
2667
+ maxLength: 2,
2668
+ validator: (value) => /^\d{1,2}$/.test(value) && parseInt(value, 10) >= 1 && parseInt(value, 10) <= 31,
2669
+ description: 'Day (1-31, 1-2 digits)'
2670
+ },
2671
+ 'dd': {
2672
+ maxLength: 2,
2673
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 1 && parseInt(value, 10) <= 31,
2674
+ description: 'Day (01-31, exactly 2 digits)'
2675
+ },
2676
+ 'm': {
2677
+ maxLength: 2,
2678
+ validator: (value) => /^\d{1,2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 59,
2679
+ description: 'Minutes (0-59, 1-2 digits)'
2680
+ },
2681
+ 'mm': {
2682
+ maxLength: 2,
2683
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 59,
2684
+ description: 'Minutes (00-59, exactly 2 digits)'
2685
+ },
2686
+ 's': {
2687
+ maxLength: 2,
2688
+ validator: (value) => /^\d{1,2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 59,
2689
+ description: 'Seconds (0-59, 1-2 digits)'
2690
+ },
2691
+ 'ss': {
2692
+ maxLength: 2,
2693
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 59,
2694
+ description: 'Seconds (00-59, exactly 2 digits)'
2695
+ },
2696
+ 'S': {
2697
+ maxLength: 3,
2698
+ validator: (value) => /^\d{1,3}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 999,
2699
+ description: 'Milliseconds (0-999, 1-3 digits)'
2700
+ },
2701
+ 'SS': {
2702
+ maxLength: 2,
2703
+ validator: (value) => /^\d{2}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 99,
2704
+ description: 'Milliseconds (0-99, exactly 2 digits)'
2705
+ },
2706
+ 'SSS': {
2707
+ maxLength: 3,
2708
+ validator: (value) => /^\d{3}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 999,
2709
+ description: 'Milliseconds (000-999, exactly 3 digits)'
2710
+ },
2711
+ 'y': {
2712
+ maxLength: 4,
2713
+ validator: (value) => /^\d{1,4}$/.test(value) && parseInt(value, 10) >= 0 && parseInt(value, 10) <= 9999,
2714
+ description: 'Year (0-9999, 1-4 digits)'
2715
+ },
2716
+ 'yy': {
2717
+ maxLength: 2,
2718
+ validator: (value) => /^\d{2}$/.test(value),
2719
+ description: 'Year (2 digits)'
2720
+ },
2721
+ 'yyyy': {
2722
+ maxLength: 4,
2723
+ validator: (value) => /^\d{4}$/.test(value),
2724
+ description: 'Year (4 digits)'
2725
+ }
2726
+ };
2727
+ // Helper function to extract a token value from the date string using token rules
2728
+ const extractValue = (tokenType, tokenLength) => {
2729
+ const tokenKey = tokenType.repeat(tokenLength);
2730
+ const rule = tokenRules[tokenKey] || tokenRules[''];
2731
+ // Extract consecutive digits up to maxLength
2732
+ let endIndex = dateStringIndex;
2733
+ let digitCount = 0;
2734
+ const maxChars = rule.maxLength || tokenLength;
2735
+ while (endIndex < dateString.length && /\d/.test(dateString[endIndex]) && digitCount < maxChars) {
2736
+ endIndex++;
2737
+ digitCount++;
2738
+ }
2739
+ const value = dateString.substring(dateStringIndex, endIndex);
2740
+ dateStringIndex = endIndex;
2741
+ // Validate the extracted value if a validator is provided
2742
+ if (rule.validator && !rule.validator(value)) {
2743
+ // Extract field name from description for better error messages
2744
+ const fieldName = (rule.description || tokenKey).split(' ')[0].toLowerCase();
2745
+ throw new Error(`Invalid ${fieldName} value: "${value}"`);
2746
+ }
2747
+ return value;
2748
+ };
2749
+ // Helper function to parse and validate a numeric value
2750
+ const parseNumericValue = (value, min, max, field) => {
2751
+ const num = parseInt(value, 10);
2752
+ if (isNaN(num) || num < min || num > max)
2753
+ throw new Error(`Invalid ${field} value: ${value}`);
2754
+ return num;
2755
+ };
2756
+ while (patternIndex < pattern.length) {
2757
+ const patternChar = pattern[patternIndex];
2758
+ if (isPatternChar(patternChar)) {
2759
+ // Start of a token - determine its full length
2760
+ let tokenLength = 0;
2761
+ while (patternIndex + tokenLength < pattern.length &&
2762
+ pattern[patternIndex + tokenLength] === patternChar) {
2763
+ tokenLength++;
2764
+ }
2765
+ // Extract and parse the corresponding value from the date string
2766
+ const value = extractValue(patternChar, tokenLength);
2767
+ // Check if we got enough characters for this token (after extraction)
2768
+ if (value.length < tokenLength) {
2769
+ throw new Error(`Date string "${dateString}" does not match pattern "${pattern}"`);
2770
+ }
2771
+ // Debug: log pattern processing (commented out for production)
2772
+ // console.log( `Processing patternChar="${patternChar}" with tokenLength=${tokenLength}, value="${value}"` );
2773
+ switch (patternChar) {
2774
+ case 'y': {
2775
+ if (tokenLength === 2) {
2776
+ // 2-digit year
2777
+ const shortYear = parseNumericValue(value, 0, 99, 'year');
2778
+ result.year = shortYear < 50 ? 2000 + shortYear : 1900 + shortYear;
2779
+ }
2780
+ else {
2781
+ // 4-digit year
2782
+ result.year = parseNumericValue(value, 0, 9999, 'year');
2783
+ }
2784
+ break;
2785
+ }
2786
+ case 'M':
2787
+ result.month = parseNumericValue(value, 1, 12, 'month');
2788
+ break;
2789
+ case 'd':
2790
+ result.date = parseNumericValue(value, 1, 31, 'day');
2791
+ break;
2792
+ case 'H':
2793
+ result.hours = parseNumericValue(value, 0, 23, 'hours');
2794
+ break;
2795
+ case 'm':
2796
+ result.minutes = parseNumericValue(value, 0, 59, 'minutes');
2797
+ break;
2798
+ case 's':
2799
+ result.seconds = parseNumericValue(value, 0, 59, 'seconds');
2800
+ break;
2801
+ case 'S': {
2802
+ let ms = parseInt(value, 10);
2803
+ if (isNaN(ms))
2804
+ throw new Error(`Invalid milliseconds value: ${value}`);
2805
+ // Normalize to milliseconds based on length
2806
+ if (tokenLength === 1)
2807
+ ms *= 100;
2808
+ else if (tokenLength === 2)
2809
+ ms *= 10;
2810
+ result.milliseconds = ms;
2811
+ break;
2812
+ }
2813
+ default:
2814
+ throw new Error(`Unsupported pattern character: ${patternChar}`);
2815
+ }
2816
+ patternIndex += tokenLength;
2817
+ }
2818
+ else {
2819
+ // Non-pattern character (separator like '-', '/', ':', ' ', '.')
2820
+ if (dateStringIndex >= dateString.length ||
2821
+ dateString[dateStringIndex] !== patternChar) {
2822
+ throw new Error(`Date string "${dateString}" does not match pattern "${pattern}"`);
2823
+ }
2824
+ patternIndex++;
2825
+ dateStringIndex++;
2826
+ }
2827
+ }
2828
+ // After processing the entire pattern, check if we consumed the entire date string
2829
+ if (dateStringIndex < dateString.length) {
2830
+ throw new Error(`Date string "${dateString}" does not match pattern "${pattern}"`);
2831
+ }
2832
+ return result;
2833
+ }
2592
2834
 
2593
2835
  const LEVELS = ["trace", "log", "debug", "info", "warn", "error"];
2594
2836
  const timestamp = () => TimeInstant.now().format('HH:mm:ss');
@@ -3263,5 +3505,5 @@ function isUpgradable(obj) {
3263
3505
  return isDefined(obj) && typeof obj === "object" && VERSION_FIELD in obj && isNumber(obj.$version) && isPositiveNumber(obj.$version);
3264
3506
  }
3265
3507
 
3266
- export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first$1 as first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last$1 as last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomId, randomNumberInInterval, range, repeat, reverse$1 as reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
3508
+ export { Cached, DataUpgrader, Deferred, DeferredCanceledError, ErrorCannotInstantiatePresentOptionalWithEmptyValue, ErrorGetEmptyOptional, ErrorSetEmptyOptional, Lazy, LazyAsync, LazyDictionary, Logger, NEVER, NonExhaustiveSwitchError, Operation, Optional, PredicateBuilder, RandomTimeDuration, RateThrottler, Semaphore, Sorter, StringParts, TimeDuration, TimeFrequency, TimeInstant, TimeRange, TimeUnit, TimeoutError, alwaysFalse, alwaysTrue, and, arrayGet, arrayIncludes, asError, asPromise, average, averageBy, awaitAtMost, capitalizeWord, clamp, clampInt0_100, constant, constantFalse, constantNull, constantOne, constantTrue, constantUndefined, constantZero, cssDeclarationRulesDictionaryToCss, decrement, decrementBy, delayPromise, dictToEntries, dictToList, divideBy, ellipsis, ensureArray, ensureDefined, ensureNegativeNumber, ensureNonNegativeNumber, ensureNonPositiveNumber, ensurePositiveNumber, ensureReadableArray, entriesToDict, entriesToEntries, entriesToList, extendArray, extendArrayWith, fill, fillWith, filterMap, filterMapReduce, filterWithTypePredicate, findInArray, findIndexInArray, first$1 as first, flatMapTruthys, getCauseMessageFromError, getCauseStackFromError, getMessageFromError, getStackFromError, groupByBoolean, groupByBooleanWith, groupByNumber, groupByNumberWith, groupByString, groupByStringWith, groupBySymbol, groupBySymbolWith, hashCode, head, identity, ifDefined, ifNullOrUndefined, iff, includes, increment, incrementBy, indexByNumber, indexByNumberWith, indexByString, indexByStringWith, indexBySymbol, indexBySymbolWith, indexByWith, isAllowedTimeDuration, isArray, isDefined, isEmpty, isError, isFalse, isFunction, isNegativeNumber, isNullOrUndefined, isNullOrUndefinedOrEmpty, isNumber, isPositiveNumber, isString, isTimeInstant, isTrue, isUpgradable, isZero, jsonCloneDeep, last$1 as last, listToDict, mapDefined, mapEntries, mapFirstTruthy, mapTruthys, max, maxBy, min, minBy, multiplyBy, noop, not, omitFromJsonObject, or, pad, padLeft, padRight, parseJson, parseTimeInstantBasicComponents, parseTimeInstantComponents, partition, pick, pipedInvoke, pipedInvokeFromArray, pluralize, promiseSequence, randomId, randomNumberInInterval, range, repeat, reverse$1 as reverse, round, roundAwayFromZero, roundToLower, roundToNearest, roundToUpper, roundTowardsZero, shallowArrayEquals, shallowRecordEquals, sortedArray, splitWords, stringToNumber, stringifyJson, sum, sumBy, tail, throttle, throwIfNullOrUndefined, transformCssDictionary, tryToParseJson, tryToParseNumber, uniq, uniqBy, uniqByKey, unzip, upsert, withTryCatch, withTryCatchAsync, wrapWithString, xor, zip };
3267
3509
  //# sourceMappingURL=index.mjs.map