From ebb7fc03fa984e23f57a64f951a4b4440908de59 Mon Sep 17 00:00:00 2001 From: Rajesh Sharma Date: Mon, 30 Oct 2017 21:39:23 +0545 Subject: [PATCH] adding date expressions by 3,6,12 months, closes #38 --- README.md | 8 ++++ src/ExprCompiler.coffee | 78 +++++++++++++++++++++++++++++++++++ src/ExprEvaluator.coffee | 18 ++++++++ src/ExprUtils.coffee | 3 ++ test/ExprCompilerTests.coffee | 51 +++++++++++++++++++++++ test/testExprs.coffee | 12 ++++++ 6 files changed, 170 insertions(+) diff --git a/README.md b/README.md index bb2fbfd..1c290cc 100644 --- a/README.md +++ b/README.md @@ -5,3 +5,11 @@ Defines a language for expressions that return a value for a single row of a tab Complex expressions involving joins, arithmetic or case statements can be created visually and then compiled to SQL or interpreted. See the [docs](docs/Expressions.md) for more information. + +### To add a new expression +1. Add tests in `ExprCompilerTests` +2. Add tests in `testExprs` +3. Add the expression in `ExprUtils` +4. Update `ExprCompiler` +5. Update `ExprEvaluator` +6. Make tests pass diff --git a/src/ExprCompiler.coffee b/src/ExprCompiler.coffee index 55c155c..5c24315 100644 --- a/src/ExprCompiler.coffee +++ b/src/ExprCompiler.coffee @@ -1200,6 +1200,84 @@ module.exports = class ExprCompiler else return null + when 'last12months' + if not compiledExprs[0] + return null + + switch expr0Type + when "date" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(11, "months").startOf('month').format("YYYY-MM-DD") ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().add(1, 'days').format("YYYY-MM-DD") ] } + ] + } + when "datetime" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(11, "months").startOf('month').toISOString() ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().startOf("day").add(1, 'days').toISOString() ] } + ] + } + else + return null + + when 'last6months' + if not compiledExprs[0] + return null + + switch expr0Type + when "date" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(5, "months").startOf('month').format("YYYY-MM-DD") ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().add(1, 'days').format("YYYY-MM-DD") ] } + ] + } + when "datetime" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(5, "months").startOf('month').toISOString() ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().startOf("day").add(1, 'days').toISOString() ] } + ] + } + else + return null + + when 'last3months' + if not compiledExprs[0] + return null + + switch expr0Type + when "date" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(2, "months").startOf('month').format("YYYY-MM-DD") ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().add(1, 'days').format("YYYY-MM-DD") ] } + ] + } + when "datetime" + return { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [compiledExprs[0], moment().subtract(2, "months").startOf('month').toISOString() ] } + { type: "op", op: "<", exprs: [compiledExprs[0], moment().startOf("day").add(1, 'days').toISOString() ] } + ] + } + else + return null + when 'distance' if not compiledExprs[0] or not compiledExprs[1] return null diff --git a/src/ExprEvaluator.coffee b/src/ExprEvaluator.coffee index 1d41a98..4e8eaa7 100644 --- a/src/ExprEvaluator.coffee +++ b/src/ExprEvaluator.coffee @@ -270,6 +270,24 @@ module.exports = class ExprEvaluator date = values[0] return moment(date, moment.ISO_8601).isBefore(moment().add(1, "days")) and moment(date, moment.ISO_8601).isAfter(moment().subtract(365, "days")) + when "last12months" + if hasNull + return null + date = values[0] + return moment(date, moment.ISO_8601).isBefore(moment().add(1, "days")) and moment(date, moment.ISO_8601).isAfter(moment().subtract(11, "months").startOf('month')) + + when "last6months" + if hasNull + return null + date = values[0] + return moment(date, moment.ISO_8601).isBefore(moment().add(1, "days")) and moment(date, moment.ISO_8601).isAfter(moment().subtract(5, "months").startOf('month')) + + when "last3months" + if hasNull + return null + date = values[0] + return moment(date, moment.ISO_8601).isBefore(moment().add(1, "days")) and moment(date, moment.ISO_8601).isAfter(moment().subtract(2, "months").startOf('month')) + when "latitude" if hasNull return null diff --git a/src/ExprUtils.coffee b/src/ExprUtils.coffee index c908b8e..248b91c 100644 --- a/src/ExprUtils.coffee +++ b/src/ExprUtils.coffee @@ -662,6 +662,9 @@ relativeDateOps = [ ['last7days', 'is in last 7 days'] ['last30days', 'is in last 30 days'] ['last365days', 'is in last 365 days'] + ['last3months', 'is in last 3 months'] + ['last6months', 'is in last 6 months'] + ['last12months', 'is in last 12 months'] ] for relativeDateOp in relativeDateOps addOpItem(op: relativeDateOp[0], name: relativeDateOp[1], resultType: "boolean", exprTypes: ['date']) diff --git a/test/ExprCompilerTests.coffee b/test/ExprCompilerTests.coffee index ef264b2..f76cbcd 100644 --- a/test/ExprCompilerTests.coffee +++ b/test/ExprCompilerTests.coffee @@ -1959,6 +1959,57 @@ describe "ExprCompiler", -> } ) + it "last3months", -> + @compile( + { + type: "op" + op: "last3months" + exprs: [@datetime1] + } + { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [@datetime1JsonQL, moment().subtract(2, "months").startOf('month').toISOString()]} + { type: "op", op: "<", exprs: [@datetime1JsonQL, moment().startOf("day").add(1, "days").toISOString()]} + ] + } + ) + + it "last6months", -> + @compile( + { + type: "op" + op: "last6months" + exprs: [@datetime1] + } + { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [@datetime1JsonQL, moment().subtract(5, "months").startOf('month').toISOString()]} + { type: "op", op: "<", exprs: [@datetime1JsonQL, moment().startOf("day").add(1, "days").toISOString()]} + ] + } + ) + + it "last12months", -> + @compile( + { + type: "op" + op: "last12months" + exprs: [@datetime1] + } + { + type: "op" + op: "and" + exprs: [ + { type: "op", op: ">=", exprs: [@datetime1JsonQL, moment().subtract(11, "months").startOf('month').toISOString()]} + { type: "op", op: "<", exprs: [@datetime1JsonQL, moment().startOf("day").add(1, "days").toISOString()]} + ] + } + ) + it "compiles days since (datetime)", -> @compile( { diff --git a/test/testExprs.coffee b/test/testExprs.coffee index 797f979..59d9b2f 100644 --- a/test/testExprs.coffee +++ b/test/testExprs.coffee @@ -199,6 +199,18 @@ addOp(true, "last30days", literal(moment().subtract(1, "minutes").subtract(1, "d addOp(false, "last365days", literal(moment().subtract(1, "minutes").add(3, "days").toISOString(), "datetime")) addOp(true, "last365days", literal(moment().subtract(1, "minutes").subtract(1, "days").toISOString(), "datetime")) +addOp(false, "last12months", literal(moment().subtract(1, "minutes").add(3, "days").toISOString(), "datetime")) +addOp(false, "last12months", literal(moment().subtract(1, "minutes").subtract(12, "months").toISOString(), "datetime")) +addOp(true, "last12months", literal(moment().subtract(1, "minutes").subtract(3, "days").toISOString(), "datetime")) + +addOp(false, "last6months", literal(moment().subtract(1, "minutes").add(3, "days").toISOString(), "datetime")) +addOp(false, "last6months", literal(moment().subtract(1, "minutes").subtract(6, "months").toISOString(), "datetime")) +addOp(true, "last6months", literal(moment().subtract(1, "minutes").subtract(3, "days").toISOString(), "datetime")) + +addOp(false, "last3months", literal(moment().subtract(1, "minutes").add(3, "days").toISOString(), "datetime")) +addOp(false, "last3months", literal(moment().subtract(1, "minutes").subtract(3, "months").toISOString(), "datetime")) +addOp(true, "last3months", literal(moment().subtract(1, "minutes").subtract(3, "days").toISOString(), "datetime")) + addOp("1", "weekofmonth", literal("2015-05-07", "date")) addOp("2", "weekofmonth", literal("2015-05-08", "date"))