Trường hợp sử dụng hợp lệ để sử dụng TIMESTAMP KHÔNG CÓ THỜI GIAN THỜI GIAN là gì?


40

Có một câu trả lời dài và khá sáng tỏ về sự khác biệt giữa

  • TIMESTAMP WITH TIME ZONE -vs-
  • TIMESTAMP WITHOUT TIME ZONE

có sẵn trong bài viết SO này . Những gì tôi muốn biết là: có bất kỳ trường hợp sử dụng hợp lệ nào cho việc sử dụng thực sự TIMESTAMP WITHOUT TIME ZONEhay nó nên được coi là một mô hình chống.


Câu hỏi này có nguy cơ bị đóng cửa là "chủ yếu dựa trên ý kiến". Tôi đã cố gắng đưa ra một số quan điểm khách quan trong câu trả lời của tôi dưới đây.
Colin 't Hart

2
Vấn đề này khá thực tế, mỗi loại dữ liệu có một ý nghĩa rất khác nhau. Vì vậy, tôi chắc chắn sẽ không xem Câu hỏi này là chủ yếu dựa trên ý kiến.
Basil Bourque

Câu trả lời:


29

Điều này được nêu trong rất nhiều nơi, nhưng tôi nghĩ rằng nó đáng nói luôn khi chúng ta so sánh timestamp with time zonevới timestamp without time zonecác loại: các timestamp WITH time zonekhông lưu trữ các múi giờ thông tin cùng với các dấu thời gian . Những gì nó làm là lưu trữ mọi dữ liệu theo múi giờ UTC, như đã nêu trong các tài liệu :

Đối với dấu thời gian với múi giờ, giá trị được lưu trữ bên trong luôn ở UTC (Giờ phối hợp toàn cầu, theo truyền thống được gọi là Giờ chuẩn Greenwich, GMT). Giá trị đầu vào có múi giờ rõ ràng được chỉ định sẽ được chuyển đổi sang UTC bằng cách sử dụng phần bù thích hợp cho múi giờ đó. Nếu không có múi giờ nào được nêu trong chuỗi đầu vào, thì nó được giả sử là ở múi giờ được chỉ định bởi tham số TimeZone của hệ thống và được chuyển đổi thành UTC bằng cách sử dụng phần bù cho múi giờ.

Nó được coi là hợp lệ đối với một số người sử dụng timestamp WITHOUT time zonetrong các tình huống trong đó (1) mọi thứ đều ở cùng múi giờ hoặc (2) lớp ứng dụng xử lý múi giờ và chỉ lưu trữ mọi thứ trong một múi giờ nhất định (thường là UTC). Nhưng nó cũng được coi là một kiểu chống mẫu, đơn giản vì giải pháp chính xác cho (1) là định cấu hình cài đặt TimeZone cho một múi giờ nhất định cho hệ thống và (2) đã được giải quyết, vì PostgreQuery đã lưu trữ mọi thứ trên cùng múi giờ (UTC).

Bây giờ, với hai thứ đó, tôi chỉ có thể sử dụng một lý do chính đáng timestamp WITHOUT time zone. Đó là khi bạn muốn lưu trữ các sự kiện trong tương lai và một loại cảnh báo nào đó phải được kích hoạt khi chúng tôi đến thời điểm đó. Điều đó có thể tốt cho timestamp WITH time zonenếu và chỉ khi, các quy tắc được xác định theo luật của khu vực về múi giờ không bao giờ thay đổi. Quy tắc phổ biến nhất thay đổi là về việc áp dụng hay không sử dụng thời gian tiết kiệm ánh sáng ban ngày (DST).

Ví dụ, hãy tưởng tượng rằng bạn đang ở, giả sử, 2013-06-15(chưa có trong DST) lên lịch một số sự kiện sẽ xảy ra tại 2013-01-15 10:00(sẽ có trong DST) và tại 2013-06-15khu vực của bạn được chỉ định áp dụng DST; nhưng, một thời gian sau đó, chính phủ đã thay đổi quy tắc và nói rằng khu vực của bạn sẽ không còn sử dụng DST nữa và đột nhiên thời gian dự kiến ​​của bạn trở thành 2013-01-15 11:00(thay vì 10:00), nếu bạn sử dụng timestamp WITH time zonevà luôn cập nhật cấu hình TZ của bạn. Tất nhiên bạn cũng có thể nhận thấy rằng cũng có thể xử lý các trường hợp như vậy theo múi giờ, nếu bạn theo dõi các thay đổi quy tắc trong các vùng / múi giờ bạn quan tâm và cập nhật các hồ sơ bị ảnh hưởng.

