import dayjs from "dayjs" ; export interface DSTInfo { startDate : Date ; endDate : Date ; standardOffset : number ; dstOffset : number ; } param defaultOffset export function getDefaultDSTInfo ( defaultOffset ? ) { const thisYear = new Date ( ) . getUTCFullYear ( ) ; if ( defaultOffset == undefined ) defaultOffset = - new Date ( ) . getTimezoneOffset ( ) ; return { startDate : new Date ( Date . UTC ( thisYear , 2 , 31 , 1 ) ) , endDate : new Date ( Date . UTC ( thisYear , 9 , 31 , 1 ) ) , standardOffset : defaultOffset , dstOffset : defaultOffset } ; } /**
 * Finds the first date on which the given timezone offset is in effect.
 * date1 must be the smaller one of the two dates
 */ function findSwitchDate ( date1 , date2 , offset ) { const stepSize = 60000 ; function middleDate ( date1 , date2 ) { const middleTime = Math . floor ( ( date1 . getTime ( ) + date2 . getTime ( ) ) / 2 / stepSize ) * stepSize ; return new Date ( middleTime ) ; } while ( date1 < date2 ) { const mid = middleDate ( date1 , date2 ) ; if ( mid . getTimezoneOffset ( ) === offset ) { date2 = mid ; } else { date1 = new Date ( mid . getTime ( ) + stepSize ) ; } } if ( date1 . getTimezoneOffset ( ) !== offset ) return undefined ; return date1 ; } /** Returns the current system's daylight savings time information if possible */ export function getDSTInfo ( now = new Date ( ) ) { const halfAYearAgo = dayjs ( now ) . subtract ( 6 , "months" ) . toDate ( ) ; const inAHalfYear = dayjs ( now ) . add ( 6 , "months" ) . toDate ( ) ; if ( now . getTimezoneOffset ( ) === halfAYearAgo . getTimezoneOffset ( ) || now . getTimezoneOffset ( ) === inAHalfYear . getTimezoneOffset ( ) ) { return getDefaultDSTInfo ( ) ; } const offsets = [ - now . getTimezoneOffset ( ) , - inAHalfYear . getTimezoneOffset ( ) , ] ; const dates = [ findSwitchDate ( halfAYearAgo , now , - offsets [ 0 ] ) , findSwitchDate ( now , inAHalfYear , - offsets [ 1 ] ) , ] ; if ( dates [ 0 ] == undefined || dates [ 1 ] == undefined ) { return getDefaultDSTInfo ( ) ; } if ( offsets [ 0 ] > offsets [ 1 ] ) { return { startDate : dates [ 0 ] , endDate : dates [ 1 ] , dstOffset : offsets [ 0 ] , standardOffset : offsets [ 1 ] } ; } else { return { startDate : dates [ 1 ] , endDate : dates [ 0 ] , dstOffset : offsets [ 1 ] , standardOffset : offsets [ 0 ] } ; } } /** Returns a timestamp with nano-second precision */ export function highResTimestamp ( ) { const [ s , ns ] = process . hrtime ( ) ; return s * 1e9 + ns ; } export const timespan = Object . freeze ( { seconds : ( num ) => num * 1000 , minutes : ( num ) => timespan . seconds ( num * 60 ) , hours : ( num ) => timespan . minutes ( num * 60 ) , days : ( num ) => timespan . hours ( num * 24 ) } ) ; export function formatDate ( date , format ) { return dayjs ( date ) . format ( format ) ; }