我使用 Node.js 和 pg 来查询 Postgres 数据库。我正在尝试执行以下查询:
SELECT COUNT(*) FROM table_name WHERE date_time_added::date = some_date;
some_date 是我从 Node.js 传递的日期。
我大部分时间都没有问题,因为两个日期/时间字符串的格式相同。但是,引入时区时会出现问题。由于我位于英国,因此我们在一年中的某些时候使用英国夏令时 (GMT+1)。
当我将 date_time_ added 从它的存储类型(带时区的时间戳)转换为日期时,时间默认为午夜。这样做的问题是在 BST 期间,时间戳被投射到前一天,并且时间设置为 23:00 而不是 00:00,如下所示:
{ date_time_added: 2020-09-28T23:00:00.000Z }
如果 JavaScript 具有相同的行为,这不会成为问题,但是如果我尝试以下操作:
const date1 = new Date(2020, 8, 29, 10, 47, 54);
console.log(date1.toString());
date1.setHours(0);
date1.setMinutes(0);
date1.setSeconds(0);
date1.setMilliseconds(0);
console.log(date1.toString());
产生以下输出:
"Tue Sep 29 2020 10:47:54 GMT+0100 (British Summer Time)"
"Tue Sep 29 2020 00:00:00 GMT+0100 (British Summer Time)"
时间设置为午夜而不是前一天的 23:00。这对我来说是个问题,因为这意味着日期不匹配,因此数据库查询中不会返回该行。
有谁知道我如何为两个日期(JS 和 Postgres)获得相同的行为?能够以与 Postgres 相同的方式初始化一个新的日期对象,默认时间与我投射到日期时一样,但是我不确定这是否可行。
答案 0 :(得分:0)
发布以防其他人将来遇到此问题。
这个问题是因为在 Postgres 中将时间戳转换为日期会丢失时区,因此它从午夜减去了一个小时(因为将时区转换为日期时时间设置为午夜),导致它变成 23 :00 日期前一天(因为 BST 是 +1 小时)。
我决定使用纪元时间,因为这使得比较更容易满足我的需求。
我使用以下查询解决了这个问题:
SELECT COUNT(*) FROM table_name WHERE extract(epoch from date_trunc('day', date_time_added)) = some_date_epoch;
这会保留时区并返回所选时间戳日期的纪元时间(午夜)。 'some_date_epoch' 是 JavaScript 日期对象的纪元时间,使用 Date.getTime() 方法获得。这是我想在数据库中搜索的日期的纪元时间。
例如,这是我如何在 JavaScript 中获取当前日期的纪元时间,然后在数据库查询中使用:
let currentDate = new Date();
currentDate.setHours(0);
currentDate.setMinutes(0);
currentDate.setSeconds(0);
currentDate.setMilliseconds(0);
let currentDateEpoch = (currentDate.getTime() / 1000); //Convert to seconds to match Postgres
currentDateEpoch 然后将用于查询数据库。