Đáng nói là một số vùng thường thay đổi các quy tắc này (như ở Brazil, một số bang - không phải toàn bộ quốc gia - thường thay đổi), nhưng trong hầu hết các trường hợp, nó thay đổi rất sớm, do đó người dùng của bạn sẽ chỉ bị ảnh hưởng bởi các sự kiện được lên lịch rất xa thời điểm hiện tại

Với tất cả những gì đã nói, tôi chỉ có một gợi ý nữa. Nếu bạn có người dùng, nhật ký hoặc bất cứ thứ gì trên các múi giờ khác nhau, hãy lưu trữ múi giờ họ đến từ đâu đó và chọn và sử dụng timestamp with time zone. Bằng cách đó, bạn có thể (1) các sự kiện chéo xảy ra gần nhau hơn cho các nguồn khác nhau (không phụ thuộc vào múi giờ của chúng) và (2) hiển thị thời gian ban đầu (thời gian đồng hồ) sự kiện đã xảy ra.


Bạn đang nói: "Tôi chỉ có thể có một lý do chính đáng để sử dụng dấu thời gian với múi giờ". Nếu đó không phải là một lỗi đánh máy thì bạn có thực sự gợi ý rằng "dấu thời gian không có múi giờ" thực sự phù hợp hơn / ít gây ra sự hiểu lầm hơn là "dấu thời gian với múi giờ"? Điều đó dường như phản trực giác với tôi.
Marcus Junius Brutus

@MarcusJuniusBrutus, xin lỗi về điều đó, nó thực sự là một lỗi đánh máy và tôi nghĩ cách khác xung quanh ... Kiểm tra câu trả lời đã chỉnh sửa.
MatheusOl

codeblog.jonskeet.uk/2019/03/27/... thảo luận sâu chính xác này kịch bản tương lai-event-quy-sức-change (với cùng một conclution)
Beni Cherniavsky-Paskin

17

Vâng. Có trường hợp sử dụng cho TIMESTAMP WITHOUT TIME ZONE.

  • Trong các ứng dụng kinh doanh phổ biến, loại này sẽ chỉ được sử dụng cho:
    • Đặt lịch hẹn trong tương lai
    • Đại diện cho cùng một thời gian trong ngày trên các múi giờ khác nhau, chẳng hạn như buổi trưa ngày 23 ở Tokyo ở Paris (hai thời điểm khác nhau cách nhau hàng giờ, cùng thời gian trong ngày)
  • Để theo dõi khoảnh khắc, các điểm cụ thể trên dòng thời gian, luôn luôn sử dụng TIMESTAMP WITH TIME ZONE, không WITHOUT.

TIMESTAMP WITHOUT TIME ZONEcác giá trị không phải là một điểm trên dòng thời gian, không phải là khoảnh khắc thực tế. Chúng đại diện cho một ý tưởng sơ bộ về những khoảnh khắc tiềm năng , những điểm có thể có trên dòng thời gian dọc theo khoảng 26-27 giờ (phạm vi múi giờ trên toàn cầu). Chúng không có ý nghĩa thực sự cho đến khi bạn áp dụng múi giờ hoặc bù từ UTC .

Vd: Giáng sinh

