Sử dụng thời gian hiện tại trong UTC làm giá trị mặc định trong PostgreSQL


172

Tôi có một cột TIMESTAMP WITHOUT TIME ZONEloại và muốn có mặc định đó cho thời điểm hiện tại trong UTC. Có được thời gian hiện tại trong UTC thật dễ dàng:

postgres=# select now() at time zone 'utc';
          timezone          
----------------------------
 2013-05-17 12:52:51.337466
(1 row)

Như đang sử dụng dấu thời gian hiện tại cho một cột:

postgres=# create temporary table test(id int, ts timestamp without time zone default current_timestamp);
CREATE TABLE
postgres=# insert into test values (1) returning ts;
             ts             
----------------------------
 2013-05-17 14:54:33.072725
(1 row)

Nhưng điều đó sử dụng giờ địa phương. Cố gắng buộc UTC đó dẫn đến lỗi cú pháp:

postgres=# create temporary table test(id int, ts timestamp without time zone default now() at time zone 'utc');
ERROR:  syntax error at or near "at"
LINE 1: ...int, ts timestamp without time zone default now() at time zo...

Câu trả lời:


297

Một chức năng thậm chí không cần thiết. Chỉ cần đặt dấu ngoặc quanh biểu thức mặc định:

create temporary table test(
    id int, 
    ts timestamp without time zone default (now() at time zone 'utc')
);

2
Tôi có thể thấy một funciton như now_utc () thực sự tỏa sáng khi viết truy vấn
misaxi

Điều này thậm chí hoạt động khi thời gian quay trở lại một giờ - now () trả về dấu thời gian biết phần bù từ UTC.
Clay Lenhart

1
FWIW, chạy truy vấn này trong PostgreQuery 11,5: ALTER TABLE testcase_result ADD COLUMN date_created TIMESTAMP WITHOUT TIME ZONE DEFAULT (NOW() AT TIME ZONE "UTC") NOT NULL;không thành công với : ERROR: column "UTC" does not exist. Hãy chắc chắn 'utc'là tất cả các trường hợp thấp hơn.
code_dredd

2
Sửa chữa: 'utc' Chuỗi cũng phải được trích dẫn đơn, không được trích dẫn kép.
code_dredd

55

Vẫn còn một giải pháp khác:

timezone('utc', now())

26

Gói nó trong một chức năng:

create function now_utc() returns timestamp as $$
  select now() at time zone 'utc';
$$ language sql;

create temporary table test(
  id int,
  ts timestamp without time zone default now_utc()
);

16

Thế còn

now()::timestamp

Nếu dấu thời gian khác của bạn không có múi giờ thì diễn viên này sẽ mang lại loại "dấu thời gian không có múi giờ" phù hợp cho thời gian hiện tại.

Tuy nhiên, tôi muốn đọc những gì người khác nghĩ về lựa chọn đó. Tôi vẫn không tin tưởng vào sự hiểu biết của mình về công cụ múi giờ "có / không" này.

EDIT: Thêm nhận xét của Michael Ekoka ở đây vì nó làm rõ một điểm quan trọng:

Hãy cẩn thận. Câu hỏi là về việc tạo dấu thời gian mặc định trong UTC cho cột dấu thời gian xảy ra không lưu trữ múi giờ (có lẽ vì không cần lưu trữ múi giờ nếu bạn biết rằng tất cả dấu thời gian của bạn đều giống nhau). Giải pháp của bạn là tạo ra dấu thời gian cục bộ (mà hầu hết mọi người sẽ không nhất thiết phải được đặt thành UTC) và lưu trữ dưới dạng dấu thời gian ngây thơ (không xác định múi giờ của nó).


Đó là một mẹo thú vị nhưng nó có thể dẫn đến sự nhầm lẫn trừ khi bạn nhận thức được hành vi này. Câu trả lời được chấp nhận là rõ ràng về hành động và kết quả mong muốn. Tương tự với chức năng nhưng tôi tránh xa các chức năng trong DB ....
Frank V

trong tùy chọn của tôi, nó tạo ra datetime cục bộ thành db
VelikiiNehochuha

Hãy cẩn thận. Câu hỏi là về việc tạo dấu thời gian mặc định trong UTC cho cột dấu thời gian xảy ra không lưu trữ múi giờ (có lẽ vì không cần lưu trữ múi giờ nếu bạn biết rằng tất cả dấu thời gian của bạn đều giống nhau). Giải pháp của bạn là tạo ra dấu thời gian cục bộ (mà hầu hết mọi người sẽ không nhất thiết phải được đặt thành UTC) và lưu trữ dưới dạng dấu thời gian ngây thơ (không xác định múi giờ của nó).
Michael Ekoka

@MichaelEkoka Tôi đã thêm nhận xét của bạn vào câu trả lời - vui lòng tiếp tục và chỉnh sửa nếu bạn muốn. Bạn đang giải thích nó rất rõ ràng. Cảm ơn!
Risadinha

Cảnh báo : dấu thời gian với trường múi giờ KHÔNG lưu trữ múi giờ, trái với giả định hợp lý. Xem liên kết dưới đây và tìm kiếm trang cho UTC. Trên đầu vào, dấu thời gian với múi giờ sẽ chuyển đổi giá trị đến thành utc và lưu trữ giá trị đó KHÔNG CÓ THÔNG TIN KHU VỰC HOẶC THÔNG TIN CỦA OFFSET . Trên đầu ra, giá trị utc được lưu trữ được chuyển đổi thành giờ địa phương bằng cách sử dụng múi giờ của khách hàng nếu có. Loại này là tất cả về chuyển đổi giá trị tại thời điểm truy vấn. Bạn nên kiểm tra điều này bằng cách lưu trữ từ một múi giờ và chọn từ một múi giờ khác. postgresql.org/docs/11/datatype-datetime.html
Tom

7

Đây là 2 giải pháp tương đương:

(trong đoạn mã sau, bạn nên thay thế 'UTC'cho khu vựcnow()cho timestamp )

  1. timestamp AT TIME ZONE zone - Phù hợp tiêu chuẩn SQL
  2. timezone(zone, timestamp) - dễ đọc hơn

Múi giờ chức năng (vùng, dấu thời gian) tương đương với dấu thời gian xây dựng tuân thủ SQL trong vùng TIME TIME.


Giải trình:

  • vùng có thể được chỉ định dưới dạng chuỗi văn bản (ví dụ 'UTC':) hoặc dưới dạng khoảng (ví dụ INTERVAL '-08:00':) - đây là danh sách tất cả các múi giờ khả dụng
  • dấu thời gian có thể là bất kỳ giá trị nào của dấu thời gian
  • now()trả về giá trị của dấu thời gian loại (chỉ những gì chúng ta cần) với múi giờ mặc định của cơ sở dữ liệu của bạn được đính kèm (ví dụ:2018-11-11T12:07:22.3+05:00 ).
  • timezone('UTC', now())biến thời gian hiện tại của chúng tôi (thuộc loại dấu thời gian với múi giờ ) thành thời gian tương đương với thời gianUTC .
    Ví dụ, SELECT timestamp with time zone '2020-03-16 15:00:00-05' AT TIME ZONE 'UTC'sẽ trở lại 2020-03-16T20:00:00Z.

Tài liệu: múi giờ ()


1
Cảm ơn đã tóm tắt những điều này. Tôi đã sử dụng phiên bản chữ thường at timezone 'utc'và nó không hoạt động với thiết lập PostgreSQL của tôi. Sử dụng chữ in hoa đã giải quyết vấn đề
Geradlus_RU

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.