From bde871707b0ca2f16ea416a605f45999f7e60828 Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Mon, 14 Jan 2013 18:07:18 +0100 Subject: [PATCH 1/4] Storing timezone-less dates in local time instead of UTC Issue #225 caused such dates to be read, but not stored in local time. --- lib/utils.js | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 7bbbe5b6..9dc54538 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -47,7 +47,7 @@ function arrayString(val) { //for complex types, etc... var prepareValue = function(val) { if(val instanceof Date) { - return JSON.stringify(val); + return dateToString(val); } if(typeof val === 'undefined') { return null; @@ -58,6 +58,33 @@ var prepareValue = function(val) { return val === null ? null : val.toString(); }; +function dateToString(date) { + function pad(number, digits) { + number = ""+number; + while(number.length < digits) + number = "0"+number; + return number; + } + + var offset = -date.getTimezoneOffset(); + var ret = pad(date.getFullYear(), 4) + '-' + + pad(date.getMonth() + 1, 2) + '-' + + pad(date.getDate(), 2) + 'T' + + pad(date.getHours(), 2) + ':' + + pad(date.getMinutes(), 2) + ':' + + pad(date.getSeconds(), 2) + '.' + + pad(date.getMilliseconds(), 3); + + if(offset < 0) { + ret += "-"; + offset *= -1; + } + else + ret += "+"; + + return ret + pad(Math.floor(offset/60), 2) + ":" + pad(offset%60, 2); +} + function normalizeQueryConfig (config, values, callback) { //can take in strings or config objects config = (typeof(config) == 'string') ? { text: config } : config; From 694fc3eb6efb734ba5bd916ff64f308c82ed2616 Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Thu, 11 Apr 2013 00:41:15 +0200 Subject: [PATCH 2/4] Fixing code style to make #238 pass jshint --- lib/utils.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 9dc54538..267f3972 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -67,13 +67,13 @@ function dateToString(date) { } var offset = -date.getTimezoneOffset(); - var ret = pad(date.getFullYear(), 4) + '-' - + pad(date.getMonth() + 1, 2) + '-' - + pad(date.getDate(), 2) + 'T' - + pad(date.getHours(), 2) + ':' - + pad(date.getMinutes(), 2) + ':' - + pad(date.getSeconds(), 2) + '.' - + pad(date.getMilliseconds(), 3); + var ret = pad(date.getFullYear(), 4) + '-' + + pad(date.getMonth() + 1, 2) + '-' + + pad(date.getDate(), 2) + 'T' + + pad(date.getHours(), 2) + ':' + + pad(date.getMinutes(), 2) + ':' + + pad(date.getSeconds(), 2) + '.' + + pad(date.getMilliseconds(), 3); if(offset < 0) { ret += "-"; From 62800f1db096d12e8755f6c23de3bd179f277daa Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Thu, 11 Apr 2013 00:42:37 +0200 Subject: [PATCH 3/4] Adding test for timezone handling (#238) --- test/integration/client/timezone-tests.js | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/integration/client/timezone-tests.js diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js new file mode 100644 index 00000000..b355550d --- /dev/null +++ b/test/integration/client/timezone-tests.js @@ -0,0 +1,29 @@ +var helper = require(__dirname + '/../test-helper'); +var exec = require('child_process').exec; + +var oldTz = process.env.TZ; +process.env.TZ = 'Europe/Berlin'; + +var date = new Date(); + +helper.pg.connect(helper.config, function(err, client, done) { + assert.isNull(err); + + test('timestamp without time zone', function() { + client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [ date ], function(err, result) { + assert.isNull(err); + assert.equal(result.rows[0].val.getTime(), date.getTime()); + + test('timestamp with time zone', function() { + client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [ date ], function(err, result) { + assert.isNull(err); + assert.equal(result.rows[0].val.getTime(), date.getTime()); + + done(); + helper.pg.end(); + process.env.TZ = oldTz; + }); + }); + }); + }); +}); \ No newline at end of file From 3aedebb0b00b5bf238e94dfc6c9724210cccead2 Mon Sep 17 00:00:00 2001 From: Candid Dauth Date: Thu, 11 Apr 2013 01:11:08 +0200 Subject: [PATCH 4/4] Fixing parsing of timestamps without timezone in binary mode --- lib/types/binaryParsers.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/types/binaryParsers.js b/lib/types/binaryParsers.js index 7f0a89c6..ca55cc4e 100644 --- a/lib/types/binaryParsers.js +++ b/lib/types/binaryParsers.js @@ -141,13 +141,17 @@ var parseNumeric = function(value) { return ((sign === 0) ? 1 : -1) * Math.round(result * scale) / scale; }; -var parseDate = function(value) { +var parseDate = function(isUTC, value) { var sign = parseBits(value, 1); var rawValue = parseBits(value, 63, 1); // discard usecs and shift from 2000 to 1970 var result = new Date((((sign === 0) ? 1 : -1) * rawValue / 1000) + 946684800000); + if (!isUTC) { + result.setTime(result.getTime() + result.getTimezoneOffset() * 60000); + } + // add microseconds to the date result.usec = rawValue % 1000; result.getMicroSeconds = function() { @@ -247,8 +251,8 @@ var init = function(register) { register(700, parseFloat32); register(701, parseFloat64); register(16, parseBool); - register(1114, parseDate); - register(1184, parseDate); + register(1114, parseDate.bind(null, false)); + register(1184, parseDate.bind(null, true)); register(1007, parseArray); register(1016, parseArray); register(1008, parseArray);