Ví dụ, giả sử bạn cần ghi lại ngày bắt đầu của ngày lễ / ngày thánh.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Để ghi lại thực tế rằng Giáng sinh bắt đầu sau nửa đêm ngày 25 tháng 12 năm nay, chúng ta cần nói 2016-12-25 00:00:00mà không có bất kỳ múi giờ nào. Đầu ngày ông già Noel, ông đến thăm Auckland New Zealand chỉ sau nửa đêm, vì đó là một trong những đêm sớm nhất trên toàn cầu. Sau đó, anh ta đi về phía tây, khi nửa đêm tiếp theo xảy ra, sớm đến Philippines. Sau đó, tuần lộc di chuyển theo hướng tây, đến Ấn Độ vào lúc nửa đêm, điều này xảy ra vài giờ sau nửa đêm Auckland. Nhiều sau đó vẫn là nửa đêm ở Paris FR, và vẫn là nửa đêm ở Montreal CA. Tất cả những chuyến viếng thăm này của ông già Noel diễn ra vào những thời điểm khác nhau là thời gian , nhưng tất cả đều diễn ra ngay sau nửa đêm, mỗi nửa đêm của mỗi địa phương.

Vì vậy, ghi âm 2016-12-25 00:00:00mà không có bất kỳ múi giờ nào khi bắt đầu Giáng sinh là thông tin và hợp pháp, nhưng chỉ mơ hồ. Cho đến khi bạn nói Giáng sinh ở Auckland và Auckland Giáng sinh ở Montréal, chúng tôi không có thời điểm cụ thể. Nếu bạn đang ghi lại khoảnh khắc thực tế mỗi khi xe trượt tuyết chạm xuống, bạn sẽ sử dụng TIMESTAMP WITH TIME ZONEchứ không phải WITHOUTloại.

Tương tự như Giáng sinh là đêm giao thừa. Khi quả bóng Times Square rơi ở New York , người dân ở Seattle vẫn đang làm lạnh rượu sâm banh và chuẩn bị còi tiệc . Tuy nhiên, chúng tôi sẽ ghi lại ý tưởng của thời điểm năm mới như 2017-01-01 00:00:00trong một TIMESTAMP WITHOUT TIME ZONE. Ngược lại, nếu chúng tôi muốn ghi lại khi quả bóng rơi ở New York hoặc khi người dân ở Seattle thổi còi, chúng tôi sẽ sử dụng TIMESTAMP WITH TIME ZONE(không WITHOUT) để ghi lại những khoảnh khắc thực tế đó, cách nhau ba giờ.

Vd: Ca làm việc của nhà máy

Một ví dụ khác có thể là ghi lại một chính sách liên quan đến thời gian đồng hồ treo tường trên nhiều địa điểm khác nhau. Giả sử chúng tôi có các nhà máy ở Detroit, Düsseldorf và Delhi. Nếu chúng ta nói rằng tại cả ba nhà máy, ca làm việc đầu tiên bắt đầu lúc 6 giờ sáng với giờ nghỉ trưa lúc 11:30 sáng, thì đó có thể được ghi là a TIMESTAMP WITHOUT TIME ZONE. Một lần nữa, thông tin này hữu ích một cách mơ hồ nhưng không chỉ ra thời điểm cụ thể cho đến khi chúng ta áp dụng múi giờ. Một ngày mới bắt đầu sớm hơn ở phía đông. Vì vậy, nhà máy Delhi sẽ là nơi đầu tiên mở cửa vào lúc 6 giờ sáng. Vài giờ sau, nhà máy Düsseldorf bắt đầu làm việc lúc 6 giờ sáng. Nhưng nhà máy Detroit sẽ không thực sự mở cửa cho đến sáu giờ sau, khi 6 giờ sáng.

Đối chiếu ý tưởng này (về thời điểm ca làm việc tại nhà máy thường bắt đầu) với thực tế lịch sử là khi nào mỗi công nhân nhà máy đồng hồ bắt đầu ca làm việc của họ vào một ngày cụ thể. Đồng hồ là một khoảnh khắc thực sự, một điểm thực tế trên dòng thời gian. Vì vậy, chúng tôi sẽ ghi lại rằng trong một cột của loại TIMESTAMP WITH TIME ZONEchứ không phải là WITHOUTloại.

