Skip to content

Commit 2104492

Browse files
committed
fix: Respect timezone for natural language date parsing and align custom date ranges to dates by default to ensure backward compatibility
1 parent e6a738a commit 2104492

File tree

4 files changed

+3214
-41
lines changed

4 files changed

+3214
-41
lines changed

packages/cubejs-api-gateway/dateParser.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
const chrono = require('chrono-node');
2-
const moment = require('moment');
2+
const moment = require('moment-timezone');
33
const UserError = require('./UserError');
44

5-
module.exports = (dateString) => {
5+
module.exports = (dateString, timezone) => {
66
let momentRange;
77
dateString = dateString.toLowerCase();
88
if (dateString.match(/(this|last)\s+(day|week|month|year|quarter|hour|minute|second)/)) {
99
const match = dateString.match(/(this|last)\s+(day|week|month|year|quarter|hour|minute|second)/);
10-
let start = moment();
11-
let end = moment();
10+
let start = moment.tz(timezone);
11+
let end = moment.tz(timezone);
1212
if (match[1] === 'last') {
1313
start = start.add(-1, match[2]);
1414
end = end.add(-1, match[2]);
@@ -19,25 +19,25 @@ module.exports = (dateString) => {
1919
const match = dateString.match(/last\s+(\d+)\s+(day|week|month|year|quarter|hour|minute|second)/);
2020
const span = match[2] === 'week' ? 'isoWeek' : match[2];
2121
momentRange = [
22-
moment().add(-parseInt(match[1], 10) - 1, match[2]).startOf(span),
23-
moment().add(-1, match[2]).endOf(span)
22+
moment.tz(timezone).add(-parseInt(match[1], 10) - 1, match[2]).startOf(span),
23+
moment.tz(timezone).add(-1, match[2]).endOf(span)
2424
];
2525
} else if (dateString.match(/today/)) {
26-
momentRange = [moment().startOf('day'), moment().endOf('day')];
26+
momentRange = [moment.tz(timezone).startOf('day'), moment.tz(timezone).endOf('day')];
2727
} else if (dateString.match(/yesterday/)) {
28-
const yesterday = moment().add(-1, 'day');
28+
const yesterday = moment.tz(timezone).add(-1, 'day');
2929
momentRange = [moment(yesterday).startOf('day'), moment(yesterday).endOf('day')];
3030
} else {
3131
const results = chrono.parse(dateString);
3232
if (!results) {
3333
throw new UserError(`Can't parse date: '${dateString}'`);
3434
}
3535
momentRange = results[0].end ? [
36-
results[0].start.moment(),
37-
results[0].end.moment()
36+
moment(results[0].start.moment()).tz(timezone).startOf('day'),
37+
moment(results[0].end.moment()).tz(timezone).endOf('day')
3838
] : [
39-
results[0].start.moment(),
40-
results[0].start.moment()
39+
moment(results[0].start.moment()).tz(timezone).startOf('day'),
40+
moment(results[0].start.moment()).tz(timezone).endOf('day')
4141
];
4242
}
4343
return momentRange.map(d => d.format(moment.HTML5_FMT.DATETIME_LOCAL_MS));

packages/cubejs-api-gateway/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ const normalizeQuery = (query) => {
206206
timeDimensions: (query.timeDimensions || []).map(td => {
207207
let dateRange;
208208
if (typeof td.dateRange === 'string') {
209-
dateRange = dateParser(td.dateRange);
209+
dateRange = dateParser(td.dateRange, timezone);
210210
} else {
211211
dateRange = td.dateRange && td.dateRange.length === 1 ? [td.dateRange[0], td.dateRange[0]] : td.dateRange;
212212
}

packages/cubejs-api-gateway/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,22 @@
66
"engines": {
77
"node": ">=8.11.1"
88
},
9+
"scripts": {
10+
"test": "jest"
11+
},
912
"main": "index.js",
1013
"dependencies": {
1114
"@hapi/joi": "^14.0.6",
1215
"chrono-node": "^1.3.11",
1316
"jsonwebtoken": "^8.3.0",
1417
"moment": "^2.24.0",
18+
"moment-timezone": "^0.5.27",
1519
"ramda": "^0.25.0"
1620
},
1721
"devDependencies": {
1822
"eslint": "^4.14.0",
1923
"eslint-plugin-node": "^5.2.1",
24+
"jest": "^24.9.0",
2025
"mocha": "^5.2.0",
2126
"should": "^13.2.3"
2227
},

0 commit comments

Comments
 (0)