Reputation: 11996
My database creates a bunch of timestamptz values using the now()::TEXT
function. In several API calls I receive these values, but I'm having difficulty turning them into Javascript Date objects.
Here's an example of a Timestamptz string that Postgres returns: 2019-09-12 09:52:52.992823+00
The problem is that if I try to do new Date("2019-09-12 09:52:52.992823+00")
, then there's finicky behavior in the browser. It looks like I have to append a "Z" first to the string to get the time correct (because of timezones?)
Also, Firefox doesn't seem to parse it at all (but Chrome does). If I remove the "+00", it seems to work.
So I came up with this "solution" which seems to work on both browsers, but I have to call it on all my dates before working with them, and it seems kinda brittle. Is this the proper way?
function fixDate(date) {
return date.replace("+00", "") + "Z";
}
Upvotes: 3
Views: 7155
Reputation: 147363
The supported formats for the built–in parser are described in ECMA-262, essentially a specific subset of ISO 8601 and the format specified for Date.prototype.toString. Parsing of any other format (that is, anything that doesn't match exactly with one of the specified formats) is implementation dependent and should not be trusted.
You might consider parsing the string and constructing a new string that is compliant with ECMA-262, e.g. convert "2019-09-12 09:52:52.992823+00" to "2019-09-12T09:52:52.992+00:00".
// Convert 2019-09-12 09:52:52.992823+00 to
// 2019-09-12T09:52:52.992+00:00
// Assumes all strings are +00:00
function rectifyFormat(s) {
let b = s.split(/\D/);
return b[0] + '-' + b[1] + '-' + b[2] + 'T' +
b[3] + ':' + b[4] + ':' + b[5] + '.' +
b[6].substr(0,3) + '+00:00';
}
let s = '2019-09-12 09:52:52.992823+00';
console.log(new Date(rectifyFormat(s)))
However, also heed the general advice to avoid the built–in parser, even with supported formats. It also seems inefficient to parse a string to produce another string that is then parsed again to produce a Date. It's preferable to write your own parse function (a couple of lines of code) or use a library, e.g.
// Parse string like '2019-09-12 09:52:52.992823+00'
// to a date
// Assumes string is always +00
function myDateParse(s) {
let b = s.split(/\D/);
--b[1]; // Adjust month number
b[6] = b[6].substr(0,3); // Microseconds to milliseconds
return new Date(Date.UTC(...b));
}
let s = '2019-09-12 09:52:52.992823+00';
console.log(myDateParse(s).toISOString());
Upvotes: 2