Skip to content

Commit 8f1fa77

Browse files
committed
make loadBuildRange() timezone-aware
1 parent 90f6f27 commit 8f1fa77

File tree

2 files changed

+27
-10
lines changed

2 files changed

+27
-10
lines changed

packages/cubejs-backend-shared/src/time.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,13 @@ export const inDbTimeZone = (timezone: string, timestampFormat: string, timestam
227227
return moment.tz(timestamp, timezone).utc().format(timestampFormat);
228228
};
229229

230-
export const utcToLocalTimeZone = (timezone: string, timestampFormat: string, timestamp: string): string => {
230+
/**
231+
* Takes timestamp in UTC, treat it as local time in provided timezone and returns the corresponding timestamp in UTC
232+
*/
233+
export const utcToLocalTimeZoneInUtc = (timezone: string, timestampFormat: string, timestamp: string): string | null => {
234+
if (!timestamp) {
235+
return null;
236+
}
231237
if (timestamp.length === 23) {
232238
const zone = moment.tz.zone(timezone);
233239
if (!zone) {

packages/cubejs-query-orchestrator/src/orchestrator/PreAggregationPartitionRangeLoader.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
TO_PARTITION_RANGE,
77
MAX_SOURCE_ROW_LIMIT,
88
reformatInIsoLocal,
9-
utcToLocalTimeZone,
9+
utcToLocalTimeZoneInUtc,
1010
timeSeries,
1111
inDbTimeZone,
1212
extractDate
@@ -136,9 +136,9 @@ export class PreAggregationPartitionRangeLoader {
136136
return queryValues?.map(
137137
param => {
138138
if (param === BUILD_RANGE_START_LOCAL) {
139-
return utcToLocalTimeZone(this.preAggregation.timezone, this.preAggregation.timestampFormat, buildRangeStart);
139+
return utcToLocalTimeZoneInUtc(this.preAggregation.timezone, this.preAggregation.timestampFormat, buildRangeStart);
140140
} else if (param === BUILD_RANGE_END_LOCAL) {
141-
return utcToLocalTimeZone(this.preAggregation.timezone, this.preAggregation.timestampFormat, buildRangeEnd);
141+
return utcToLocalTimeZoneInUtc(this.preAggregation.timezone, this.preAggregation.timestampFormat, buildRangeEnd);
142142
} else {
143143
return param;
144144
}
@@ -396,31 +396,42 @@ export class PreAggregationPartitionRangeLoader {
396396
const { preAggregationStartEndQueries } = this.preAggregation;
397397
const [startDate, endDate] = await Promise.all(
398398
preAggregationStartEndQueries.map(
399-
async rangeQuery => PreAggregationPartitionRangeLoader.extractDate(await this.loadRangeQuery(rangeQuery)),
399+
async rangeQuery => utcToLocalTimeZoneInUtc(
400+
this.preAggregation.timezone,
401+
'YYYY-MM-DDTHH:mm:ss.SSS',
402+
PreAggregationPartitionRangeLoader.extractDate(await this.loadRangeQuery(rangeQuery)),
403+
)
400404
),
401405
);
406+
402407
if (!this.preAggregation.partitionGranularity) {
403408
return this.orNowIfEmpty([startDate, endDate]);
404409
}
410+
411+
// startDate & endDate are `localized` here
405412
const wholeSeriesRanges = PreAggregationPartitionRangeLoader.timeSeries(
406413
this.preAggregation.partitionGranularity,
407414
this.orNowIfEmpty([startDate, endDate]),
408415
this.preAggregation.timestampPrecision,
409416
);
410417
const [rangeStart, rangeEnd] = await Promise.all(
411418
preAggregationStartEndQueries.map(
412-
async (rangeQuery, i) => PreAggregationPartitionRangeLoader.extractDate(
413-
await this.loadRangeQuery(
414-
rangeQuery, i === 0 ? wholeSeriesRanges[0] : wholeSeriesRanges[wholeSeriesRanges.length - 1],
419+
async (rangeQuery, i) => utcToLocalTimeZoneInUtc(
420+
this.preAggregation.timezone,
421+
'YYYY-MM-DDTHH:mm:ss.SSS',
422+
PreAggregationPartitionRangeLoader.extractDate(
423+
await this.loadRangeQuery(
424+
rangeQuery, i === 0 ? wholeSeriesRanges[0] : wholeSeriesRanges[wholeSeriesRanges.length - 1],
425+
),
415426
),
416-
),
427+
)
417428
),
418429
);
419430
return this.orNowIfEmpty([rangeStart, rangeEnd]);
420431
}
421432

422433
private now() {
423-
return utcToLocalTimeZone(this.preAggregation.timezone, 'YYYY-MM-DDTHH:mm:ss.SSS', new Date().toJSON().substring(0, 23));
434+
return utcToLocalTimeZoneInUtc(this.preAggregation.timezone, 'YYYY-MM-DDTHH:mm:ss.SSS', new Date().toJSON().substring(0, 23));
424435
}
425436

426437
private orNowIfEmpty(dateRange: QueryDateRange): QueryDateRange {

0 commit comments

Comments
 (0)