web-dev-qa-db-fra.com

Sqlite: CURRENT_TIMESTAMP est en GMT, pas le fuseau horaire de la machine

J'ai une table sqlite (v3) avec cette définition de colonne:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

Le serveur sur lequel réside cette base de données se trouve dans le fuseau horaire CST. Lorsque j'insère dans ma table sans inclure la colonne timestamp, sqlite remplit automatiquement ce champ avec l'horodatage actuel au format GMT, et non pas CST.

Existe-t-il un moyen de modifier mon instruction insert pour forcer l'horodatage stocké à être dans CST? D’autre part, il est probablement préférable de le stocker au format GMT (au cas où la base de données serait déplacée vers un fuseau horaire différent, par exemple). l'extraire de la table?

112
BrianH

J'ai trouvé dans la documentation de sqlite ( https://www.sqlite.org/lang_datefunc.html ) ce texte:

Calculez la date et l'heure en fonction de l'horodatage Unix 1092941466 et corrigez le fuseau horaire local.

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

Cela ne semblait pas répondre à mes besoins, alors j'ai essayé de modifier un peu la fonction "datetime", et je me suis retrouvé avec ceci:

select datetime(timestamp, 'localtime')

Cela semble fonctionner - est-ce la bonne façon de convertir votre fuseau horaire ou y a-t-il une meilleure façon de le faire?

136
BrianH

utilisez simplement l'heure locale par défaut:

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

En règle générale, vous devez laisser des horodatages dans la base de données GMT et les convertir uniquement en heure locale/en heure locale en entrée/sortie, lorsque vous pouvez les convertir en horodatage local de l'utilisateur (et non du serveur).

Ce serait bien si vous pouviez faire ce qui suit:

SELECT DATETIME(col, 'PDT')

... pour afficher l'horodatage d'un utilisateur à l'heure avancée du Pacifique. Malheureusement, ça ne marche pas. Selon ce tutoriel SQLite , cependant (faites défiler jusqu'à "Autres commandes de date et heure"), vous pouvez demander l'heure, puis appliquer un décalage (en heures) en même temps. Donc, si vous connaissez le décalage horaire du fuseau horaire de l'utilisateur, tout va bien.

Ne traite pas des règles de l'heure d'été, cependant ...

14
Roger Lipscombe

Dans le cas (admis, très rare) où une heure locale est souhaitée (par exemple, je stocke l'heure locale dans une de mes bases de données, car tout ce qui m'importe est l'heure de la journée et je ne garde pas trace de l'endroit où j'étais. en termes de fuseaux horaires ...), vous pouvez définir la colonne comme

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

Le% Y-% m-% dT% H:% M est bien entendu facultatif; c'est juste comme j'aime que mon temps soit stocké. [De plus, si mon impression est correcte, il n'y a pas de type de données "DATETIME" dans sqlite, donc peu importe que TEXT ou DATETIME soit utilisé comme type de données dans la déclaration de colonne.]

13
polyglot

Lorsqu’une colonne est définie avec "NOT NULL DEFAULT CURRENT_TIMESTAMP, "les enregistrements insérés seront toujours définis avec l’heure UTC/GMT.

Voici ce que j'ai fait pour ne pas avoir à inclure l'heure dans mes instructions 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

Testez pour voir si ça marche ...

--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

J'espère que ça t'as aidé.

8
Patrick
SELECT datetime('now', 'localtime');
7
liquide

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

5
Jens A. Koch

Vous pouvez également simplement convertir la colonne time en un horodatage en utilisant strftime ():

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

Vous donne:

1454521888

La colonne de table 'timestamp' peut être même un champ de texte, en utilisant le current_timestamp par défaut.

Sans strftime:

SELECT timestamp FROM ... ;

Vous donne:

2016-02-03 17:51:28

4
danger89

Je pense que cela pourrait aider.

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

L'heure actuelle, dans le fuseau horaire de votre machine:

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

Selon http://www.sqlite.org/lang_datefunc.html

2
Joseph

Time ( 'now', 'localtime' ) et date ( 'now', 'localtime' ) travaux.

1
Julian