Skip to content
This repository has been archived by the owner on Mar 2, 2022. It is now read-only.

Commit

Permalink
Added relative date handling
Browse files Browse the repository at this point in the history
closes: https://github.com/NexesJS/NQL-Lang/issues/9

This adds relative date expressions in the form now-1d.
These are translated into absolute dates inside the NQL parser
The output format then contains a standard gt/lt type date expression

This is because mongo queries don't support relative dates without using $expr and knex doesn't support them at all.
We'd have to change a lot of stuff to support relative queries to the DB / to JSON but this solves the immediate problem simply.

This has meant introducing state into the lexer, which is new to me. This done so that we can correctly interpret the -/+ symbols
in two different "states". This could be used to improve the lexer further.

This is quite a complex addition to the language, but it reduces complexity everywhere else.
  • Loading branch information
ErisDS committed Feb 28, 2022
1 parent e884c20 commit 976d2a0
Show file tree
Hide file tree
Showing 8 changed files with 488 additions and 27 deletions.
71 changes: 46 additions & 25 deletions dist/parser.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions lib/scope.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
const util = require('util');
const ops = {
add: require('date-fns/add'),
sub: require('date-fns/sub')
};
const format = require('date-fns/formatRFC3339');

const intervals = {
d: 'days',
w: 'weeks',
M: 'months',
y: 'years',
h: 'hours',
m: 'minutes',
s: 'seconds'
};

module.exports = {
ungroup(value) {
Expand All @@ -10,6 +25,13 @@ module.exports = {
return value.replace(re, '$1');
},

relDateToAbsolute(op, amount, duration) {
const now = new Date();
const finalDate = ops[op](now, {[intervals[duration]]: amount});

return format(finalDate);
},

debug() {
if (!process.env.DEBUG || !/nql/.test(process.env.DEBUG)) {
return;
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@
"ship": "STATUS=$(git status --porcelain); echo $STATUS; if [ -z \"$STATUS\" ]; then yarn publish && git push --follow-tags; fi"
},
"devDependencies": {
"date-fns": "2.28.0",
"eslint": "4.19.1",
"eslint-plugin-ghost": "0.0.25",
"jison": "0.4.18",
"mocha": "5.2.0",
"should": "13.2.1"
"should": "13.2.1",
"sinon": "13.0.1"
},
"dependencies": {}
}
12 changes: 12 additions & 0 deletions src/nql.l
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
omitops [^\s'"\+\,\(\)\>\<=\[\]\-]
omitopsbarnot [^\s'"\+\,\(\)\>\<=\[\]]
escapable ['"\+\,\(\)\>\<=\[\]]
final [\+\,\(\)\[\]]

%s reldate

%%

Expand All @@ -17,6 +19,16 @@ escapable ['"\+\,\(\)\>\<=\[\]]
[0-9]+(\.[0-9]+)?\b(?![\-]) return 'NUMBER';
'[' return 'LBRACKET';
']' return 'RBRACKET';

/* relative date handling */
now(?=[-+]\d+[dwMyhms](?:{final}|$)) { this.pushState('reldate');
return 'NOW'; }
<reldate>'-' return 'SUB';
<reldate>'+' return 'ADD';
<reldate>\d+ return 'AMOUNT'
<reldate>[dwMyhms] { this.popState();
return 'INTERVAL' }

{omitops}(\\{escapable}|{omitopsbarnot})+ return 'LITERAL';
['](\\['"]|[^'"])+?['] return 'STRING';
'(' return 'LPAREN';
Expand Down
6 changes: 6 additions & 0 deletions src/nql.y
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,16 @@ VALUE
| TRUE { $$ = true }
| FALSE { $$ = false }
| NUMBER { $$ = parseInt(yytext); }
| NOW DATEOP AMOUNT INTERVAL { $$ = yy.relDateToAbsolute($2, $3, $4) }
| LITERAL { $$ = yy.unescape($1); }
| STRING { $1 = $1.replace(/^'|'$/g, ''); $$ = yy.unescape($1); }
;

DATEOP
: ADD { $$ = "add"; }
| SUB { $$ = "sub"; }
;

OP
: NOT { $$ = "$ne"; }
| GT { $$ = "$gt"; }
Expand Down
Loading

0 comments on commit 976d2a0

Please sign in to comment.