Sqlite:当前时间戳以GMT为单位,而不是机器的时区

Sqlite:当前时间戳以GMT为单位,而不是机器的时区,sql,sqlite,timezone,timestamp,Sql,Sqlite,Timezone,Timestamp,我有一个具有以下列定义的sqlite(v3)表: "timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP 此数据库所在的服务器位于CST时区。当我在不包含timestamp列的情况下插入到表中时,sqlite会自动使用GMT(而不是CST)中的当前时间戳填充该字段 有没有办法修改我的insert语句以强制存储的时间戳在CST中?另一方面,最好将其存储在GMT中(例如,如果数据库移动到不同的时区),那么有没有一种方法可以在我从表中提取时修改select SQ

我有一个具有以下列定义的sqlite(v3)表:

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


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

我在sqlite文档()中找到了以下文本:

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

这看起来不符合我的需要,因此我尝试稍微更改“datetime”函数,最后得出以下结论:

select datetime(timestamp, 'localtime')

这似乎有效-这是转换时区的正确方法,还是有更好的方法?

通常,您应该在数据库中以GMT为单位保留时间戳,并且仅在输入/输出时将其转换为本地时间,而您可以将其转换为用户(而不是服务器)的本地时间戳

如果您能做到以下几点,那就太好了:

SELECT DATETIME(col, 'PDT')
…在太平洋夏令时为用户输出时间戳。不幸的是,这不起作用。但是,根据(向下滚动至“其他日期和时间命令”),您可以询问时间,然后同时应用偏移量(以小时为单位)。所以,如果你知道用户的时区偏移量,你就很好了


不涉及夏令时规则,不过…

我认为这可能会有所帮助

SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');
在需要本地数据时间的情况下(非常罕见)(例如,我将本地时间存储在我的一个数据库中,因为我关心的是一天中的时间,而我不跟踪时区中我所在的位置…),您可以将该列定义为

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

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

当使用“
非空默认当前时间戳”定义列时,插入的记录将始终使用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

希望有帮助。

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

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

机器时区中的当前时间:

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

根据

时间('now','localtime')
和日期('now','localtime')
工作。

选择日期时间(当前时间戳,'localtime')
您也可以使用strftime()将时间列转换为时间戳:

给你:

1454521888

“timestamp”表列甚至可以是文本字段,使用
current\u timestamp
作为默认值

没有strftime:

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

2016-02-03 17:51:28


这确实存在不能跨时区传输的问题,但是,不是吗?是的,它对我也不起作用,我正在使用sqliteZF2@iconoclast如果您意识到这一点,并且如果它使您的实现更容易,那么它应该不会有危险,是吗?如果我只需要将本地时区存储到数据库中,并且我知道我的应用程序永远不会需要其他方式,那么我会这样做。@xFighter我知道我的应用程序永远不会需要其他方式。。。除非您忘记了这一点,或者其他人正在使用它。请注意这一点-SQLite3将默认将日期时间值存储为简单的整数Unix时间戳,而不包含其他时区信息。如果与localtime结合使用,sqlite将简单地增加/减少此数字,并有效地保存错误的时间戳(因为它不会表示自unix时间开始以来的秒数)-并且使用其他locale设置与客户端连接将显示错误的时间,没有简单的纠正方法。以UTC格式存储时间戳被认为是最佳做法。显示时转换为本地时间。POSIX将时间戳定义为UTC:不确定其他类型的数据库是否会遇到此类问题。你可以想象,如果你在日本创建一个数据库,你可以使用英国的数据!对于退欧时期;选择strftime(“%s”、“now”、“localtime”);sqlite localtime在时间戳和最终用户不直接通过BI工具使用数据的应用程序中可能不那么重要。但是,需要使用localtime来存储所有特定于应用程序的日期,例如生日。如果使用DATETIME Sqlite,则会在内部将该值存储为整数,这可能会对查询性能产生很大影响,行大小和缓存如果datetime值是64位整数而不是20字节字符串,这与用户hoju提供的答案不同,请创建表(..timestamp DATE DEFAULT(datetime('now','localtime')),);?
SELECT strftime('%s', timestamp) as timestamp FROM ... ;
SELECT timestamp FROM ... ;