Sqlite: CURRENT_TIMESTAMP в GMT, а не в часовом поясе машины - PullRequest
111 голосов
/ 19 декабря 2008

У меня есть таблица sqlite (v3) с определением этого столбца:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

Сервер, на котором живет эта база данных, находится в часовом поясе CST. Когда я вставляю в свою таблицу, не включая столбец метки времени, sqlite автоматически заполняет это поле текущей меткой времени в GMT, а не в CST.

Есть ли способ изменить мой оператор вставки, чтобы сохранить сохраненную метку времени в CST? С другой стороны, вероятно, лучше хранить его в GMT (например, в случае, если база данных будет перемещена в другой часовой пояс), поэтому есть ли способ изменить мой выбор SQL, чтобы преобразовать сохраненную временную метку в CST, когда я извлечь его из таблицы?

Ответы [ 11 ]

134 голосов
/ 19 декабря 2008

Я нашел в документации sqlite (https://www.sqlite.org/lang_datefunc.html) этот текст:

Вычислить дату и время с учетом Unix отметка времени 1092941466 и компенсировать для вашего местного часового пояса.

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

Это не выглядело так, как будто это соответствовало моим потребностям, поэтому я попытался немного изменить функцию "datetime" и в итоге получил следующее:

select datetime(timestamp, 'localtime')

Кажется, это работает - это правильный способ конвертации для вашего часового пояса или есть лучший способ сделать это?

59 голосов
/ 30 мая 2010

просто используйте местное время по умолчанию:

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);
14 голосов
/ 19 декабря 2008

Как правило, вы должны оставлять временные метки в базе данных в GMT и конвертировать их в / из местного времени при вводе / выводе, только когда вы можете конвертировать их в локальную временную метку пользователя (не сервера).

Было бы неплохо, если бы вы могли сделать следующее:

SELECT DATETIME(col, 'PDT')

... для вывода метки времени для пользователя по тихоокеанскому летнему времени. К сожалению, это не работает. Однако в соответствии с этим руководством по SQLite (прокрутите вниз до «Другие команды даты и времени»), вы можете запросить время, а затем одновременно применить смещение (в часах). Так что, если вы знаете смещение часового пояса пользователя, все в порядке.

Хотя правила летнего времени не применяются ...

13 голосов
/ 21 февраля 2009

В (признанном редком) случае, когда требуется локальное время данных (я, например, храню местное время в одной из моих баз данных, так как все, что меня волнует, это то, какое было время дня, и я не отслеживаю где я был в терминах часовых поясов ...), вы можете определить столбец как

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

Часть% Y-% m-% dT% H:% M, конечно, необязательна; Просто мне нравится, когда мое время хранится. [Кроме того, если мое представление верно, в sqlite нет типа данных "DATETIME", поэтому не имеет значения, используется ли TEXT или DATETIME в качестве типа данных в объявлении столбца.]

8 голосов
/ 11 августа 2009

Если столбец определен как «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

Надеюсь, это поможет.

7 голосов
/ 16 января 2014
SELECT datetime('now', 'localtime');
5 голосов
/ 22 апреля 2015

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

4 голосов
/ 03 февраля 2016

Вы также можете просто преобразовать столбец времени в метку времени, используя strftime ():

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

Дает вам:

1454521888

Столбец таблицы 'timestamp' может быть даже текстовым полем, используя current_timestamp как DEFAULT.

Без указания времени:

SELECT timestamp FROM ... ;

Дает вам:

2016-02-03 17: 51: 28

3 голосов
/ 21 февраля 2009

Я думаю, что это может помочь.

SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');
2 голосов
/ 14 ноября 2012

Текущее время в часовом поясе вашей машины:

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

Согласно http://www.sqlite.org/lang_datefunc.html

...