d51*_*512 4 utc node.js sequelize.js
我正在为节点项目使用sequelize。它连接到一个 Postgres 数据库,它包含一个带有DATE字段的表(与 不同TIMESTAMP WITH TIMEZONE,DATE没有时间数据)。
在代码中,我使用 javascriptDate对象对日期进行建模,该对象将时间存储为 UTC 午夜。当我使用该Date对象将记录插入到表中时,sequelize 显然首先将其覆盖到本地时间,因为记录总是落后 1 天。因此,如果我想将 2000-10-31 插入到数据库中,我最终会得到 2000-10-30。我在UTC-5。
如何告诉 sequelize 在插入数据库之前不要将日期转换为本地时间?
这是一些示例代码。如果你想自己运行它,我还创建了一个存储库。
var Sequelize = require('sequelize');
const sequelize = new Sequelize('testdb', 'postgres', '???', {
host: 'localhost',
dialect: 'postgres'
});
TestTable = sequelize.define('date_test',
{
id: {
primaryKey: true,
type: Sequelize.INTEGER,
autoIncrement: true
},
someDate: {
field: 'some_date',
type: Sequelize.DATEONLY
}
},
{
timestamps: false,
freezeTableName: true
}
);
// midnight UTC on Halloween
var date = new Date(Date.UTC(2000, 9, 31));
// converts to local time resulting in 2000-10-30
TestTable.create({ someDate: date })
.then(function() {
// also apparently converts to local time resulting in 2000-10-30
return TestTable.create({ someDate: date.toUTCString() });
})
.then(function() {
// convert to string, definitely works but seems unnecessary
var strDate = date.getUTCFullYear() + '-' + pad2(date.getUTCMonth() + 1) + '-' + pad2(date.getUTCDate());
return TestTable.create({ someDate: strDate });
})
.then(function() {
// cerate a new local Date, also works but seems hacky
var newDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
return TestTable.create({ someDate: newDate });
})
.then(function() {
process.exit(0);
});
function pad2(n) {
if (n.length === 1) {
return '0' + n;
}
return n;
}
Run Code Online (Sandbox Code Playgroud)
小智 5
问题是日期是作为 UTC 时间创建的,但由于DATEONLY不知道时区,它使用格式YYYY-MM-DD(使用 moment.js -请参阅此处的源代码)“按原样”(本地时间)格式化日期对象。
对于 aDATEONLY你可以这样做:
var date = new Date(2000, 9, 31);
Run Code Online (Sandbox Code Playgroud)
这将正确插入日期。
程序员很少这么说,但有一次你对时区考虑太多了!
这取决于您如何检查值,但 javascript 和 postgresql 正在将其转换为您的本地时区以进行显示。
Sequelize 使用TIMESTAMP WITH TIMEZONE类型作为日期字段(source)。
在postgresql 文档中它说:
对于带时区的时间戳,内部存储的值始终采用 UTC(世界协调时间,传统上称为格林威治标准时间,GMT)。使用该时区的适当偏移量将具有指定显式时区的输入值转换为 UTC。如果输入字符串中未指定时区,则假定其位于系统时区参数指示的时区中,并使用时区区域的偏移量转换为 UTC。
当输出带有时区值的时间戳时,它总是从UTC转换为当前时区区域,并显示为该区域的本地时间。要查看另一个时区的时间,请更改时区或使用 AT TIME ZONE 构造(请参阅第 9.9.3 节)。
如果您在 postgresql 中输出时间值,请尝试将其转换为 UTC。如果您在 javascript 中输出它,请尝试date.toUTCString().
您的 hack 似乎有效的原因是因为它们实际上是在存储,2000-11-01 05:00但是当您检查该值时,它会转换为您的本地时区。
| 归档时间: |
|
| 查看次数: |
10335 次 |
| 最近记录: |