Skip to content

Commit

Permalink
Add Date comparison support
Browse files Browse the repository at this point in the history
  • Loading branch information
pbatey committed Mar 15, 2015
1 parent 8d600fc commit fd2868a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 2 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Any query parameters other then _fields_, _sort_, _offset_, and _limit_ are inte
* Supports standard comparison operations (=, !=, >, <, >=, <=).
* Numeric values, where `Number(value) != NaN`, are compared as numbers (ie., `field=10` yields `{field:10}`).
* Values of _true_ and _false_ are compared as booleans (ie., `{field:true}`)
* Values that are [dates](http://www.w3.org/TR/NOTE-datetime) are compared as dates (except for YYYY which matches the number rule).
* Multiple equals comparisons are merged into a `$in` operator. For example, `id=a&id=b` yields `{id:{$in:['a','b']}}`.
* Multiple not-equals comparisons are merged into a `$nin` operator. For example, `id!=a&id!=b` yields `{id:{$nin:['a','b']}}`.
* Comma separated values in equals or not-equals yeild an `$in` or `$nin` operator. For example, `id=a,b` yields `{id:{$in:['a','b']}}`.
Expand Down
7 changes: 5 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var querystring = require('querystring')
var iso8601 = require('./lib/iso8601-regex')

// Convert comma separate list to a mongo projection.
// for example f('field1,field2,field3') -> {field1:true,field2:true,field3:true}
Expand All @@ -24,10 +25,12 @@ function sortToMongo(sort) {
return hash
}

// Convert String to Number or Boolean if possible
// Convert String to Number, Date, or Boolean if possible
function typedValue(value) {
var n = Number(value)
return (n && n != NaN) ? n : ((value == 'true') || ((value == 'false') ? false : value))
if (n && n != NaN) return n
if (iso8601.test(value)) return new Date(value)
return (value == 'true') || ((value == 'false') ? false : value)
}

// Convert a key/value pair split at an equals sign into a mongo comparison.
Expand Down
1 change: 1 addition & 0 deletions lib/iso8601-regex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = /^\d{4}(-(0[1-9]|1[0-2])(-(0[1-9]|[12][0-9]|3[01]))?)?(T([01][0-9]|2[0-3]):[0-5]\d(:[0-5]\d(\.\d+)?)?(Z|[+-]\d{2}:\d{2}))?$/
56 changes: 56 additions & 0 deletions test/iso8601-regex.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
var assert = require("chai").assert
var iso8601 = require('../lib/iso8601-regex')

describe("iso8601-regex", function () {
it("should match YYYY", function () {
assert.ok(iso8601.test("2000"))
})
it("should match YYYY-MM", function () {
assert.ok(iso8601.test("2000-04"))
})
it("should match YYYY-MM-DD", function () {
assert.ok(iso8601.test("2000-04-01"))
})
it("should match YYYY-MM-DDThh:mmZ", function () {
assert.ok(iso8601.test("2000-04-01T12:00Z"), 'Z')
assert.ok(iso8601.test("2000-04-01T12:00-08:00"), '-08:00')
assert.ok(iso8601.test("2000-04-01T12:00+01:00"), '+01:00')
})
it("should match YYYY-MM-DDThh:mm:ssZ", function () {
assert.ok(iso8601.test("2000-04-01T12:00:30Z"), 'Z')
assert.ok(iso8601.test("2000-04-01T12:00:30-08:00"), '-08:00')
assert.ok(iso8601.test("2000-04-01T12:00:30+01:00"), '+01:00')
})
it("should match YYYY-MM-DDThh:mm:ss.sZ", function () {
assert.ok(iso8601.test("2000-04-01T12:00:30.250Z"), 'Z')
assert.ok(iso8601.test("2000-04-01T12:00:30.250-08:00"), '-08:00')
assert.ok(iso8601.test("2000-04-01T12:00:30.250+01:00"), '+01:00')
})
it("should not match time without timezone", function () {
assert.notOk(iso8601.test("2000-04-01T12:00"), 'hh:mm')
assert.notOk(iso8601.test("2000-04-01T12:00:00"), 'hh:mm:ss')
assert.notOk(iso8601.test("2000-04-01T12:00:00.000"), 'hh:mm:ss.s')
})
it("should not match out of range month", function () {
assert.notOk(iso8601.test("2000-00"), '00')
assert.notOk(iso8601.test("2000-13"), '13')
})
it("should not match out of range day", function () {
assert.notOk(iso8601.test("2000-04-00"), '00')
assert.notOk(iso8601.test("2000-04-32"), '32')
})
it("should not match out of range hour", function () {
assert.notOk(iso8601.test("2000-04-01T24:00Z"))
})
it("should not match out of range minute", function () {
assert.notOk(iso8601.test("2000-04-01T12:60Z"))
})
it("should not match out of range second", function () {
assert.notOk(iso8601.test("2000-04-01T12:00:60Z"))
})
it("should not match time without timezone", function () {
assert.notOk(iso8601.test("2000-04-01T12:00"), 'hh:mm')
assert.notOk(iso8601.test("2000-04-01T12:00:00"), 'hh:mm:ss')
assert.notOk(iso8601.test("2000-04-01T12:00:00.000"), 'hh:mm:ss.s')
})
})
69 changes: 69 additions & 0 deletions test/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,75 @@ describe("query-to-mongodb(query) =>", function () {
assert.ok(results.criteria)
assert.deepEqual(results.criteria, {t: true, f: false})
})
it("should create Date criteria from YYYY-MM", function () {
var results = q2m("d=2010-04"), expect
assert.ok(results.criteria)
expect = new Date(2010, 3)
expect.setUTCDate(1)
expect.setUTCHours(0)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DD", function () {
var results = q2m("d=2010-04-01"), expect
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(0)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DDThh:mmZ", function () {
var results = q2m("d=2010-04-01T12:00Z")
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(12)
expect.setUTCMinutes(0)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DDThh:mm:ssZ", function () {
var results = q2m("d=2010-04-01T12:00:30Z")
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(12)
expect.setUTCMinutes(0)
expect.setUTCSeconds(30)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DDThh:mm:ss.sZ", function () {
var results = q2m("d=2010-04-01T12:00:30.250Z")
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(12)
expect.setUTCMinutes(0)
expect.setUTCSeconds(30)
expect.setUTCMilliseconds(250)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DDThh:mm:ss.s-hh:mm", function () {
var results = q2m("d=2010-04-01T11:00:30.250-01:00")
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(12)
expect.setUTCMinutes(0)
expect.setUTCSeconds(30)
expect.setUTCMilliseconds(250)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create Date criteria from YYYY-MM-DDThh:mm:ss.s+hh:mm", function () {
var results = q2m(encodeURIComponent("d=2010-04-01T13:00:30.250+01:00"))
assert.ok(results.criteria)
expect = new Date(2010, 3, 1)
expect.setUTCHours(12)
expect.setUTCMinutes(0)
expect.setUTCSeconds(30)
expect.setUTCMilliseconds(250)
assert.ok(results.criteria.d instanceof Date, 'instanceof Date')
assert.deepEqual(results.criteria, {d: expect})
})
it("should create $gt criteria", function () {
var results = q2m("field>value")
assert.ok(results.criteria)
Expand Down

0 comments on commit fd2868a

Please sign in to comment.