javascript + postgres:时区和时间戳的使用
Posted
技术标签:
【中文标题】javascript + postgres:时区和时间戳的使用【英文标题】:javascript + postgres: timezone and timestamp usage 【发布时间】:2015-11-09 01:41:29 【问题描述】:我不太了解时间戳的用法,
例如
用户创建文章,可以选择PublishDate
,系统也会自动存储CreateDate
。
一个。我应该使用时区制作PublishDate
和CreateDate
时间戳并设置UTC?
b.用户发布字符串,然后我像下面使用momentjs
转换为utc 时间戳并存储,当有人选择此行时,将它们显示为用户客户端时间反向使用momentjs
c。我使用CURRENT_TIMESTAMP
到CreateDate
,CURRENT_TIMESTAMP
这是否意味着服务器时间?我做对了吗?
我的想法是我总是将 utc 时区时间戳插入数据库,并且无论用户/客户端读取的位置,将数据转换为用户/客户端时区?我做对了吗?
一个。我的数据库(postgres)由
创建CREATE TABLE IF NOT EXISTS "Article"(
"ArticleId" SERIAL NOT NULL,
"PublishDate" timestamp with time zone,
"Active" bit NOT NULL,
"CreateByUserId" integer,
"CreateDate" timestamp with time zone,
PRIMARY KEY ("ArticleId")
);
SET timezone = 'UTC';
b.用户提交帖子到存储(nodejs)
// publishDate: '"y":2015,"m":8,"d":16,"h":15,"mi":46,"s":24
var publishDate = JSON.parse(req.body.publishDate);
var leadingZeroAndDateFormat = function(publishDate)
return new Promise(function (fulfill, reject)
if (publishDate.m < 10) publishDate.m = '0'+publishDate.m;
if (publishDate.d < 10) publishDate.d = '0'+publishDate.d;
if (publishDate.h < 10) publishDate.h = '0'+publishDate.h;
if (publishDate.mi < 10) publishDate.mi = '0'+publishDate.mi;
if (publishDate.s < 10) publishDate.s = '0'+publishDate.s;
var str = publishDate.y+'-'+publishDate.m+'-'+publishDate.d+' '+publishDate.h+':'+publishDate.mi+':'+publishDate.s;
var utc = moment(str).unix();
fulfill(utc);
);
;
c。将CreateDate
插入数据库使用CURRENT_TIMESTAMP
var insertArticle = function(publishDate, active, createByUserId)
return new Promise(function (fulfill, reject)
var query = 'INSERT INTO "Article" ("PublishDate","Active","CreateByUserId","CreateDate") VALUES ($1,$2,$3,CURRENT_TIMESTAMP) RETURNING "ArticleId"';
dbClient.query(query,[publishDate,active,createByUserId], function(error, result)
if (error)
reject(error);
else
fulfill(result);
);
);
;
更新
当我更改没有时区的所有列时,我执行insertArticle
显示错误
[error: date/time field value out of range: "1439717298"]
name: 'error',
length: 158,
severity: 'ERROR',
code: '22008',
detail: undefined,
hint: 'Perhaps you need a different "datestyle" setting.',
position: undefined,
internalPosition: undefined,
internalQuery: undefined,
where: undefined,
schema: undefined,
table: undefined,
column: undefined,
dataType: undefined,
constraint: undefined,
file: 'datetime.c',
line: '3775',
routine: 'DateTimeParseError'
var insertArticle = function(publishDate, active, createByUserId)
return new Promise(function (fulfill, reject)
var query = 'INSERT INTO "Article" ("PublishDate","Active","CreateByUserId","CreateDate") VALUES ($1,$2,$3,$4) RETURNING "ArticleId"';
dbClient.query(query,[publishDate,active,createByUserId,moment.utc().unix()], function(error, result)
if (error)
reject(error);
else
fulfill(result);
);
);
;
【问题讨论】:
始终使用 UTC 时间和没有时区的时间戳,因为不需要存储不同的时区。如果需要,然后在表示层处理区域。 感谢您的回复,是否意味着将列设置为不带时区?然后在插入时使用 momentjs utc 时间戳 是的,使数据库中的列没有时区,并始终存储从时刻开始的 UTC 时间。通过这种方式,您始终知道数据是什么,并且可以轻松处理它。演示也可以在您轻松选择的任何时区进行。 A) 始终使用类型 timestamptz。 B) 始终插入为 UTC,这是 PostgreSQL 始终自动理解的格式。如果您使用pg-promise,则默认情况下始终获得 UTC。 【参考方案1】:最简单的方法是始终以 UTC 格式存储没有时区的时间戳。这样,使用它们进行显示和计算总是很容易。差异只是减法,直接比较。
如果该列是带有时区的时间戳,则无论如何输入都将转换为 UTC,但输出将处于当前设置的时区,如果设置不正确,则可能会显示错误的值。这也降低了数据库的效率。
在表示层中,时间戳可以显示在适当的时区,输入的值也可以转换为 UTC 进行存储。
这是处理时间戳的最简单、最有效和最灵活的方式。
使用 CURRENT_TIMESTAMP 将在执行时从服务器获取时间戳。
【讨论】:
我将列更新为没有时区,但是当我执行`insertArticle`时显示错误[error: date/time field value out of range: "1439715951000"]
这似乎是一个毫秒值,可能是 UNIX 纪元?然后你需要插入timestamp '1970-1-1' + interval '12357 seconds'
来实现一个实际的时间戳。当然数字转换为秒。
插入`时间戳'1970-1-1'+间隔'12357秒'`?你的意思是在数据库 sql 上执行这个
是的,而不是仅仅发送数字,如果时刻给出它的话,发送它的秒数。我对 moment/node.js 不熟悉,所以很遗憾无法给出最佳答案。我认为还有一种方法可以直接绑定时间戳/日期时间值。
如果我的服务器有时在欧洲或美国,这可行吗?我想要一个正确的日期,并且不依赖于服务器位置【参考方案2】:
没有时区的传入时间戳是在本地时间而不是 UTC 中解析的——我称之为 node-postgres 中的错误。无论如何,您可以通过添加以下代码来覆盖它以执行正确的操作:
pg.types.setTypeParser(1114, function(stringValue)
console.log(stringValue);
return new Date(Date.parse(stringValue + "+0000"));
)
【讨论】:
感谢您的回答。我也在 seqlize.js 文档中看到了这段代码。但是我应该在哪里写这个函数?弄糊涂了! 只需将它添加到你的 node.js 源文件的顶部——在你调用 pg.connect 之前 只是给其他人的说明,我想实现同样的目标,但我的日期/时间列的类型为TIMESTAMP
。使用上面的代码,其值为1184
,而不是工作以上是关于javascript + postgres:时区和时间戳的使用的主要内容,如果未能解决你的问题,请参考以下文章
Postgres中没有时区默认CURRENT_TIMESTAMP的字段TIMESTAMP的JPA模型类?