brianc / node-postgres

PostgreSQL client for node.js.

Home Page:https://node-postgres.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Client returns wrong date, when the date in Postgres is declared as date-type

vheinitz opened this issue · comments

I have declared a date column in Postgres as date.
When I write the value with node's pg module, the Postgres Tool pgAdmin displays it correctly.
When I read the value back using pg, Instead of plain date, a date-time string comes with wrong day.
e.g.:

Date inserted: 1975-05-11
Date displayed by pgAdmin: 1975-05-11
Date returned by node's pg: 1975-05-10T23:00:00.000Z

The error seems to be due to the different handling of time-zone during parsing from string and converting the Date-object back to string.

I hope this post may help: SO

The node-postgres team decided long ago to convert dates and datetimes
without timezones to local time when pulling them out. This is consistent
with some documentation we've dug up in the past. If you root around
through old issues here you'll find the discussions.

The good news is its trivially easy to over-ride this behavior and return
dates however you see fit.

There's documentation on how to do this here:
https://github.com/brianc/node-pg-types

There's probably even a module somewhere that will convert dates from
postgres into whatever timezone you want (utc I'm guessing). And if
there's not...that's a good opportunity to write one & share with everyone!

On Fri, Jul 24, 2015 at 6:36 AM, Valentin Heinitz notifications@github.com
wrote:

I have declared a date column in Postgres as date.
When I write the value with node's pg module, the Postgres Tool pgAdmin
displays it correctly.
When I read the value back using pg, Instead of plain date, a date-time
string comes with wrong day.
e.g.:

Date inserted: 1975-05-11
Date displayed by pgAdmin: 1975-05-11
Date returned by node's pg: 1975-05-10T23:00:00.000Z

The error seems to be due to the different handling of time-zone during
parsing from string and converting the Date-object back to string.

I hope this post may help: SO
http://stackoverflow.com/questions/31608368/nodes-postgres-module-pg-returns-wrong-date


Reply to this email directly or view it on GitHub
#818.

I'm affraid, trying to convert date objects to timestamps doesn't work wll in all use-cases.

There are dates like birth-dates or historical events, which have no time-relevance. If one client writes let's say 1973-09-11 and another reads 1973-09-10 it is bad.

The date 1973-09-11 is a historical event. May be, that from Australian point of view it happened a day before or a day after, but even in their historical books the date is provided as 1973-09-11.

Yeah you're totally right about that if you're storing them for that
reason. Definitely suggest you over-write the type parser to return them
as a custom data type or maybe even just a string?

On Fri, Jul 24, 2015 at 12:19 PM, Valentin Heinitz <notifications@github.com

wrote:

I'm affraid, trying to convert date objects to timestamps doesn't work wll
in all use-cases.

There are dates like birth-dates or historical events, which have no
time-relevance. If one client writes let's say 1973-09-11 and another reads
1973-09-10 it is bad.

The date 1973-09-11 is a historical event. May be, that from Australian
point of view it happened a day before or a day after, but even in their
historical books the date is provided as 1973-09-11.


Reply to this email directly or view it on GitHub
#818 (comment)
.

Thank you very much, Brian for you quick response and suggestions! I'll check the opportunities you've mentioned.

This is workaround what i did:

/* Node postgres date fix /
var Moment = require('moment');
var parseDate = function parseDate(val) {
return val === null ? null : Moment(val).format('YYYY-MM-DD')
};
var types = pg.types;
var DATATYPE_DATE = 1082;
types.setTypeParser(DATATYPE_DATE, function(val) {
return val === null ? null : parseDate(val)
});
/
Node postgres date fix - end */

commented

This behaviour is crazy to me.

In almost all cases you should be using timestamptz EXCEPT when you need to store future dates at wall-time. This is where timestamp comes in.

Storing without timezone for future dates protects againsts changes to DST that can and do happen before the future date arrives.

Since pg is parsing timestamp into UTC, things get really weird at the application layer.

I think the main problem here is that pg coerces both of these types into a Date. It would be super weird if timestamptz was a Date and timestamp was a String, so this is probably the reasoning.

For anyone running into similar issues, I ended up bypassing the parser for timestamp completely and just use a String:

import pg from 'pg'
pg.types.setTypeParser(1114, function (value) {
  return value
})

@ashconnell thank you!

You have to bypass the date parser also:

pg.types.setTypeParser(1082, function(value) { //date
  return value;
});

There are built-in constants for date (1082), timestamp (1114) and timestamptz (1184) :

pg.types.setTypeParser(pg.types.builtins.DATE, value => value)

pg.types.setTypeParser(pg.types.builtins.TIMESTAMP, value => value)

pg.types.setTypeParser(pg.types.builtins.TIMESTAMPTZ, value => value)