Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | 14x 14x 14x 14x 98x 14x 28x 185x 185x 43x 142x 142x 517x 1x 141x 1114x 1114x 1114x 141x 141x 1114x 141x 9x 141x 14x 14x 14x 156x 156x 15x 141x | import { Duration } from '../types'; import { ZERO, UnitKey } from './units'; import { negate } from '../negate'; import { isNegativelySigned } from './numberUtils'; const millisecondsPattern = '(?:[,.](\\d{1,3})\\d*)?'; const unitPattern = (unit: string) => `(?:(-?\\d+)${unit})?`; const createDurationParser = ( regex: RegExp, unitsOrder: UnitKey[], ) => { return (duration: string): Duration | null => { const match = duration.match(regex); if (!match) { return null; } const isDurationNegative = match[1] === '-'; const unitStrings: (string | undefined)[] = match.slice(2); // Must have at least one unit match if (unitStrings.every(value => value === undefined)) { return null; } const unitNumbers = unitStrings.map((value, i) => { value = value ?? '0'; const isMilliseconds = i === unitStrings.length - 1; return isMilliseconds // Pad the end of the millisecond values. For example, when taking the "6" // portion from the string "PT3.6S", we need to interpret that as "600 // milliseconds". ? Number(value.padEnd(3, '0')) : Number(value); }); const output = { ...ZERO }; unitsOrder.forEach((unit, i) => { output[unit] = unitNumbers[i]; }); // Milliseconds don't have their own minus symbol. It depends on the symbol // before the seconds value. if (isNegativelySigned(output.seconds)) { output.milliseconds *= -1; } return isDurationNegative ? negate(output) : output; }; }; /** * Parse a duration string expressed in one of the following formats: * * - PYYYYMMDDThhmmss * - PYYYY-MM-DDThh:mm:ss */ const parseFullFormatISODuration = createDurationParser( new RegExp([ '^(-)?P', '(\\d{4})', '-?', '(\\d{2})', '-?', '(\\d{2})', 'T', '(\\d{2})', ':?', '(\\d{2})', ':?', '(\\d{2})', millisecondsPattern, '$', ].join('')), [ 'years', 'months', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', ], ); /** * Parse a duration string expressed via number and unit character pairs. For * example: * * - P6D * - P1Y2D * - P2DT6H2,5S */ const parseUnitsISODuration = createDurationParser( new RegExp([ '^(-)?P', unitPattern('Y'), unitPattern('M'), unitPattern('W'), unitPattern('D'), '(?:T', unitPattern('H'), unitPattern('M'), unitPattern(`${millisecondsPattern}S`), ')?$', ].join('')), [ 'years', 'months', 'weeks', 'days', 'hours', 'minutes', 'seconds', 'milliseconds', ], ); /** * Parse an ISO 8601 duration string into an object. * * The units of duration are not normalized. For example, the string `"P365D"` * doesn't get converted to `{ years: 1 }` since not all years are the same * length. * * @example parseISODuration('P365D') // { days: 365 } */ export const parseISODuration = (duration: string): Duration => { const output = ( parseUnitsISODuration(duration) || parseFullFormatISODuration(duration) ); if (output === null) { throw new SyntaxError(`Failed to parse duration. "${duration}" is not a valid ISO duration string.`); } return output; }; |