Sqlite: CURRENT_TIMESTAMP è in GMT, non nel fuso orario della macchina


118

Ho una tabella sqlite (v3) con questa definizione di colonna:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

Il server su cui risiede questo database si trova nel fuso orario CST. Quando inserisco nella mia tabella senza includere la colonna timestamp, sqlite popola automaticamente quel campo con il timestamp corrente in GMT, non CST.

C'è un modo per modificare la mia istruzione di inserimento per forzare il timestamp memorizzato in CST? D'altra parte, probabilmente è meglio memorizzarlo in GMT (nel caso in cui il database venga spostato in un fuso orario diverso, ad esempio), quindi c'è un modo per modificare il mio SQL selezionato per convertire il timestamp memorizzato in CST quando ho estrarlo dal tavolo?


24
La memorizzazione dei timestamp in UTC è considerata la migliore pratica. Converti in ora locale durante la presentazione .
csl


1
Non sono sicuro che questo tipo di problema affronti altri tipi di database. Immagina che se crei un database in Giappone, potresti utilizzare i dati nel Regno Unito!
NoChance

Risposte:


145

Ho trovato nella documentazione di sqlite ( https://www.sqlite.org/lang_datefunc.html ) questo testo:

Calcola la data e l'ora con un timestamp unix 1092941466 e compensa il fuso orario locale.

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

Sembrava che non si adattasse alle mie esigenze, quindi ho provato a cambiare un po 'la funzione "datetime" e ho concluso con questo:

select datetime(timestamp, 'localtime')

Sembra funzionare: è il modo corretto di convertire per il tuo fuso orario o c'è un modo migliore per farlo?


64

usa semplicemente l'ora locale come impostazione predefinita:

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

5
Questo ha il problema di non essere trasferibile su fusi orari, no?
Vadim Peretokin

sì, lo è, non funziona neanche per me, sto usando sqlite in ZF2
Rohutech

@iconoclast non dovrebbe essere pericoloso dove se ne sei consapevole e se rende più facile la tua implementazione, giusto? se questo è ciò di cui ho bisogno solo per memorizzare il fuso orario locale nel database e so che la mia applicazione non avrà mai bisogno di un altro modo, allora lo farò.
Ahad

1
@xFighter So che la mia applicazione non avrà mai bisogno di un altro modo ... Fino a quando non te ne dimentichi o qualcun altro lo sta usando.
MKesper

16

Di norma, dovresti lasciare i timestamp nel database in GMT e convertirli in / dall'ora locale su input / output, quando puoi convertirli nel timestamp locale dell'utente (non del server).

Sarebbe bello se potessi fare quanto segue:

SELECT DATETIME(col, 'PDT')

... per generare il timestamp per un utente in Pacific Daylight Time. Sfortunatamente, non funziona. Secondo questo tutorial SQLite , tuttavia (scorri verso il basso fino a "Altri comandi di data e ora"), puoi chiedere l'ora e quindi applicare un offset (in ore) allo stesso tempo. Quindi, se conosci la differenza di fuso orario dell'utente, sei a posto.

Non si occupa delle regole dell'ora legale, però ...


15

Nel caso (ammesso raro) che si desideri un datatime locale (io, ad esempio, memorizzo l'ora locale in uno dei miei database poiché tutto ciò che mi interessa è che ora è stata del giorno e non tengo traccia di dove mi trovavo in termini di fusi orari ...), è possibile definire la colonna come

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

La parte% Y-% m-% dT% H:% M è ovviamente facoltativa; è proprio come mi piace che il mio tempo venga immagazzinato. [Inoltre, se la mia impressione è corretta, non esiste alcun tipo di dati "DATETIME" in sqlite, quindi non importa se TEXT o DATETIME viene utilizzato come tipo di dati nella dichiarazione di colonna.]


sqlite localtime può essere meno importante nei timestamp e nelle applicazioni in cui l'utente finale non utilizza i dati direttamente tramite uno strumento BI. Tuttavia, l'ora locale è ciò di cui hai bisogno per memorizzare tutte le date specifiche dell'applicazione come la data di nascita.
NoChance

9

Quando si ha una colonna definita con " NOT NULL DEFAULT CURRENT_TIMESTAMP," i record inseriti verranno sempre impostati con l'ora UTC / GMT.

Ecco cosa ho fatto per evitare di dover includere l'ora nelle mie istruzioni 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

Prova per vedere se funziona ...

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

Spero che aiuti.


1
È diverso dalla risposta fornita dall'utente hoju, CREATE TABLE qualunque (.... timestamp DATE DEFAULT (datetime ('now', 'localtime')),.) ;?
NoChance



4

Puoi anche convertire la colonna del tempo in un timestamp usando strftime ():

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

Ti dà:

1454521888

La colonna della tabella "timestamp" può essere anche un campo di testo, utilizzando current_timestampcome DEFAULT.

Senza strftime:

SELECT timestamp FROM ... ;

Ti dà:

03-02-2016 17:51:28


3

Penso che questo potrebbe aiutare.

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

per non marittimo; SELEZIONA strftime ('% s', 'now', 'localtime');
PodTech.io


1

Time ( 'now', 'localtime' )e la data ( 'now', 'localtime' )funziona.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.