Sqlite: CURRENT_TIMESTAMP tính theo GMT, không phải múi giờ của máy


118

Tôi có một bảng sqlite (v3) với định nghĩa cột này:

"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP

Máy chủ mà cơ sở dữ liệu này sử dụng nằm trong múi giờ CST. Khi tôi chèn vào bảng của mình mà không bao gồm cột dấu thời gian, sqlite sẽ tự động điền trường đó với dấu thời gian hiện tại theo GMT, không phải CST.

Có cách nào để sửa đổi câu lệnh chèn của tôi để buộc dấu thời gian được lưu trữ trong CST không? Mặt khác, có lẽ tốt hơn nên lưu trữ nó theo GMT (ví dụ: trong trường hợp cơ sở dữ liệu được chuyển sang múi giờ khác), vì vậy có cách nào để tôi có thể sửa đổi SQL đã chọn của mình để chuyển đổi dấu thời gian được lưu trữ thành CST khi tôi giải nén nó khỏi bảng?


24
Lưu trữ dấu thời gian trong UTC được coi là phương pháp hay nhất. Chuyển đổi sang giờ địa phương khi trình bày chúng.
csl


1
Không chắc liệu loại rắc rối này có gặp phải các loại cơ sở dữ liệu khác hay không. Bạn sẽ tưởng tượng rằng nếu bạn tạo cơ sở dữ liệu ở Nhật Bản, bạn có thể sử dụng dữ liệu ở Vương quốc Anh!
NoChance

Câu trả lời:


145

Tôi tìm thấy trên tài liệu sqlite ( https://www.sqlite.org/lang_datefunc.html ) văn bản này:

Tính toán ngày và giờ cho dấu thời gian unix 1092941466 và bù cho múi giờ địa phương của bạn.

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

Điều đó có vẻ không phù hợp với nhu cầu của tôi, vì vậy tôi đã thử thay đổi một chút chức năng "datetime" và kết thúc với điều này:

select datetime(timestamp, 'localtime')

Điều đó có vẻ hiệu quả - đó có phải là cách chính xác để chuyển đổi cho múi giờ của bạn hay có cách nào tốt hơn để làm điều này?


64

chỉ cần sử dụng giờ địa phương làm mặc định:

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

5
Tuy nhiên, điều này có vấn đề là không thể chuyển đổi qua các múi giờ, phải không?
Vadim Peretokin

có nó là, nó không làm việc hoặc cho tôi, tôi đang sử dụng SQLite trong ZF2
Rohutech

@iconoclast sẽ không nguy hiểm nếu bạn nhận thức được điều này và nếu nó giúp việc triển khai của bạn dễ dàng hơn, có nên không? nếu đây là những gì tôi chỉ cần để lưu trữ múi giờ địa phương vào cơ sở dữ liệu và tôi biết ứng dụng của mình sẽ không bao giờ cần theo cách khác thì tôi sẽ làm.
Ahad

1
@xFighter Tôi biết ứng dụng của mình sẽ không bao giờ cần theo cách khác ... Cho đến khi bạn quên điều đó hoặc ai đó đang sử dụng nó.
MKesper

16

Theo quy định, bạn nên để dấu thời gian trong cơ sở dữ liệu theo GMT và chỉ chuyển đổi chúng thành / từ giờ địa phương trên đầu vào / đầu ra, khi bạn có thể chuyển đổi chúng thành dấu thời gian cục bộ của người dùng (không phải của máy chủ).

Sẽ thật tuyệt nếu bạn có thể làm như sau:

SELECT DATETIME(col, 'PDT')

... để xuất dấu thời gian cho người dùng vào Giờ ban ngày Thái Bình Dương. Thật không may, điều đó không hoạt động. Theo hướng dẫn SQLite này , tuy nhiên (di chuyển xuống "Ngày khác và Time Commands"), bạn có thể yêu cầu thời điểm đó, và sau đó áp dụng một offset (theo giờ) cùng một lúc. Vì vậy, nếu bạn biết chênh lệch múi giờ của người dùng, bạn tốt.

Tuy nhiên, không giải quyết các quy tắc tiết kiệm ánh sáng ban ngày ...


15

Trong trường hợp (hiếm khi được thừa nhận) là muốn có một số liệu cục bộ (ví dụ: tôi lưu trữ giờ địa phương vào một trong cơ sở dữ liệu của mình vì tất cả những gì tôi quan tâm là thời gian trong ngày là bao nhiêu và tôi không theo dõi được mình đã ở đâu. theo múi giờ ...), bạn có thể xác định cột là

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

Phần% Y-% m-% dT% H:% M tất nhiên là tùy chọn; nó chỉ là cách tôi muốn thời gian của mình được lưu trữ. [Ngoài ra, nếu ấn tượng của tôi là chính xác, không có kiểu dữ liệu "DATETIME" trong sqlite, vì vậy không thực sự quan trọng liệu TEXT hay DATETIME được sử dụng làm kiểu dữ liệu trong khai báo cột.]


sqlite localtime có thể ít quan trọng hơn trong tem thời gian và trong các ứng dụng mà người dùng cuối không sử dụng dữ liệu trực tiếp thông qua công cụ BI. Tuy nhiên, localtime là thứ bạn cần sử dụng để lưu trữ tất cả các ngày cụ thể của ứng dụng, chẳng hạn như ngày sinh.
NoChance

9

Khi có một cột được xác định bằng " NOT NULL DEFAULT CURRENT_TIMESTAMP," các bản ghi được chèn sẽ luôn được đặt theo giờ UTC / GMT.

Đây là những gì tôi đã làm để tránh phải đưa thời gian vào câu lệnh INSERT / UPDATE của mình:

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

Kiểm tra xem nó có hoạt động không ...

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

Hy vọng rằng sẽ giúp.


1
Điều này có khác với câu trả lời được cung cấp bởi người dùng hoju không, TẠO BẢNG bất cứ điều gì (.... dấu thời gian DATE DEFAULT (datetime ('now', 'localtime')),.);?
NoChance



4

Bạn cũng có thể chỉ cần chuyển đổi cột thời gian thành dấu thời gian bằng cách sử dụng strftime ():

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

Mang đến cho bạn:

1454521888

cột bảng 'dấu thời gian' có thể là một trường văn bản thậm chí, sử dụng current_timestampnhư DEFAULT.

Không có strftime:

SELECT timestamp FROM ... ;

Mang đến cho bạn:

2016-02-03 17:51:28


3

Tôi nghĩ điều này có thể hữu ích.

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

cho sự không nhạy cảm; SELECT strftime ('% s', 'now', 'localtime');
PodTech.io


1

Time ( 'now', 'localtime' )và Ngày tháng ( 'now', 'localtime' )hoạt động.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.