@zelgadis87/utils-core 5.3.5 → 5.3.6
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.
- package/.rollup/index.cjs +78 -24
- package/.rollup/index.cjs.map +1 -1
- package/.rollup/index.mjs +78 -24
- package/.rollup/index.mjs.map +1 -1
- package/.rollup/tsconfig.tsbuildinfo +1 -1
- package/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/time/TimeInstant.ts +84 -24
package/.rollup/index.cjs
CHANGED
|
@@ -2345,8 +2345,48 @@ function normalizeMonthName(name) {
|
|
|
2345
2345
|
// Trim whitespace
|
|
2346
2346
|
.trim();
|
|
2347
2347
|
}
|
|
2348
|
-
const PATTERN_REGEX = /(M|y|d|D|h|H|m|s|S|G|Z|P|a)+/g;
|
|
2349
2348
|
const ESCAPE_REGEX = /\\"|"((?:\\"|[^"])*)"/g;
|
|
2349
|
+
/**
|
|
2350
|
+
* Tokenize a date/time pattern by detecting character changes.
|
|
2351
|
+
*
|
|
2352
|
+
* This function uses a character-change detection algorithm to split a pattern into tokens:
|
|
2353
|
+
* 1. Iterates through the pattern character by character
|
|
2354
|
+
* 2. Detects when the character changes (e.g., 'y' → 'M' → 'd')
|
|
2355
|
+
* 3. Creates tokens based on consecutive identical characters
|
|
2356
|
+
* 4. Marks tokens as pattern tokens only if they consist of repeated pattern characters
|
|
2357
|
+
*
|
|
2358
|
+
* This approach works correctly for patterns with or without separators:
|
|
2359
|
+
* - "yyyy-MM-dd" → [{token:"yyyy", type:"y"}, {token:"-", type:null}, {token:"MM", type:"M"}, {token:"-", type:null}, {token:"dd", type:"d"}]
|
|
2360
|
+
* - "yyyyMMdd" → [{token:"yyyy", type:"y"}, {token:"MM", type:"M"}, {token:"dd", type:"d"}]
|
|
2361
|
+
*
|
|
2362
|
+
* @param pattern - The date/time pattern to tokenize
|
|
2363
|
+
* @returns Array of tokens with their types (null for separators/literals, pattern char for pattern tokens)
|
|
2364
|
+
*/
|
|
2365
|
+
function tokenizePattern(pattern) {
|
|
2366
|
+
const result = [];
|
|
2367
|
+
let currentToken = '';
|
|
2368
|
+
let currentChar = '';
|
|
2369
|
+
for (const char of pattern) {
|
|
2370
|
+
if (char === currentChar) {
|
|
2371
|
+
// Same character, extend current token
|
|
2372
|
+
currentToken += char;
|
|
2373
|
+
}
|
|
2374
|
+
else {
|
|
2375
|
+
// Character changed, end current token and start new one
|
|
2376
|
+
if (currentToken) {
|
|
2377
|
+
// Mark the token with its character (caller will decide if it's a valid pattern)
|
|
2378
|
+
result.push({ token: currentToken, type: currentChar });
|
|
2379
|
+
}
|
|
2380
|
+
currentToken = char;
|
|
2381
|
+
currentChar = char;
|
|
2382
|
+
}
|
|
2383
|
+
}
|
|
2384
|
+
// Don't forget the last token
|
|
2385
|
+
if (currentToken) {
|
|
2386
|
+
result.push({ token: currentToken, type: currentChar });
|
|
2387
|
+
}
|
|
2388
|
+
return result;
|
|
2389
|
+
}
|
|
2350
2390
|
// Formatter configuration mapping: token pattern -> configuration with optional extraction rules
|
|
2351
2391
|
const formatterConfigs = {
|
|
2352
2392
|
// Year
|
|
@@ -2428,11 +2468,16 @@ function formatTimeInstant(instant, pattern, config = {}) {
|
|
|
2428
2468
|
if (index % 2 !== 0) {
|
|
2429
2469
|
return sub;
|
|
2430
2470
|
}
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2471
|
+
// Tokenize the pattern by detecting character changes
|
|
2472
|
+
const tokens = tokenizePattern(sub);
|
|
2473
|
+
// Format each token and join the results
|
|
2474
|
+
return tokens.map(({ token, type }) => {
|
|
2475
|
+
// If type is null or formatting fails, keep token as-is
|
|
2476
|
+
if (!type)
|
|
2477
|
+
return token;
|
|
2478
|
+
const formatted = formatType(type, token.length, date, locale, timeZone);
|
|
2479
|
+
return formatted !== undefined ? formatted : token;
|
|
2480
|
+
}).join('');
|
|
2436
2481
|
})
|
|
2437
2482
|
.join('');
|
|
2438
2483
|
}
|
|
@@ -2460,53 +2505,62 @@ function parseTimeInstantComponents(dateString, pattern, config = {}) {
|
|
|
2460
2505
|
if (index % 2 !== 0) {
|
|
2461
2506
|
return sub.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // Escape special regex chars
|
|
2462
2507
|
}
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2508
|
+
// Tokenize the pattern by detecting character changes
|
|
2509
|
+
const patternTokens = tokenizePattern(sub);
|
|
2510
|
+
// Build regex pattern from tokens
|
|
2511
|
+
return patternTokens.map(({ token, type }) => {
|
|
2512
|
+
// Check if this is a valid pattern by looking it up in formatterConfigs
|
|
2513
|
+
const isValidPattern = type && formatterConfigs[token];
|
|
2514
|
+
if (!isValidPattern) {
|
|
2515
|
+
// This is a literal/separator, escape it for regex
|
|
2516
|
+
return token.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
2517
|
+
}
|
|
2518
|
+
// This is a pattern token, track it and create regex
|
|
2519
|
+
tokens.push({ type, length: token.length, position: position++ });
|
|
2466
2520
|
// Create appropriate regex for each token type
|
|
2467
2521
|
switch (type) {
|
|
2468
2522
|
case 'y':
|
|
2469
|
-
return
|
|
2523
|
+
return token.length === 2 ? '(\\d{2})' : '(\\d{4})';
|
|
2470
2524
|
case 'M':
|
|
2471
|
-
if (
|
|
2525
|
+
if (token.length === 1)
|
|
2472
2526
|
return '(\\d{1,2})';
|
|
2473
|
-
if (
|
|
2527
|
+
if (token.length === 2)
|
|
2474
2528
|
return '(\\d{2})';
|
|
2475
|
-
if (
|
|
2529
|
+
if (token.length === 3)
|
|
2476
2530
|
return '([A-Za-z.]{1,7})';
|
|
2477
2531
|
return '([A-Za-z]+)';
|
|
2478
2532
|
case 'd':
|
|
2479
|
-
return
|
|
2533
|
+
return token.length === 1 ? '(\\d{1,2})' : '(\\d{2})';
|
|
2480
2534
|
case 'H':
|
|
2481
2535
|
case 'h':
|
|
2482
|
-
return
|
|
2536
|
+
return token.length === 1 ? '(\\d{1,2})' : '(\\d{2})';
|
|
2483
2537
|
case 'm':
|
|
2484
2538
|
case 's':
|
|
2485
|
-
return
|
|
2539
|
+
return token.length === 1 ? '(\\d{1,2})' : '(\\d{2})';
|
|
2486
2540
|
case 'S':
|
|
2487
|
-
return `(\\d{${
|
|
2541
|
+
return `(\\d{${token.length}})`;
|
|
2488
2542
|
case 'a':
|
|
2489
2543
|
return '([aApP][mM])';
|
|
2490
2544
|
case 'D':
|
|
2491
|
-
if (
|
|
2545
|
+
if (token.length === 1)
|
|
2492
2546
|
return '([A-Za-z])';
|
|
2493
|
-
if (
|
|
2547
|
+
if (token.length === 2)
|
|
2494
2548
|
return '([A-Za-z]{3})';
|
|
2495
2549
|
return '([A-Za-z]+)';
|
|
2496
2550
|
case 'G':
|
|
2497
|
-
if (
|
|
2551
|
+
if (token.length === 1)
|
|
2498
2552
|
return '([A-Za-z])';
|
|
2499
|
-
if (
|
|
2553
|
+
if (token.length === 2)
|
|
2500
2554
|
return '([A-Za-z]{2})';
|
|
2501
2555
|
return '([A-Za-z\\s]+)';
|
|
2502
2556
|
case 'Z':
|
|
2503
|
-
return
|
|
2557
|
+
return token.length === 1 ? '([A-Za-z0-9+\\-:]+)' : '([A-Za-z\\s]+)';
|
|
2504
2558
|
case 'P':
|
|
2505
2559
|
return '([A-Za-z\\s]+)';
|
|
2506
2560
|
default:
|
|
2507
|
-
return
|
|
2561
|
+
return token;
|
|
2508
2562
|
}
|
|
2509
|
-
});
|
|
2563
|
+
}).join('');
|
|
2510
2564
|
}).join('');
|
|
2511
2565
|
const regex = new RegExp('^' + regexPattern + '$');
|
|
2512
2566
|
const matches = dateString.match(regex);
|