Bạn đã khẳng định rằng:
Vì vậy, bạn không bao giờ vượt qua đường dữ liệu trong cùng một hàng. Tôi khuyên bạn nên lưu 1x date
3x time
và múi giờ (dưới dạng text
hoặc cột FK):
CREATE TABLE legacy_table (
event_id bigint PRIMARY KEY NOT NULL
, report_date date NOT NULL
, start_hour time
, end_hour time
, expected_hour time
, tz text -- time zone
);
Giống như bạn đã tìm thấy, timetz
(time with time zone
) thường nên tránh
. Nó không thể xử lý đúng các quy tắc DST ( d aylight s aving t ime).
Vì vậy, về cơ bản những gì bạn đã có . Chỉ cần bỏ thành phần ngày tháng khỏi start_hour
, đó là cước phí chết. Truyền timestamp
đến time
để cắt bỏ ngày tháng. Như:(timestamp '2018-03-25 1:00:00')::time
tz
có thể là bất kỳ chuỗi nào được chấp nhận bởi AT TIME ZONE
nhưng để xử lý các múi giờ khác nhau một cách đáng tin cậy, tốt nhất bạn nên sử dụng riêng tên múi giờ. Bất kỳ name
nào bạn tìm thấy trong danh mục hệ thống pg_timezone_names
.
Để tối ưu hóa dung lượng, bạn có thể thu thập các tên múi giờ được phép trong một bảng tra cứu nhỏ và thay thế bằng tz text
với tz_id int REFERENCES my_tz_table
.
Hai hàng mẫu có và không có DST:
INSERT INTO legacy_table VALUES
(1, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Vienna') -- sadly, with DST
, (2, '2018-03-25', '1:00', '3:00', '2:00', 'Europe/Moscow'); -- Russians got rid of DST
Đối với mục đích biểu diễn hoặc tính toán, bạn có thể làm những việc như:
SELECT (report_date + start_hour) AT TIME ZONE tz AT TIME ZONE 'UTC' AS start_utc
, (report_date + end_hour) AT TIME ZONE tz AT TIME ZONE 'UTC' AS end_utc
, (report_date + expected_hour) AT TIME ZONE tz AT TIME ZONE 'UTC' AS expected_utc
-- START_HOUR - END_HOUR
, (report_date + start_hour) AT TIME ZONE tz
- (report_date + end_hour) AT TIME ZONE tz AS start_minus_end
FROM legacy_table;
Bạn có thể tạo một hoặc nhiều chế độ xem để dễ dàng hiển thị các chuỗi khi cần thiết. Bảng dùng để lưu trữ thông tin bạn cần .
Lưu ý dấu ngoặc đơn! Khác toán tử +
sẽ ràng buộc trước AT TIME ZONE
do ưu tiên toán tử
.
Và hãy xem kết quả:
db <> fiddle tại đây
Vì thời gian được điều chỉnh ở Vienna (giống như bất kỳ nơi nào áp dụng các quy tắc DST ngớ ngẩn), bạn sẽ nhận được kết quả "đáng ngạc nhiên".
Có liên quan:
- Tính toán DST trong Postgres, khi chọn các mục đã lên lịch
- Bỏ qua thời gian các vùng hoàn toàn trong Rails và PostgreSQL