Sqlite:CURRENT_TIMESTAMP是GMT,而不是机器的时区

时间:2008-12-19 15:53:33

标签: sql sqlite timezone timestamp

我有一个带有此列定义的sqlite(v3)表:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

此数据库所在的服务器位于CST时区。当我在不包含timestamp列的情况下插入到我的表中时,sqlite会自动使用GMT中的当前时间戳填充该字段,而不是CST。

有没有办法修改我的insert语句以强制存储的时间戳在CST中?另一方面,最好将它存储在GMT中(例如,如果数据库被移动到不同的时区),那么我是否可以修改我的选择SQL以将存储的时间戳转换为CST从表中提取它?

11 个答案:

答案 0 :(得分:134)

我在sqlite文档(https://www.sqlite.org/lang_datefunc.html)上找到了这个文本:

  

计算给定unix的日期和时间   时间戳1092941466,并补偿   为您当地的时区。

SELECT datetime(1092941466, 'unixepoch', 'localtime');

这看起来不符合我的需要,所以我试着改变一下“datetime”功能,结果就是这样:

select datetime(timestamp, 'localtime')

这似乎有效 - 这是转换为您的时区的正确方法,还是有更好的方法来做到这一点?

答案 1 :(得分:59)

只需使用当地时间作为默认值:

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);

答案 2 :(得分:14)

作为一项规则,您应该在GMT中将时间戳保留在数据库中,并且只能在输入/输出时将它们转换为本地时间/从本地时间转换,当您可以将它们转换为用户(而不是服务器)的本地时间戳时。

如果你能做到以下几点会很好:

SELECT DATETIME(col, 'PDT')

...在Pacific Daylight Time输出用户的时间戳。不幸的是,这不起作用。但是,根据this SQLite tutorial(向下滚动到“其他日期和时间命令”),您可以询问时间,然后同时应用偏移量(以小时为单位)。所以,如果你确实知道用户的时区偏移量,那就很好了。

不处理夏令时规则,但是......

答案 3 :(得分:13)

在(很少见的)需要本地数据时间的情况下(例如,我将当地时间存储在我的一个数据库中,因为我关心的是当天的时间,而且我没有跟踪在我所处的时区......)中,您可以将列定义为

"timestamp" TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M','now', 'localtime'))

%Y-%m-%dT%H:%M部分当然是可选的;这就是我喜欢存储时间的方式。 [另外,如果我的印象是正确的,sqlite中没有“DATETIME”数据类型,因此在列声明中是否将TEXT或DATETIME用作数据类型并不重要。]

答案 4 :(得分:8)

如果列中定义了“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

希望有所帮助。

答案 5 :(得分:7)

SELECT datetime('now', 'localtime');

答案 6 :(得分:5)

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

答案 7 :(得分:4)

您还可以使用strftime()将时间列转换为时间戳:

SELECT strftime('%s', timestamp) as timestamp FROM ... ;

给你:

  

1454521888

'timestamp'表格列甚至可以是文本字段,使用current_timestamp作为默认值。

没有strftime:

SELECT timestamp FROM ... ;

给你:

  

2016-02-03 17:51:28

答案 8 :(得分:3)

我认为这可能会有所帮助。

SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');

答案 9 :(得分:2)

当前时间,在您机器的时区:

select time(time(), 'localtime');

根据http://www.sqlite.org/lang_datefunc.html

答案 10 :(得分:1)

Time ( 'now', 'localtime' )和日期( 'now', 'localtime' )有效。