Sqlite: CURRENT_TIMESTAMP в GMT, а не в часовом поясе машины

97

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

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

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

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

  • 20
    Хранение меток времени в UTC считается лучшей практикой. Преобразовать в местное время при их представлении .
  • 1
    POSIX определяет временные метки как UTC: stackoverflow.com/a/34107910/895245
Теги:
timestamp
timezone

11 ответов

113
Лучший ответ

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

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

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

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

select datetime(timestamp, 'localtime')

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

  • 8
    Это правильный способ конвертировать временные метки в местное время в SQLite.
  • 2
    второй был идеальным решением, спасибо.
Показать ещё 2 комментария
51

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

CREATE TABLE whatever(
     ....
     timestamp DATE DEFAULT (datetime('now','localtime')),
     ...
);
  • 4
    Однако проблема заключается в том, что она не может передаваться через часовые пояса, не так ли?
  • 2
    Полезно знать, но это кажется опасной практикой ...
Показать ещё 4 комментария
13

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

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

SELECT DATETIME(col, 'PDT')

... для вывода метки времени для пользователя в режиме Pacific Daylight Time. К сожалению, это не сработает. В соответствии с этот учебник по SQLite (прокрутите вниз до "Другие команды даты и времени" ), вы можете запросить время, а затем применить смещение (в часах) в одно и то же время. Итак, если вы знаете смещение часового пояса пользователя, вы хорошо.

Не соблюдает правила летнего времени, хотя...

  • 1
    О, это было бы удобно! Я попытался использовать 'PDT' и 'PST', но он вернул нули. Видимо, это не доступно в sqlite.
12

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

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

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

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

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

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

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

2

Текущее время в часовом поясе вашего компьютера:

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

По http://www.sqlite.org/lang_datefunc.html

2

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

SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');
  • 0
    для unxitime; SELECT strftime ('% s', 'now', 'localtime');
1

Time ( 'now', 'localtime' ) и дата ( 'now', 'localtime' ).

0

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

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

Дает вам:

1454521888

Столбец таблицы

'timestamp' может быть текстовым полем даже с использованием current_timestamp как DEFAULT.

Без strftime:

SELECT timestamp FROM ... ;

Дает вам:

2016-02-03 17:51:28

Ещё вопросы

Сообщество Overcoder
Наверх
Меню