我有一个带有此列定义的 sqlite (v3) 表:
"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP
该数据库所在的服务器位于 CST 时区。当我插入表而不包含时间戳列时,sqlite 会自动使用 GMT(而不是 CST)中的当前时间戳填充该字段。
有没有办法修改我的插入语句以强制存储的时间戳采用 CST?另一方面,最好将其存储在 GMT 中(例如,以防数据库移动到不同的时区),所以有没有办法可以修改我的选择 SQL 以将存储的时间戳转换为 CST从表中提取它?
我在 sqlite 文档(https://www.sqlite.org/lang_datefunc.html)中找到了这段文字:
计算给定unix的日期和时间 时间戳1092941466,并补偿 您当地的时区。
SELECT datetime(1092941466, 'unixepoch', 'localtime');
这看起来不符合我的需求,所以我尝试稍微改变一下“日期时间”函数,最后得到这个:
SELECT datetime(timestamp, 'localtime')
这似乎有效 - 这是转换时区的正确方法,还是有更好的方法?
只需使用当地时间作为默认值:
CREATE TABLE whatever(
....
timestamp DATE DEFAULT (datetime('now','localtime')),
...
);
通常,您应该在数据库中保留 GMT 时间戳,并且仅当您可以将它们转换为用户(而不是服务器)的本地时间戳时,才在输入/输出时将它们转换为本地时间/从本地时间转换。
如果您能做到以下几点那就太好了:
SELECT DATETIME(col, 'PDT')
...输出太平洋夏令时用户的时间戳。不幸的是,这不起作用。然而,根据这个 SQLite 教程(向下滚动到“其他日期和时间命令”),您可以询问时间,然后同时应用偏移量(以小时为单位)。因此,如果您确实知道用户的时区偏移量,那就很好了。
但不涉及夏令时规则......
在(承认罕见)需要本地数据时间的情况下(例如,我将本地时间存储在我的一个数据库中,因为我关心的是一天中的时间,并且我不跟踪我在哪里)是根据时区...),您可以将列定义为
"timestamp" TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M','now', 'localtime'))
%Y-%m-%dT%H:%M 部分当然是可选的;这正是我喜欢的时间存储方式。 [另外,如果我的印象是正确的,sqlite 中没有“DATETIME”数据类型,因此在列声明中使用 TEXT 还是 DATETIME 作为数据类型并不重要。]
SELECT datetime(CURRENT_TIMESTAMP, 'localtime')
简而言之:CURRENT_TIMESTAMP 是 UTC 并转换为本地时间。
“本地时间”修饰符 (21) 假定其左侧的时间值是 世界协调时间 (UTC) 并调整该时间值,以便 这是当地时间。如果“localtime”后面的时间不是 UTC, 那么行为是未定义的。 “utc”修饰符与以下相反 “当地时间”。 “utc”假定其左侧的时间值位于 本地时区并将该时间值调整为 UTC。如果时间 左边不是本地时间,那么“utc”的结果是 不明确的。 -- 来源:https://www.sqlite.org/lang_datefunc.html#modifiers
当使用“
NOT NULL DEFAULT CURRENT_TIMESTAMP
”定义列时,插入的记录将始终使用 UTC/GMT 时间设置。
为了避免在 INSERT/UPDATE 语句中包含时间,我做了以下操作:
--Create a table having a CURRENT_TIMESTAMP:
CREATE TABLE FOOBAR (
RECORD_NO INTEGER NOT NULL,
TO_STORE INTEGER,
UPC CHAR(30),
QTY DECIMAL(15,4),
EID CHAR(16),
RECORD_TIME NOT NULL DEFAULT CURRENT_TIMESTAMP)
--Create before update and after insert triggers:
CREATE TRIGGER UPDATE_FOOBAR BEFORE UPDATE ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
CREATE TRIGGER INSERT_FOOBAR AFTER INSERT ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
测试一下是否有效...
--INSERT a couple records into the table:
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (0, 1, 'xyz1', 31, '777')
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (1, 1, 'xyz2', 32, '777')
--UPDATE one of the records:
UPDATE foobar SET price = 29 WHERE upc = 'xyz2'
--Check the results:
SELECT * FROM foobar
希望有帮助。
SELECT datetime('now', 'localtime');
Time ( 'now', 'localtime' )
和日期 ( 'now', 'localtime' )
有效。
您还可以使用 strftime() 将时间列转换为时间戳:
SELECT strftime('%s', timestamp) as timestamp FROM ... ;
给你:
1454521888
“时间戳”表列甚至可以是文本字段,使用
current_timestamp
作为默认值。
没有strftime:
SELECT timestamp FROM ... ;
给你:
2016-02-03 17:51:28
我认为这可能会有所帮助。
SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');