Skip to content
This repository has been archived by the owner on Nov 29, 2023. It is now read-only.

Commit

Permalink
Fix/dates 141 (#143)
Browse files Browse the repository at this point in the history
* Fixed date arithmetic returning date instead of number, closes #141
  • Loading branch information
MartijnR authored Jan 18, 2022
1 parent 83aede7 commit 4ad7ad7
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 39 deletions.
36 changes: 11 additions & 25 deletions src/openrosa-extensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { getTimezoneOffsetAsTime } = require('./date-extensions');
const { asGeopoints, area, distance } = require('./geo');
const digest = require('./digest');
const { randomToken } = require('./random-token');
const { DATE_STRING, dateStringToDays, isValidDate } = require('./utils/date');
const { DATE_STRING, dateStringToDays, dateToDays, isValidDate } = require('./utils/date');
const shuffle = require('./utils/shuffle');
const { asBoolean, asNumber, asString } = require('./utils/xpath-cast');
const sortByDocumentOrder = require('./utils/sort-by-document-order');
Expand Down Expand Up @@ -154,7 +154,7 @@ const openrosa_xpath_extensions = function() {
'decimal-date-time': function(r) {
if(arguments.length > 1) throw TOO_MANY_ARGS;

const days = dateStringToDays(asString(r));
const days = r.t === 'num' ? asNumber(r) : dateStringToDays(asString(r));

return XPR.number(days);
},
Expand Down Expand Up @@ -456,27 +456,13 @@ const openrosa_xpath_extensions = function() {
return;
}

// For comparisons, we must make sure that both values are numbers
// Dates would be fine, except for equality!
if(op >= EQ && op <= GTE) {
if(lhs.t === 'arr' || lhs.t === 'str') lhs = XPR.date(asDate(lhs));
if(rhs.t === 'arr' || rhs.t === 'str') rhs = XPR.date(asDate(rhs));
if(lhs.t !== 'date' || rhs.t !== 'date') {
return op === '!=';
} else {
lhs = { t:'num', v:lhs.v.getTime() };
rhs = { t:'num', v:rhs.v.getTime() };
}
} else if(op === PLUS || op === MINUS) {
// for math operators, we need to do it ourselves
if(lhs.t === 'date' && rhs.t === 'date') err('No handling for simple arithmetic with two dates.');
const d = lhs.t === 'date'? lhs.v: rhs.v,
res = new Date(d.getTime());
let n = lhs.t !== 'date'? asInteger(lhs): asInteger(rhs);
if(op === MINUS) n = -n;
res.setDate(d.getDate() + n);
return res;
}
// For comparisons and math, we must make sure that both values are numbers
if(lhs.t === 'arr' || lhs.t === 'str') lhs = XPR.date(asDate(lhs));
if(rhs.t === 'arr' || rhs.t === 'str') rhs = XPR.date(asDate(rhs));

if (lhs.t === 'date') lhs = { t:'num', v:dateToDays(lhs.v) };
if (rhs.t === 'date') rhs = { t:'num', v:dateToDays(rhs.v) };

return { t:'continue', lhs:lhs, op:op, rhs:rhs };
}

Expand All @@ -489,7 +475,7 @@ const openrosa_xpath_extensions = function() {
const delta = op === PLUS ? lDays + rDays : lDays - rDays;
const date = new Date(1970, 0, 1);
date.setDate(date.getDate() + delta);
return date;
return dateToDays(date);
}

const rStr = asString(rhs);
Expand All @@ -499,7 +485,7 @@ const openrosa_xpath_extensions = function() {
const delta = op === PLUS ? lDays + rDays : lDays - rDays;
const date = new Date(1970, 0, 1);
date.setDate(date.getDate() + delta);
return date;
return dateToDays(date);
}
} else if(op >= EQ && op <= GTE) {
const lStr = asString(lhs);
Expand Down
22 changes: 15 additions & 7 deletions test/integration/openrosa-xpath/date.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ describe('#date()', () => {
it('example 3', () => {
assertStringValue('date("2018-01-01" + 1)', '2018-01-02');
});
it('example 4', () => {
assertStringValue('"2021-11-30" + 1', '18962.291666666668'); // correctness of decimals tbd later
});
it('example 5', () => {
assertStringValue('"2021-11-30" - "2021-11-29"', '1.2916666666666667');
});

[
'today()',
Expand Down Expand Up @@ -138,7 +144,9 @@ describe('#date()', () => {
['date("2012-01-01") < today()', true],
['date("2012-01-01") > today()', false],
['date("2100-01-02") > today()', true],
['date("2100-01-02") < today()', false]
['date("2100-01-02") < today()', false],
['date("2100-01-02") > 1', true],
['date("1970-01-02") < 3', true]
].forEach(([expr, expected]) => {
it('should evaluate \'' + expr + '\' to: ' + expected, () => {
assertBoolean(expr, expected);
Expand All @@ -148,12 +156,12 @@ describe('#date()', () => {

describe('math', () => {
[
['date("2001-12-26") + 5', '2001-12-31'],
['date("2001-12-26") - 5', '2001-12-21'],
['5 + date("2001-12-26")', '2001-12-31'],
['-5 + date("2001-12-26")', '2001-12-21'],
['3 + date("2001-12-26") + 5', '2002-01-03'],
['3 + date("2001-12-26") - 5', '2001-12-24']
['date("2001-12-26") + 5', '11687.291666666666'],
['date("2001-12-26") - 5', '11677.291666666666'],
['5 + date("2001-12-26")', '11687.291666666666'],
['-5 + date("2001-12-26")', '11677.291666666666'],
['3 + date("2001-12-26") + 5', '11690.291666666666'],
['3 + date("2001-12-26") - 5', '11680.291666666666']
].forEach(([expr, expected]) => {
it('should evaluate \'' + expr + '\' to: ' + expected, () => {
assertString(expr, expected);
Expand Down
14 changes: 7 additions & 7 deletions test/unit/openrosa-extensions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ describe('openrosa-extensions', () => {

[
// addition
[ 1, '+', new Date(1970, 0, 1), new Date(1970, 0, 2) ],
[ 1, '+', '1970-1-1', new Date(1970, 0, 2) ],
[ 1, '+', [ '1970-1-1' ], new Date(1970, 0, 2) ],
[ 10, '+', new Date(2012, 6, 24), new Date(2012, 7, 3) ],
[ new Date(1970, 0, 1), '+', 1, new Date(1970, 0, 2) ],
[ '1970-1-1', '+', 1, new Date(1970, 0, 2) ],
[ [ '1970-1-1' ], '+', 1, new Date(1970, 0, 2) ],
[ 1, '+', new Date(1970, 0, 1), { t:'continue', lhs:wrapVal(1), op:opVals.PLUS, rhs:wrapVal(0.2916666666666667) } ], // correctness of decimals tbd later
[ 1, '+', '1970-1-1', 1.2916666666666667 ], // correctness of decimals tbd later
[ 1, '+', [ '1970-1-1' ], 1.2916666666666667 ], // correctness of decimals tbd later
[ 10, '+', new Date(2012, 6, 24), { t:'continue', lhs:wrapVal(10), op:opVals.PLUS, rhs:wrapVal(15545.2916666666666667) } ], // correctness of decimals tbd later
[ new Date(1970, 0, 1), '+', 1, { t:'continue', lhs:wrapVal(0.2916666666666667), op:opVals.PLUS, rhs:wrapVal(1) } ], // correctness of decimals tbd later
[ '1970-1-1', '+', 1, 1.2916666666666667 ], // correctness of decimals tbd later
[ [ '1970-1-1' ], '+', 1, 1.2916666666666667 ], // correctness of decimals tbd later

// inequality
[ true, '!=', new Date(), undefined ],
Expand Down

0 comments on commit 4ad7ad7

Please sign in to comment.