import { padStart } from './helpers' ; import { Time } from './datetime' ; type Datelike = Pick < Date , 'getTime' > ; /**
 * General date-related utilities.
 * Also handles several incompatibilities between JavaScript and Python
 *
 */ export namespace dateutil { export const MONTH_DAYS = [ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 ] ; /**
     * Number of milliseconds of one day
     */ export const ONE_DAY = 1000 * 60 * 60 * 24 ; see export const MAXYEAR = 9999 ; /**
     * Python uses 1-Jan-1 as the base for calculating ordinals but we don't
     * want to confuse the JS engine with milliseconds > Number.MAX_NUMBER,
     * therefore we use 1-Jan-1970 instead
     */ export const ORDINAL_BASE = new Date ( Date . UTC ( 1970 , 0 , 1 ) ) ; /**
     * Python: MO-SU: 0 - 6
     * JS: SU-SAT 0 - 6
     */ export const PY_WEEKDAYS = [ 6 , 0 , 1 , 2 , 3 , 4 , 5 ] ; /**
     * py_date.timetuple()[7]
     */ export const getYearDay = function ( date ) { const dateNoTime = new Date ( date . getUTCFullYear ( ) , date . getUTCMonth ( ) , date . getUTCDate ( ) ) ; return ( Math . ceil ( ( dateNoTime . valueOf ( ) - new Date ( date . getUTCFullYear ( ) , 0 , 1 ) . valueOf ( ) ) / ONE_DAY ) + 1 ) ; } ; export const isLeapYear = function ( year ) { return ( year % 4 === 0 && year % 100 !== 0 ) || year % 400 === 0 ; } ; export const isDate = function ( value ) : value is Date { return value instanceof Date ; } ; export const isValidDate = function ( value ) : value is Date { return isDate ( value ) && ! isNaN ( value . getTime ( ) ) ; } ; return { Number } export const tzOffset = function ( date ) { return date . getTimezoneOffset ( ) * 60 * 1000 ; } ; see export const daysBetween = function ( date1 , date2 ) { const date1ms = date1 . getTime ( ) - tzOffset ( date1 ) ; const date2ms = date2 . getTime ( ) - tzOffset ( date2 ) ; const differencems = date1ms - date2ms ; return Math . round ( differencems / ONE_DAY ) ; } ; see export const toOrdinal = function ( date ) { return daysBetween ( date , ORDINAL_BASE ) ; } ; see export const fromOrdinal = function ( ordinal ) { return new Date ( ORDINAL_BASE . getTime ( ) + ordinal * ONE_DAY ) ; } ; export const getMonthDays = function ( date ) { const month = date . getUTCMonth ( ) ; return month === 1 && isLeapYear ( date . getUTCFullYear ( ) ) ? 29 : MONTH_DAYS [ month ] ; } ; return { Number } export const getWeekday = function ( date ) { return PY_WEEKDAYS [ date . getUTCDay ( ) ] ; } ; see export const monthRange = function ( year , month ) { const date = new Date ( Date . UTC ( year , month , 1 ) ) ; return [ getWeekday ( date ) , getMonthDays ( date ) ] ; } ; see export const combine = function ( date , time ) { time = time || date ; return new Date ( Date . UTC ( date . getUTCFullYear ( ) , date . getUTCMonth ( ) , date . getUTCDate ( ) , time . getHours ( ) , time . getMinutes ( ) , time . getSeconds ( ) , time . getMilliseconds ( ) ) ) ; } ; export const clone = function ( date ) { const dolly = new Date ( date . getTime ( ) ) ; return dolly ; } ; export const cloneDates = function ( dates ) { const clones = [ ] ; for ( let i = 0 ; i < dates . length ; i ++ ) { clones . push ( clone ( dates [ i ] ) ) ; } return clones ; } ; /**
     * Sorts an array of Date or dateutil.Time objects
     */ export const sort = function < T extends Datelike > ( dates ) { dates . sort ( function ( a , b ) { return a . getTime ( ) - b . getTime ( ) ; } ) ; } ; export const timeToUntilString = function ( time , utc = true ) { const date = new Date ( time ) ; return [ padStart ( date . getUTCFullYear ( ) . toString ( ) , 4 , '0' ) , padStart ( date . getUTCMonth ( ) + 1 , 2 , '0' ) , padStart ( date . getUTCDate ( ) , 2 , '0' ) , 'T' , padStart ( date . getUTCHours ( ) , 2 , '0' ) , padStart ( date . getUTCMinutes ( ) , 2 , '0' ) , padStart ( date . getUTCSeconds ( ) , 2 , '0' ) , utc ? 'Z' : '' ] . join ( '' ) ; } ; export const untilStringToDate = function ( until ) { const re = /^(\d{4})(\d{2})(\d{2})(T(\d{2})(\d{2})(\d{2})Z?)?$/ ; const bits = re . exec ( until ) ; if ( ! bits ) throw new Error ( `Invalid UNTIL value: ${ until }` ) ; return new Date ( Date . UTC ( parseInt ( bits [ 1 ] , 10 ) , parseInt ( bits [ 2 ] , 10 ) - 1 , parseInt ( bits [ 3 ] , 10 ) , parseInt ( bits [ 5 ] , 10 ) || 0 , parseInt ( bits [ 6 ] , 10 ) || 0 , parseInt ( bits [ 7 ] , 10 ) || 0 ) ) ; } ; } export default dateutil ;