web-dev-qa-db-ja.com

Sqlite:CURRENT_TIMESTAMPはGMTであり、マシンのタイムゾーンではありません

この列定義を持つsqlite(v3)テーブルがあります。

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

このデータベースが存在するサーバーは、CSTタイムゾーンにあります。タイムスタンプ列を含めずにテーブルに挿入すると、sqliteは自動的にそのフィールドにCSTではなくGMTの現在のタイムスタンプを入力します。

挿入ステートメントを変更して、保存されたタイムスタンプを強制的にCSTにする方法はありますか?一方、データベースを別のタイムゾーンに移動する場合などにGMTに保存する方がおそらくよいので、選択したSQLを変更して、保存したタイムスタンプをCSTに変換する方法がありますテーブルから抽出しますか?

112
BrianH

私はsqliteのドキュメント( https://www.sqlite.org/lang_datefunc.html )でこのテキストを見つけました:

UNIXタイムスタンプ1092941466を指定して日付と時刻を計算し、ローカルタイムゾーンを補正します。

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

それは私のニーズに合わないように見えたので、「datetime」関数を少し変更してみましたが、これで終わりました:

select datetime(timestamp, 'localtime')

それはうまくいくようです-それはあなたのタイムゾーンに変換する正しい方法ですか、これを行うより良い方法はありますか?

136
BrianH

デフォルトとして現地時間を使用するだけです:

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

原則として、タイムスタンプをGMTでデータベースに残し、ユーザーの(サーバーのではなく)ローカルタイムスタンプに変換できる場合は、入力/出力のローカル時間のみに変換する必要があります。

次のことができるといいですね。

SELECT DATETIME(col, 'PDT')

...太平洋夏時間のユーザーのタイムスタンプを出力します。残念ながら、それは機能しません。 このSQLiteチュートリアル によると(ただし、「その他の日付と時刻のコマンド」までスクロールダウン)、時刻を確認してから、オフセット(時間単位)を同時に適用できます。そのため、ユーザーのタイムゾーンオフセットがわかっている場合は、問題ありません。

ただし、夏時間の規則は扱いません...

14
Roger Lipscombe

(まれに認められる)現地のデータ時刻が必要な場合(たとえば、データベースの1つに現地時刻を格納するのは、1日の時刻が何であるかだけで、自分がどこにいたかを追跡しないためです)タイムゾーンの観点から...)、次のように列を定義できます

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

もちろん、%Y-%m-%dT%H:%Mの部分はオプションです。それは私の時間を保存するのが好きな方法です。 [また、私の印象が正しければ、sqliteには「DATETIME」データ型がないため、列宣言でTEXTまたはDATETIMEがデータ型として使用されるかどうかは実際には関係ありません。

13
polyglot

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

お役に立てば幸いです。

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

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

5
Jens A. Koch

Strftime()を使用して、時間列をタイムスタンプに変換することもできます。

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

あなたにあげる:

1454521888

'timestamp'テーブル列は、デフォルトとしてcurrent_timestampを使用して、テキストフィールドにすることもできます。

Strftimeなし:

SELECT timestamp FROM ... ;

あなたにあげる:

2016-02-03 17:51:28

4
danger89

これが役立つと思います。

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

マシンのタイムゾーンでの現在の時間:

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

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

2
Joseph

Time ( 'now', 'localtime' )およびDate ( 'now', 'localtime' )は機能します。

1
Julian