From a1d784b60426fc9cd282b0485819e29b7d0e3c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miroslav=20Bajto=C5=A1?= Date: Tue, 13 Sep 2016 10:38:51 +0200 Subject: [PATCH] Fix rest-coercion of timestamp strings When converting a value coming from a string source like querystring to a date, and the value is a timestamp (i.e. an integer), we treat the value as a number now. That way the value "0" always produces "1970-01-01T00:00:00.000Z" instead of some date around 1999/2000/2001 depending on server timezone. --- 3.0-RELEASE-NOTES.md | 5 +++++ lib/types/date.js | 8 ++++++-- test/rest-coercion/urlencoded-array.suite.js | 4 ++-- test/rest-coercion/urlencoded-date.suite.js | 19 ++++++++----------- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/3.0-RELEASE-NOTES.md b/3.0-RELEASE-NOTES.md index 4c7c8617..ce00ca80 100644 --- a/3.0-RELEASE-NOTES.md +++ b/3.0-RELEASE-NOTES.md @@ -168,6 +168,11 @@ Most notable breaking changes: 'true', 'false', '0' and '1' Values are case-insensitive, i.e. 'TRUE' and 'FaLsE' work too. - Date type detects "Invalid Date" and rejects such requests. + - When converting a value coming from a string source like querystring + to a date, and the value is a timestamp (i.e. an integer), we treat + the value as a number now. That way the value "0" always produces + "1970-01-01T00:00:00.000Z" instead of some date around 1999/2000/2001 + depending on server timezone. Hopefully this change should leave most LoopBack applications (and clients) unaffected. If your start seeing unusual amount of 400 error responses after diff --git a/lib/types/date.js b/lib/types/date.js index 4d9e7384..37676e4d 100644 --- a/lib/types/date.js +++ b/lib/types/date.js @@ -28,8 +28,12 @@ module.exports = { if (value === '') return { value: undefined }; - // we don't have any special sloppy conversion yet - // TODO(bajtos) convert numeric strings to numbers first + if (/^-?[0-9]+$/.test(value)) { + // convert a timestamp string to a number + // that way ?from=0 produces 1970-01-01T00:00:00.000Z + value = +value; + } + return this.fromTypedValue(ctx, value); }, diff --git a/test/rest-coercion/urlencoded-array.suite.js b/test/rest-coercion/urlencoded-array.suite.js index 8cf2828d..5f94299c 100644 --- a/test/rest-coercion/urlencoded-array.suite.js +++ b/test/rest-coercion/urlencoded-array.suite.js @@ -196,8 +196,8 @@ function suite(prefix, ctx) { ['arg=null', null], // Valid values - repeated keys - ['arg=0', [new Date('0')]], // 1999-12-31T23:00:00.000Z in CEST - ['arg=1', [new Date('1')]], // 2000-12-31T23:00:00.000Z + ['arg=0', [new Date('1970-01-01T00:00:00.000Z')]], + ['arg=1', [new Date('1970-01-01T00:00:00.001Z')]], ['arg=2016-05-19T13:28:51.299Z', [new Date('2016-05-19T13:28:51.299Z')]], ['arg=2016-05-19T13:28:51.299Z&arg=2016-05-20T08:27:28.539Z', [ diff --git a/test/rest-coercion/urlencoded-date.suite.js b/test/rest-coercion/urlencoded-date.suite.js index 097c2e85..f2aa6739 100644 --- a/test/rest-coercion/urlencoded-date.suite.js +++ b/test/rest-coercion/urlencoded-date.suite.js @@ -50,18 +50,15 @@ function suite(prefix, ctx) { ['arg=Thu+May+19+2016+15:28:51+GMT+0200+(CEST)', new Date('2016-05-19T15:28:51.000Z')], - // NOTE(bajtos) should we convert the numeric values into a number - // before passing it to the Date constructor? - // That way ?arg=0 would produce '1970-01-01T00:00:00.000Z', which is + // Integer values are converted to a number before passing it to + // the Date constructor + // That way ?arg=0 produces '1970-01-01T00:00:00.000Z', which is // arguably more expected then some date around 1999/2000/2001 - // Also note that with the current implementation, the parsed - // value depends on the timezone of the server, therefore - // we cannot specify exact date values here in the test - // and have to use the same Date input as in the HTTP request :( - // See also https://github.com/strongloop/strong-remoting/issues/238 - ['arg=0', new Date('0')], // 1999-12-31T23:00:00.000Z in CEST - ['arg=1', new Date('1')], // 2000-12-31T23:00:00.000Z - ['arg=-1', new Date('-1')], // 2000-12-31T23:00:00.000Z + ['arg=0', new Date('1970-01-01T00:00:00.000Z')], + ['arg=1', new Date('1970-01-01T00:00:00.001Z')], + ['arg=-1', new Date('1969-12-31T23:59:59.999Z')], + + // Non-integer numbers are treated as strings. ['arg=1.2', new Date('1.2')], // 2001-01-01T23:00:00.000Z ['arg=-1.2', new Date('-1.2')], // 2001-01-01T23:00:00.000Z