Vì vậy, có, có trường hợp sử dụng hợp pháp cho TIMESTAMP WITHOUT TIME ZONE. Nhưng theo kinh nghiệm của tôi với các ứng dụng kinh doanh, chúng tương đối hiếm. Trong kinh doanh, chúng ta có xu hướng quan tâm đến những khoảnh khắc thực tế: khi nào hóa đơn thực sự đến, khi nào chính xác hợp đồng đó có hiệu lực, vào thời điểm nào giao dịch ngân hàng đó thực hiện. Vì vậy, trong các tình huống phổ biến như vậy, chúng tôi muốn các TIMESTAMP WITH TIME ZONEloại.

Để thảo luận thêm, hãy xem Câu trả lời của tôi cho Câu hỏi tương tự, Tôi nên lưu trữ dấu thời gian UTC hoặc giờ địa phương để thay đổi

Bưu điện

Lưu ý rằng Postgres đặc biệt không bao giờ lưu thông tin múi giờ được chỉ định khi chèn dấu thời gian.

  • TIMESTAMP WITH TIME ZONE
    • Bất kỳ múi giờ hoặc phần bù nào được chỉ định kèm theo dữ liệu đầu vào đều được sử dụng để điều chỉnh giá trị thành UTC và được lưu trữ. Sau đó, thông tin vùng / bù được thông qua sẽ bị loại bỏ. Hãy nghĩ về TIMESTAMP WITH TIME ZONEnhư TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Đầu vào 12:00 trưa ngày 7 tháng 3 năm nay tại Ấn Độ sẽ được điều chỉnh theo thời gian trong ngày bằng UTC bằng cách trừ năm giờ rưỡi: 6:30 sáng.
  • TIMESTAMP WITHOUT TIME ZONE
    • Bất kỳ múi giờ hoặc phần bù được chỉ định kèm theo dữ liệu đầu vào hoàn toàn bị bỏ qua.
    • Một đầu vào của 12:00 trưa ngày 7 tháng 3 năm nay ở Ấn Độ được ghi là 12:00 vào ngày 7 tháng 3 năm nay mà không có sự điều chỉnh.

Tiêu chuẩn SQL hầu như không đề cập đến các vấn đề về kiểu dữ liệu và hành vi thời gian. Vì vậy, cơ sở dữ liệu khác nhau rộng rãi trong xử lý ngày-thời gian.


hơn nữa với các ca làm việc tại nhà máy (hoặc bệnh viện), bất cứ ai làm việc theo ca ở nghĩa địa vào những ngày chuyển đổi DST sẽ ghi lại số giờ của họ không chính xác nếu không có múi giờ ..
Jasen

Tôi nghĩ rằng có một lỗi đánh máy trong ví dụ cuối: 'Đầu vào của 12:00 trưa ngày 7 tháng 3 .. nên được' ghi là 12 : 00 '(không 21:00)
TmTron

11

Tôi muốn thêm một góc nhìn khác cho điều này, nó đi ngược lại với hầu hết những gì được viết trong các câu trả lời khác. Theo tôi timestamp with time zonecó rất ít trường hợp sử dụng hợp lệ, và timestamp without time zonenói chung nên được ưu tiên.

Trước tiên, bạn phải hiểu mẫu "UTC ở mọi nơi", thường được khuyến nghị cho tất cả các ứng dụng không có yêu cầu rất đặc biệt. Nó đơn giản có nghĩa là ứng dụng của bạn sẽ đại diện cho tất cả các dấu thời gian của nó trong UTC, ở mọi nơi, mọi lúc. Tất nhiên, bạn sẽ hiển thị ngày / giờ địa phương cho người dùng, nhưng ý tưởng là chuyển đổi những thứ này ở ngay cạnh chương trình của bạn, khi hiển thị chế độ xem. Đây là nơi thích hợp để kết hợp dấu thời gian UTC (mà bạn có thể đã tải từ cơ sở dữ liệu) và múi giờ của người dùng (có thể đến từ trình duyệt) vào dấu thời gian cục bộ.

