import { DateParts , DatePartName , FormatOptions , Parser , Token } from './types' ; const parsers = new Map ( ) ; const intlFormattersOptions = [ { weekday : 'long' , year : 'numeric' , month : '2-digit' , day : '2-digit' , hour : '2-digit' , minute : '2-digit' , second : '2-digit' } , { month : 'long' , hour : '2-digit' , hour12 : false } ] ; const createIntlFormatterWith = ( options ) : Intl . DateTimeFormat [ ] => intlFormattersOptions . map ( intlFormatterOptions => new Intl . DateTimeFormat ( options . locale , { ... intlFormatterOptions , timeZone : options . timezone } ) ) ; const longTokensTransformer = ( token ) : Token => ( token . type !== 'literal' ? { type : `l${ token . type }` , value : token . value } : token ) as Token ; const datePartsReducer = ( parts , token ) : DateParts => { parts [ token . type as DatePartName ] = token . value ; return parts ; } ; const tokenize = ( intlFormatter , date ) : Token [ ] => intlFormatter . formatToParts ( date ) . filter ( token => token . type !== 'literal' ) as Token [ ] ; const normalize = ( parts ) : DateParts => { parts . dayPeriod = parts . dayPeriod || ( parts as any ) . dayperiod || '' ; delete ( parts as any ) . dayperiod ; parts . lhour = ( '0' + ( Number ( parts . lhour ) % 24 ) ) . slice ( - 2 ) ; return parts ; } ; const createParser = ( options ) : Parser => { const [ intlFormatter , intlFormatterLong ] = createIntlFormatterWith ( options ) ; return function parseDateImpl ( date ) : DateParts { const tokens = tokenize ( intlFormatter , date ) ; const longTokens = tokenize ( intlFormatterLong , date ) . map ( longTokensTransformer ) ; const allTokens = [ ... tokens , ... longTokens ] ; const parts = allTokens . reduce ( datePartsReducer , { } as DateParts ) ; return normalize ( parts ) ; } ; } ; export default function parseDate ( date , options = { } ) { const key = `${ options . locale }${ options . timezone }` ; let parser = parsers . get ( key ) ; if ( ! parser ) { parser = createParser ( options ) ; parsers . set ( key , parser ) ; } return parser ( date ) ; }