@@ -123,53 +123,6 @@ export function addInterval(date: dayjs.Dayjs, interval: ParsedInterval): dayjs.
123123 return res ;
124124}
125125
126- export const dayRange = ( from : any , to : any , annotations ?: Record < string , { granularity ?: Granularity } > ) : DayRange => ( {
127- by : ( value : any ) => {
128- const results = [ ] ;
129-
130- let start = internalDayjs ( from ) ;
131- const end = internalDayjs ( to ) ;
132-
133- while ( start . startOf ( value ) . isBefore ( end ) || start . isSame ( end ) ) {
134- results . push ( start ) ;
135- start = start . add ( 1 , value ) ;
136- }
137-
138- return results ;
139- } ,
140- snapTo : ( value : any ) : DayRange => {
141- // Check if this is a custom granularity
142- if ( ! isPredefinedGranularity ( value ) && annotations ) {
143- // Try to find the custom granularity metadata
144- // The annotation key might be in format "Cube.dimension.granularity"
145- // So we need to search through all annotations
146- let customGranularity : Granularity | undefined ;
147-
148- for ( const key of Object . keys ( annotations ) ) {
149- if ( key . endsWith ( `.${ value } ` ) && annotations [ key ] . granularity ) {
150- customGranularity = annotations [ key ] . granularity ;
151- break ;
152- }
153- }
154-
155- if ( customGranularity && customGranularity . interval ) {
156- // For custom granularities, calculate the range for the bucket
157- const intervalParsed = parseSqlInterval ( customGranularity . interval ) ;
158- const intervalStart = internalDayjs ( from ) ;
159- // End is start + interval - 1 millisecond (to stay within the bucket)
160- const intervalEnd = addInterval ( intervalStart , intervalParsed ) . subtract ( 1 , 'millisecond' ) ;
161-
162- return dayRange ( intervalStart , intervalEnd , annotations ) ;
163- }
164- }
165-
166- // Default behavior for predefined granularities
167- return dayRange ( internalDayjs ( from ) . startOf ( value ) , internalDayjs ( to ) . endOf ( value ) , annotations ) ;
168- } ,
169- start : internalDayjs ( from ) ,
170- end : internalDayjs ( to ) ,
171- } ) ;
172-
173126/**
174127 * Adds interval to provided date.
175128 * TODO: It's copy/paste of subtractInterval from @cubejs-backend/shared [time.ts]
@@ -230,6 +183,65 @@ function alignToOrigin(startDate: dayjs.Dayjs, interval: ParsedInterval, origin:
230183 return alignedDate ;
231184}
232185
186+ export const dayRange = ( from : any , to : any , annotations ?: Record < string , { granularity ?: Granularity } > ) : DayRange => ( {
187+ by : ( value : any ) => {
188+ const results = [ ] ;
189+
190+ let start = internalDayjs ( from ) ;
191+ const end = internalDayjs ( to ) ;
192+
193+ while ( start . startOf ( value ) . isBefore ( end ) || start . isSame ( end ) ) {
194+ results . push ( start ) ;
195+ start = start . add ( 1 , value ) ;
196+ }
197+
198+ return results ;
199+ } ,
200+ snapTo : ( value : any ) : DayRange => {
201+ // Check if this is a custom granularity
202+ if ( ! isPredefinedGranularity ( value ) && annotations ) {
203+ // Try to find the custom granularity metadata
204+ // The annotation key might be in format "Cube.dimension.granularity"
205+ // So we need to search through all annotations
206+ let customGranularity : Granularity | undefined ;
207+
208+ for ( const key of Object . keys ( annotations ) ) {
209+ if ( key . endsWith ( `.${ value } ` ) && annotations [ key ] . granularity ) {
210+ customGranularity = annotations [ key ] . granularity ;
211+ break ;
212+ }
213+ }
214+
215+ if ( customGranularity ?. interval ) {
216+ // For custom granularities, calculate the range for the bucket
217+ const intervalParsed = parseSqlInterval ( customGranularity . interval ) ;
218+ let intervalStart = internalDayjs ( from ) ;
219+
220+ // If custom granularity has an origin, align to it
221+ if ( customGranularity . origin ) {
222+ let origin = internalDayjs ( customGranularity . origin ) ;
223+ if ( customGranularity . offset ) {
224+ origin = addInterval ( origin , parseSqlInterval ( customGranularity . offset ) ) ;
225+ }
226+
227+ // Align the value to the origin to find the actual bucket start
228+ intervalStart = alignToOrigin ( intervalStart , intervalParsed , origin ) ;
229+ }
230+
231+ // End is start + interval - 1 millisecond (to stay within the bucket)
232+ const intervalEnd = addInterval ( intervalStart , intervalParsed ) . subtract ( 1 , 'millisecond' ) ;
233+
234+ return dayRange ( intervalStart , intervalEnd , annotations ) ;
235+ }
236+ }
237+
238+ // Default behavior for predefined granularities
239+ return dayRange ( internalDayjs ( from ) . startOf ( value ) , internalDayjs ( to ) . endOf ( value ) , annotations ) ;
240+ } ,
241+ start : internalDayjs ( from ) ,
242+ end : internalDayjs ( to ) ,
243+ } ) ;
244+
233245/**
234246 * Returns the time series points for the custom interval
235247 * TODO: It's almost a copy/paste of timeSeriesFromCustomInterval from
0 commit comments