Nếu bạn đang theo mô hình này, thì đó timestamp with time zonelà một mô hình chống. Tất cả kiểu này là làm cho PostgreQuery thực hiện chuyển đổi múi giờ khi đọc và viết dấu thời gian, dựa trên TimeZonebiến phiên PostgreQuery của bạn . Thay vì xử lý các múi giờ ở chính rìa ứng dụng của bạn, bạn đã đưa chúng vào trung tâm của nó, vào chính giao tiếp với cơ sở dữ liệu của bạn. Bạn phải cẩn thận để luôn luôn có PostgreSQL TimeZoneđược cấu hình đúng cách, thêm một điểm không cần thiết và thất bại không cần thiết.

Và để làm gì? Nếu bạn đang theo mẫu UTC ở mọi nơi, ứng dụng của bạn chỉ có dấu thời gian UTC; vậy tại sao yêu cầu cơ sở dữ liệu của bạn thực hiện chuyển đổi múi giờ trên chúng? Bạn chỉ có thể lưu trữ chúng trong một timestamp without time zonecột và coi nó như UTC. Không chuyển đổi, không có múi giờ, không có biến chứng.


2
Tôi nghĩ rằng những người đề xuất dấu thời gian cũng hỗ trợ mô hình "UTC ở mọi nơi". Đó chỉ là quy tắc được thực thi ở cấp cơ sở dữ liệu thay vì chỉ dựa vào các nhà phát triển ứng dụng / API để thực thi nó? Nếu bạn có thể thực thi thực hành đó, tại sao không? Ngoài ra, bạn chỉ có thể thực thi rằng tất cả các kết nối postgres đặt múi giờ của họ thành UTC. Ngay cả khi chúng không có, định dạng ISO sẽ chứa phần bù tz. Vì vậy, đó không phải là điều tương tự như UTC ở khắp mọi nơi nhưng được thực thi?
iamnat

3
Đầu tiên, nếu PostgreSQL TimeZone của bạn được đặt thành bất cứ thứ gì ngoại trừ UTC và bạn đang sử dụng dấu thời gian, chương trình của bạn đang đọc dấu thời gian không phải UTC. Đây đơn giản không phải là mẫu "UTC ở mọi nơi" và tùy thuộc vào ngôn ngữ khách hàng của bạn có thể hoặc không thể tạo ra nhiều sự phức tạp. Hoặc bạn là UTC ở mọi nơi hoặc bạn đang sử dụng dấu thời gian cục bộ ....
Shay Rojansky

Thứ hai, một lần nữa, nếu bạn là UTC ở mọi nơi trong ứng dụng của mình, đơn giản là không có phần bù nào để gửi ở định dạng ISO cho dấu thời gian của bạn. Các chi tiết cụ thể sẽ khác nhau giữa các ngôn ngữ, nhưng lý tưởng nhất là bạn nên sử dụng loại ứng dụng khách không có khả năng đại diện cho bất cứ thứ gì ngoại trừ dấu thời gian UTC (ví dụ: Instancetrong NodaTime / JodaTime). Về cơ bản, bạn đang mô tả một tình huống mà "UTC ở mọi nơi" gần như được theo dõi, hoặc theo sau ...
Shay Rojansky

Một lần nữa, thật dễ dàng để tưởng tượng một cá thể PostgreSQL mới đang được thiết lập trên một số máy chủ, vô tình giữ lại múi giờ của máy cục bộ được cấu hình theo mặc định. Các ứng dụng đọc từ máy chủ này và nhận các dấu thời gian cục bộ trong múi giờ hoàn toàn tùy ý (mà máy chủ xảy ra). Tại sao chúng tôi muốn biến chứng bổ sung này?
Shay Rojansky

1
Nó có thể, nhưng sau đó nó sẽ làm cho ít ý nghĩa hơn để sử dụng timestamptz. Toàn bộ quan điểm của loại này là thực hiện chuyển đổi múi giờ dưới dạng các giá trị được đọc và ghi vào PostgreQuery (bên trong cơ sở dữ liệu, dấu thời gian luôn được lưu dưới dạng UTC). Luôn đặt múi giờ phiên thành UTC vô hiệu hóa hiệu quả các chuyển đổi đó, vậy tại sao lại sử dụng timestamptz? Nói cách khác, nếu các giá trị trong cơ sở dữ liệu là UTC và các giá trị vào và ra khỏi cơ sở dữ liệu luôn là UTC, thì tại sao lại có nhận thức về múi giờ trong cơ sở dữ liệu của bạn?
Shay Rojansky

