Sqlite: CURRENT_TIMESTAMP GMT'de, makinenin saat diliminde değil


118

Bu sütun tanımına sahip bir sqlite (v3) tablom var:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

Bu veritabanının üzerinde yaşadığı sunucu CST saat dilimindedir. Zaman damgası sütununu eklemeden tabloma eklediğimde, sqlite bu alanı CST'de değil, GMT'deki geçerli zaman damgasıyla otomatik olarak dolduruyor.

Saklanan zaman damgasını CST'de olmaya zorlamak için insert deyimimi değiştirmenin bir yolu var mı? Öte yandan, muhtemelen GMT'de saklamak daha iyidir (örneğin, veritabanının farklı bir saat dilimine taşınması durumunda), bu nedenle, depolanan zaman damgasını CST'ye dönüştürmek için seçtiğim SQL'i değiştirmenin bir yolu var mı? masadan çıkarmak mı?


24
Zaman damgalarının UTC'de saklanması en iyi uygulama olarak kabul edilir. Bunları sunarken yerel saate dönüştürün .
csl


1
Bu tür bir sorunun diğer veri tabanı türleriyle karşılaşıp karşılaşmadığından emin değilim. Japonya'da bir veritabanı oluşturursanız, verileri İngiltere'deki kullanabileceğinizi hayal edersiniz!
NoChance

Yanıtlar:


145

Sqlite belgelerinde ( https://www.sqlite.org/lang_datefunc.html ) bu metni buldum :

Bir unix zaman damgası 1092941466 verilen tarih ve saati hesaplayın ve yerel saat diliminizi dengeleyin.

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

Bu ihtiyaçlarıma uyuyor gibi görünmedi, bu yüzden "tarihsaat" işlevini biraz değiştirmeyi denedim ve şununla son buldum:

select datetime(timestamp, 'localtime')

Bu işe yarıyor gibi görünüyor - saat diliminiz için dönüştürme yapmanın doğru yolu bu mu yoksa bunu yapmanın daha iyi bir yolu var mı?


64

varsayılan olarak yerel saati kullanın:

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

5
Ancak bunun zaman dilimleri arasında aktarılamama sorunu var, değil mi?
Vadim Peretokin

evet, benim için de çalışmıyor, ZF2'de sqlite kullanıyorum
Rohutech

@iconoclast, bunun farkındaysanız ve uygulamanızı kolaylaştıracaksa tehlikeli olmamalı mı? eğer sadece yerel saat dilimini veri tabanına kaydetmem için ihtiyacım varsa ve uygulamamın asla başka bir yola ihtiyaç duymayacağını biliyorsam, o zaman yapacağım.
Ahad

1
@xFighter Uygulamamın asla başka bir yola ihtiyaç duymayacağını biliyorum ... Bunu unutana kadar veya başka biri onu kullanana kadar.
MKesper

16

Kural olarak, GMT'de veritabanında zaman damgaları bırakmalı ve bunları kullanıcının (sunucunun değil) yerel zaman damgasına dönüştürebileceğiniz zaman, yalnızca giriş / çıkışta yerel saate / yerel saate dönüştürmelisiniz.

Aşağıdakileri yaparsanız iyi olur:

SELECT DATETIME(col, 'PDT')

... Pasifik Yaz Saati'nde bir kullanıcı için zaman damgasını çıkarmak için. Maalesef bu işe yaramıyor. Bununla birlikte, bu SQLite öğreticisine göre ("Diğer Tarih ve Saat Komutları" na gidin), saati sorabilir ve ardından aynı anda bir fark (saat olarak) uygulayabilirsiniz. Öyleyse, kullanıcının zaman dilimi farkını biliyorsanız, iyisinizdir.

Yine de gün ışığından yararlanma kurallarıyla ilgilenmiyor ...


15

Yerel bir veri saatinin istendiği (kabul edilen nadir) durumda (örneğin, yerel saati veritabanımdan birinde saklıyorum çünkü tek umursadığım şey günün saatinin ne olduğudur ve nerede olduğumu takip etmiyorum zaman dilimleri açısından ...), sütunu şu şekilde tanımlayabilirsiniz:

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

% Y-% m-% dT% H:% M kısmı elbette isteğe bağlıdır; tam da zamanımın saklanmasını seviyorum. [Ayrıca, gösterimim doğruysa, sqlite'da "DATETIME" veri türü yoktur, bu nedenle sütun bildiriminde veri türü olarak TEXT veya DATETIME kullanılıp kullanılmadığı gerçekten önemli değildir.]


sqlite localtime, zaman damgalarında ve son kullanıcının verileri doğrudan bir BI aracı aracılığıyla kullanmadığı uygulamalarda daha az önemli olabilir. Ancak yerel zaman, doğum tarihi gibi uygulamaya özel tüm tarihleri ​​saklamak için kullanmanız gereken şeydir.
NoChance

9

" NOT NULL DEFAULT CURRENT_TIMESTAMP" İle tanımlanan bir sütun olduğunda , eklenen kayıtlar her zaman UTC / GMT saatine göre ayarlanır.

INSERT / UPDATE ifadelerime zamanı dahil etmek zorunda kalmamak için şunları yaptım:

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

Çalışıp çalışmadığını test edin ...

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

Umarım yardımcı olur.


1
Bu, kullanıcı hoju tarafından sağlanan cevaptan farklı mı, CREATE TABLE ne olursa olsun (.... timestamp DATE DEFAULT (datetime ('şimdi', 'localtime')),.) ;?
NoChance



4

Strftime () kullanarak zaman sütununu bir zaman damgasına da dönüştürebilirsiniz:

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

Sana verir:

1454521888

'zaman damgası' tablo sütunu, current_timestampVARSAYILAN olarak kullanıldığında bile bir metin alanı olabilir .

Strftime olmadan:

SELECT timestamp FROM ... ;

Sana verir:

2016-02-03 17:51:28


3

Bunun yardımcı olabileceğini düşünüyorum.

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

boş zaman için; SELECT strftime ('% s', 'şimdi', 'localtime');
PodTech.io


1

Time ( 'now', 'localtime' )ve Tarih ( 'now', 'localtime' )çalışır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.