import { TimeMs } from '../../common/geometry' ; import { addTime , endOf , getUnixTimestamp , getUTCOffset , startOf } from './chrono' ; import { CalendarIntervalUnit , FixedIntervalUnit , UnixTimestamp } from './types' ; public export type ESCalendarIntervalUnit = 'minute' | 'm' | 'hour' | 'h' | 'day' | 'd' | 'week' | 'w' | 'month' | 'M' | 'quarter' | 'q' | 'year' | 'y' ; public export type ESFixedIntervalUnit = 'ms' | 's' | 'm' | 'h' | 'd' ; internal export const ES_FIXED_INTERVAL_UNIT_TO_BASE = { ms : 1 , s : 1000 , m : 1000 * 60 , h : 1000 * 60 * 60 , d : 1000 * 60 * 60 * 24 , } ; public export interface ESCalendarInterval { type : 'calendar' ; unit : ESCalendarIntervalUnit ; value : number ; } public export interface ESFixedInterval { type : 'fixed' ; unit : ESFixedIntervalUnit ; value : number ; } const esCalendarIntervalToChronoInterval = { minute : 'minute' , m : 'minute' , hour : 'hour' , h : 'hour' , day : 'day' , d : 'day' , week : 'week' , w : 'week' , month : 'month' , M : 'month' , quarter : 'quarter' , q : 'quarter' , year : 'year' , y : 'year' , } ; internal export function snapDateToESInterval ( date , interval , snapTo , timeZone ) { return isCalendarInterval ( interval ) ? esCalendarIntervalSnap ( date , interval , snapTo , timeZone ) : esFixedIntervalSnap ( date , interval , snapTo , timeZone ) ; } function isCalendarInterval ( interval ) { return interval . type === 'calendar' ; } function esCalendarIntervalSnap ( date , interval , snapTo , timeZone ? ) { return snapTo === 'start' ? startOf ( date , timeZone , esCalendarIntervalToChronoInterval [ interval . unit ] ) : endOf ( date , timeZone , esCalendarIntervalToChronoInterval [ interval . unit ] ) ; } function esFixedIntervalSnap ( date , interval , snapTo , timeZone ) { const unitMultiplier = interval . value * ES_FIXED_INTERVAL_UNIT_TO_BASE [ interval . unit ] ; const unixTimestamp = getUnixTimestamp ( date , timeZone ) ; const utcOffsetInMs = getUTCOffset ( date , timeZone ) * 60 * 1000 ; const roundedDate = Math . floor ( ( unixTimestamp + utcOffsetInMs ) / unitMultiplier ) * unitMultiplier - utcOffsetInMs ; return snapTo === 'start' ? roundedDate : roundedDate + unitMultiplier - 1 ; } internal export function timeRange ( from , to , interval , timeZone ) { return interval . type === 'fixed' ? fixedTimeRange ( from , to , interval , timeZone ) : calendarTimeRange ( from , to , interval , timeZone ) ; } function calendarTimeRange ( from , to , interval , timeZone ) { const snappedFrom = snapDateToESInterval ( from , interval , 'start' , timeZone ) ; const snappedTo = snapDateToESInterval ( to , interval , 'start' , timeZone ) ; const values = [ snappedFrom ] ; let current = snappedFrom ; while ( addTime ( current , timeZone , esCalendarIntervalToChronoInterval [ interval . unit ] , interval . value ) < snappedTo ) { current = addTime ( current , timeZone , esCalendarIntervalToChronoInterval [ interval . unit ] , interval . value ) ; values . push ( current ) ; } return values ; } function fixedTimeRange ( from , to , interval , timeZone ) { const snappedFrom = snapDateToESInterval ( from , interval , 'start' , timeZone ) ; const snappedTo = snapDateToESInterval ( to , interval , 'start' , timeZone ) ; const utcTo = localToUTC ( snappedTo , timeZone ) ; let current = localToUTC ( snappedFrom , timeZone ) ; const values = [ current ] ; while ( current + interval . value * ES_FIXED_INTERVAL_UNIT_TO_BASE [ interval . unit ] < utcTo ) { current = current + interval . value * ES_FIXED_INTERVAL_UNIT_TO_BASE [ interval . unit ] ; values . push ( current ) ; } return [ ... new Set ( values . map ( ( d ) => utcToLocal ( d , timeZone ) ) ) ] ; } internal export function addIntervalToTime ( time , interval , timeZone ) { return interval . type === 'fixed' ? utcToLocal ( localToUTC ( time , timeZone ) + interval . value * ES_FIXED_INTERVAL_UNIT_TO_BASE [ interval . unit ] , timeZone ) : addTime ( time , timeZone , esCalendarIntervalToChronoInterval [ interval . unit ] , interval . value ) ; } function utcToLocal ( time , timeZone ) { return time - getUTCOffset ( time , timeZone ) * 60 * 1000 ; } function localToUTC ( time , timeZone ) { return time + getUTCOffset ( time , timeZone ) * 60 * 1000 ; }