2

Các datedấu thời gian cũng không có thông tin múi giờ, nhưng có rất nhiều người sử dụng nó.

Tất nhiên, đó không phải là một câu trả lời.

Nó hợp lệ để sử dụng timestampdatecho bất kỳ dấu thời gian và ngày nào luôn ở cùng múi giờ hoặc đang được lưu trữ liên quan đến một số múi giờ đã biết.

Nếu múi giờ luôn giống nhau hoặc ẩn thì việc lưu trữ nó nhiều hơn là không lưu trữ (thông tin dư thừa).

Dấu thời gian cũng có thể được sử dụng để lưu trữ thông tin kỹ thuật như được sử dụng trong nhật ký ứng dụng hoặc để đo hiệu suất. Trong trường hợp này, múi giờ cũng có thể không quan trọng.


Ngược lại, nếu bạn đang thiết kế hoặc làm việc trên một hệ thống phân tán hoặc trong bất kỳ hệ thống nào mà các bộ phận của hệ thống sẽ được phân phối trên các múi giờ khác nhau, nó có thể được coi là một mô hình chống không sử dụng timestamp with timezone, mặc dù một số hệ thống có thể được thiết kế để chạy trong một múi giờ, ví dụ UTC. Trong trường hợp này, logic múi giờ có thể được đẩy vào lớp ứng dụng - nhưng tôi sẽ coi đây là một mô hình chống, vâng.


Tôi hiểu rằng trong một số trường hợp nhất định, nó không gây hại cho việc sử dụng timestamp without timezone, nhưng nó có bao giờ mua cho tôi không? Nếu không, tại sao tôi phải bận tâm nếu timestamp with timezone dataloại luôn luôn bằng nhau hoặc phù hợp hơn?
Marcus Junius Brutus

Không lưu trữ thông tin dư thừa sẽ là đối số chính của tôi. Tôi cho rằng số học ngày timestamp without timezonecũng sẽ nhanh hơn, nhưng điều đó có lẽ chỉ quan trọng nếu bạn đang xử lý hàng tỷ hàng ...
Colin 't Hart

1
@ Colin'tHart timestamptimestamptzcả hai đều được lưu trữ theo cùng một cách. Không có thông tin múi giờ được lưu trữ trong một timestamptz, nhưng thay vào đó, nó được chuyển đổi thành UTC để lưu trữ. Tôi muốn nói, luôn luôn sử dụng timestamptzkhi dấu thời gian trong câu hỏi biểu thị thời gian tuyệt đối . Đó là tất cả những gì timestamptzcó nghĩa. Tôi đã viết về điều này ở đây .
fphilipe

2

Có vẻ như tạm thời lưu trữ và xử lý ngày / giờ theo giờ địa phương nếu ứng dụng của bạn bị giới hạn trong một múi giờ duy nhất nhưng tôi tin rằng đây là một sai lầm.

Khi chuyển trở lại từ thời gian tiết kiệm ánh sáng ban ngày sang thời gian tiêu chuẩn, một giờ trong giờ địa phương được lặp lại (giả sử sự khác biệt là một giờ). Nơi tôi sống điều này thường xảy ra vào khoảng 2 giờ sáng vì vậy giờ địa phương chạy 01:58, 01:59, 01:00 và chỉ tiến tới 02:00 vào cuối giờ lặp lại.

Nếu bạn cố gắng sắp xếp các sự kiện theo thời gian bằng giờ địa phương, điều đó có nghĩa là các sự kiện từ hai giờ riêng biệt được trộn lẫn với nhau và không xuất hiện theo thứ tự mà chúng thực sự xảy ra.

Bằng cách so sánh, UTC không có vấn đề này và đơn hàng sạch sẽ. Vì vậy, ngay cả khi làm việc chỉ với một múi giờ, bạn vẫn muốn DB lưu trữ và xử lý thời gian trong UTC và chuyển đổi sang / từ giờ địa phương cho đầu vào / hiển thị. Đây là hành vi của TIMESTAMP VỚI TIME ZONE.

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.