首页 > 解决方案 > 如何将 Postgresql 时间戳转换为 Javascript 日期?

问题描述

now()::TEXT我的数据库使用该函数创建了一堆 timestamptz 值。在几个 API 调用中,我收到了这些值,但我很难将它们转换为 Javascript Date 对象。

这是 Postgres 返回的 Timestamptz 字符串的示例:2019-09-12 09:52:52.992823+00

问题是,如果我尝试这样做new Date("2019-09-12 09:52:52.992823+00"),那么浏览器中就会出现挑剔的行为。看起来我必须先在字符串中附加一个“Z”才能正确获取时间(因为时区?)

此外,Firefox 似乎根本不解析它(但 Chrome 可以)。如果我删除“+00”,它似乎工作。

所以我想出了这个似乎适用于两种浏览器的“解决方案”,但在使用它们之前我必须在所有日期调用它,它似乎有点脆弱。这是正确的方法吗?

function fixDate(date) {
  return date.replace("+00", "") + "Z";
}

标签: javascriptstringpostgresqldatetimezone

解决方案


内置解析器支持的格式在ECMA-262中描述,本质上是 ISO 8601 的特定子集和为Date.prototype.toString指定的格式。任何其他格式的解析(即与指定格式之一不完全匹配的任何内容都依赖于实现,不应被信任。

您可以考虑解析字符串并构造一个符合 ECMA-262 的新字符串,例如将“2019-09-12 09:52:52.992823+00”转换为“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)))

但是,还要注意避免使用内置解析器的一般建议,即使使用受支持的格式。解析一个字符串以生成另一个字符串,然后再次解析该字符串以生成一个日期似乎也是低效的。最好编写自己的解析函数(几行代码)或使用库,例如

// 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());


推荐阅读