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 ) => `(?:(-?\\d+)${ unit })?` ; const createDurationParser = ( regex , unitsOrder ) => { return ( duration ) : Duration | null => { const match = duration . match ( regex ) ; if ( ! match ) { return null ; } const isDurationNegative = match [ 1 ] === '-' ; const unitStrings = match . slice ( 2 ) ; if ( unitStrings . every ( value => value === undefined ) ) { return null ; } const unitNumbers = unitStrings . map ( ( value = '0' , i ) => { const isMilliseconds = i === unitStrings . length - 1 ; return isMilliseconds ? Number ( value . padEnd ( 3 , '0' ) ) : Number ( value ) ; } ) ; const output = { ... ZERO } ; unitsOrder . forEach ( ( unit , i ) => { output [ unit ] = unitNumbers [ i ] ; } ) ; 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' , ] ) ; example export const parseISODuration = ( duration ) : 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 ; } ;