TIME ZONE OLMADAN TIMESTAMP kullanmak için geçerli bir kullanım durumu nedir?


40

Aradaki farklar konusunda uzun ve oldukça aydınlatıcı bir cevap var.

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

Bu SO postasında mevcut . Bilmek istediğim şey şu: gerçekten kullanmak için geçerli herhangi bir kullanım durumu var mı, yoksa TIMESTAMP WITHOUT TIME ZONEbir anti-patern olarak mı düşünülmeli?


Bu soru “öncelikli olarak görüş temelli” olmaktan kapatılma riskini taşıyor. Aşağıdaki cevabımda objektif görüşler vermeye çalıştım.
Colin 't Hart

2
Bu sorun oldukça gerçektir, her veri türü çok farklı bir anlama sahiptir. Bu yüzden kesinlikle bu soruyu öncelikle görüş temelli olarak değerlendirmeyeceğim.
Basil Bourque,

Yanıtlar:


29

Bu yerlerde bir sürü belirtildiği, ama biz karşılaştırdığımızda buna değer her zaman söz düşünüyorum edilir timestamp with time zoneile timestamp without time zonetipleri: saklamaz saat dilimi zaman damgası ile birlikte bilgi . Dokümanlarda belirtildiği gibi her verinin UTC zaman diliminde saklanması :timestamp WITH time zone

Zaman dilimine sahip zaman damgası için dahili olarak depolanan değer her zaman UTC’dedir (geleneksel olarak Greenwich Ortalama Saati, GMT olarak bilinen Evrensel Koordineli Zaman). Açık bir zaman dilimi belirlenmiş bir giriş değeri, o zaman dilimi için uygun ofset kullanılarak UTC'ye dönüştürülür. Giriş dizgisinde saat dilimi belirtilmezse, o zaman sistemin TimeZone parametresi tarafından belirtilen saat diliminde olduğu varsayılır ve saat dilimi bölgesi için ofset kullanılarak UTC'ye dönüştürülür.

timestamp WITHOUT time zone(1) her şeyin aynı saat diliminde olduğu veya (2) uygulama katmanının zaman dilimini tuttuğu ve sadece her şeyi belirli bir zaman diliminde (genellikle UTC) sakladığı durumlarda bazılarının kullanımı geçerli sayılır . Ancak, aynı zamanda bir anti-pattern olarak kabul edilir, çünkü (1) için doğru çözüm, TimeZone ayarını sistem için verilen bir saat dilimine ayarlamaktır ve (2) PostgreSQL zaten her şeyi aynı saat diliminde sakladığı için zaten çözülmüştür. (UTC).

Şimdi, bu ikisi kapalıyken, kullanmak için tek bir sebeple gelebilirim timestamp WITHOUT time zone. Gelecekte olayları saklamak istediğinizde ve o zamana vardığımızda bir tür uyarının tetiklenmesi gerektiğini söyler. Bu timestamp WITH time zone, bölgenin zaman dilimi konusundaki yasalarının tanımladığı kuralların değişmemesi halinde iyi olabilir. Değişen en yaygın kural, gün ışığından yararlanma zamanının (DST) benimsenmesi veya benimsenmemesiyle ilgilidir.

Örneğin, 2013-06-15(henüz DST'de değil), 2013-01-15 10:00(zaten DST'de olacaktı ) bazı bölgeleri planladığınızı ve 2013-06-15bölgenizde DST'yi benimsemek için belirlenmiş olduğunu düşünelim; Ancak, bundan bir süre sonra, hükümet kuralı değiştirdi ve bölgenizin artık DST kullanmayacağını ve aniden zamanladığınız zamanın 2013-01-15 11:00(yerine 10:00) olacağını timestamp WITH time zone, kullanırsanız ve TZ yapılandırmalarınızı güncel tuttuğunu söylüyor . Elbette, ilgilendiğiniz bölgelerdeki / saat dilimlerindeki kural değişikliklerini izlerseniz ve etkilenen kayıtları güncellerseniz, bu gibi durumlara zaman dilimiyle de davranmanın mümkün olduğunu fark edebilirsiniz.

Bazı bölgelerin sık sık bu kuralları değiştirdiğini söylemeye değer (Brezilya gibi, bazı devletler - tüm ülke değil - çoğu zaman değişir), ancak çoğu durumda çok daha önce değiştirir, bu nedenle kullanıcılarınız yalnızca çok uzakta zamanlanmış olan etkinliklerden etkilenir şu anki zaman.

Tüm bunlara rağmen, sadece bir önerim daha var. Kullanıcılarınız, günlükleriniz veya farklı saat dilimleri üzerindeki herhangi bir şey varsa, bir yerden geldikleri saat dilimini saklayın ve seçin ve kullanın timestamp with time zone. Bu şekilde (1) farklı kaynaklar (birbirlerine ait saat dilimlerinden bağımsız olarak) için birbirlerine daha yakın gerçekleşen olayları geçebilir ve (2) olayın gerçekleştiği orijinal zamanı (saat zamanı) gösterebilirsiniz.


Diyorsunuz: "Zaman dilimi ile zaman damgasını kullanmak için tek bir iyi sebeple gelebilirim". Bu bir yazım hatası değilse, o zaman gerçekten "zaman dilimi olmayan zaman damgası" nın "zaman dilimi olan zaman damgası" ndan yanlış anlamalar üretmeye daha eğilimli olduğunu mu düşünüyorsunuz? Bu bana karşı sezgisel görünüyor.
Marcus Junius Brutus

@ MarcusJuniusBrutus, bunun için üzgünüm, gerçekten bir yazım hatası oldu ve ben tersini düşündüm ... Düzenlenmiş cevabı kontrol edin.
MatheusOl

codeblog.jonskeet.uk/2019/03/27/… bu gelecek-olay-kurallar-değişim-değişim senaryosunu tam olarak tartışıyor (aynı sonuç ile)
Beni Cherniavsky-Paskin

17

Evet. Kullanım durumlar vardır TIMESTAMP WITHOUT TIME ZONE.

  • Yaygın işletme uygulamalarında bu tür yalnızca şunlar için kullanılır:
    • Gelecekteki randevular rezervasyon
    • Tokyo'daki ve Paris'teki öğleden sonraki öğleden sonraki öğleden sonra saatlerinde aynı saat dilimini temsil eder (iki ayrı dakika saat, saat aynı saat)
  • Zaman çizelgesinde anları, belirli noktaları izleme için daima kullanmak TIMESTAMP WITH TIME ZONEdeğil WITHOUT.

TIMESTAMP WITHOUT TIME ZONEdeğerlerdir değil zaman çizelgesi üzerinde bir nokta değil gerçek anlar. Potansiyel anlar, zaman çizelgesi üzerindeki muhtemel noktaları yaklaşık 26-27 saat (dünyadaki zaman dilimleri aralığı) hakkında kaba bir fikir temsil ederler . Siz bir saat dilimi veya UTC dengeleme uygulayana kadar gerçek bir anlamı yoktur .

Ör: Noel

Örneğin, tatillerin başlangıcını / kutsal günleri kaydetmeniz gerektiğini söyleyin.

Table: holiday_

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

Noel’in bu yıl 25 Aralık’ta gece yarısından sonra başladığı gerçeğini kaydetmek için, 2016-12-25 00:00:00herhangi bir zaman dilimi olmadan söylemeliyiz . Noel Baba'nın ilk günlerinde, gece yarısından hemen sonra Auckland NZ'yi ziyaret ediyor, çünkü bu dünyanın en erken gece yarısı gecelerinden biri. Ardından bir sonraki gece yarısı olduğu gibi kısa sürede Filipinler'e ulaşacak şekilde batıya doğru ilerliyor. Sonra ren geyiği, batı yönünde ilerleyerek, Auckland'ın gece yarısından birkaç saat sonra meydana geldiği gece yarısında Hindistan'a ulaşır. Çok daha sonra hala Paris'te gece yarısı, daha sonra da Montreal'de gece yarısı. Noel Baba tarafından yapılan tüm bu ziyaretler, farklı anlarda gerçekleşiyor , ancak her bir yerin kendi gece yarısına göre hepsi gece yarısından kısa bir süre sonra gerçekleşti.

2016-12-25 00:00:00Noel'in başlangıcı olarak herhangi bir zaman dilimi olmadan kayıt yapmak bilgilendirici ve meşrudur, ancak yalnızca belirsizdir. “Auckland'da Noel” veya “Montréal'de Noel” diyene kadar, zaman içinde belirli bir anımız yok. Kızak her aşağı dokunduğunda gerçek anı kaydediyorsanız TIMESTAMP WITH TIME ZONE, WITHOUTtür yerine kullanırsınız .

Noel'e benzer Yılbaşı. Ne zaman Times Square Ball New York'ta düşer , Seattle insanlar hala kendi şampanya soğutma ve onların hazırlanıyor parti boynuzları . Yine de, Yeni Yıl anı fikrini2017-01-01 00:00:00 a TIMESTAMP WITHOUT TIME ZONE. Buna karşılık, topun New York'a ne zaman düştüğünü veya Seattle'daki insanlar boynuzlarını patladığında kaydetmek istiyorsak, bunun yerine her üç saatte bir, diğer gerçek anları kaydetmek için kullanırız TIMESTAMP WITH TIME ZONE(değil WITHOUT).

Ör: Fabrika Vardiyaları

Başka bir örnek , çeşitli yerlerde duvar saati süresini içeren bir politika kaydetme olabilir . Detroit, Düsseldorf ve Delhi'de fabrikalarımız olduğunu söyleyin. Her üç fabrikada da ilk vardiya sabah 6’da başlıyor ve 11: 30’da bir öğle yemeği molası veriyor TIMESTAMP WITHOUT TIME ZONE. Yine, bu bilgiler belirsiz bir şekilde faydalıdır, ancak bir zaman dilimi uygulayana kadar zamanın belirli bir anını göstermez. Yeni bir gün doğuda daha erken doğar. Bu yüzden, Delhi fabrikası saat 6'da ilk açılacak. Saatler sonra, Düsseldorf fabrikası sabah 6'da çalışmaya başlar. Ancak Detroit fabrikası sabah altıda bir olan 6 saat sonra başlayacak.

Bu düşünceyi (fabrika değişimleri genellikle başladığında), her bir fabrika işçisinin belirli bir günde vardiyasına başlamak için ne zaman çalıştığının tarihsel gerçeğiyle karşılaştırın. Saat girişi gerçek bir an, zaman çizelgesinde gerçek bir nokta. Böylece bunu türden TIMESTAMP WITH TIME ZONEçok bir tür sütununa kaydederdik WITHOUT.

Yani, evet, meşru kullanım durumları var TIMESTAMP WITHOUT TIME ZONE. Ancak iş uygulamaları konusundaki deneyimimde, nispeten nadirdir. İş dünyasında gerçek anları önemseriz: fatura gerçekte ne zaman geldi, bu sözleşme tam olarak ne zaman yürürlüğe girdi, o banka işlemi hangi anda yürüdü. Yani böyle yaygın durumlarda, TIMESTAMP WITH TIME ZONEtürü istiyoruz .

Daha fazla tartışma için, bkz benim cevap benzer Soru, için vardiya için Meli ben mağaza UTC zaman damgaları veya localtime'a

postgres

Postgres’lerin , zaman damgası eklerken belirtilen saat dilimi bilgilerini hiçbir zaman özellikle kaydetmediğini unutmayın .

  • TIMESTAMP WITH TIME ZONE
    • Girdi verilerinde belirtilen herhangi bir zaman dilimi veya ofset değeri UTC'ye ayarlamak ve saklamak için kullanılır. Geçirilen bölge / ofset bilgisi daha sonra atılır. Düşünün TIMESTAMP WITH TIME ZONEolarak TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Hindistan'da bu yıl 7 Mart günü öğlen 12: 00’daki bir girdi, beş buçuk saat: 18: 30’u çıkararak gününü UTC’ye ayarlayacak.
  • TIMESTAMP WITHOUT TIME ZONE
    • Girdi verilerinde belirtilen herhangi bir zaman dilimi veya ofset tamamen göz ardı edilir.
    • Hindistan'da bu yıl 7 Mart günü öğlen 12: 00'deki girdi, bu yılın 7 Mart günü saat 12: 00'de ayar yapılmadan kaydedildi.

SQL standardı, tarih-zaman veri tipleri ve davranışlarıyla ilgili konulara nadiren değiniyor. Bu nedenle, veritabanı zamanın işlenmesinde büyük ölçüde değişiklik gösterir .


Fabrika (veya hastane) vardiyalarında, DST değişiminin yapıldığı günlerde mezarlık vardiyasında çalışan herhangi bir kişi saatlerini saat dilimi olmadan kayıtlı olarak yanlış bir şekilde kaydetmiş olacak.
Jasen

Bence son örnekte bir yazım hatası var: '7 Mart öğlen 12:00 öğlen girişi ..' 12 : 00 olarak kaydedilmelidir '(değil 21:00)
TmTron

11

Diğer cevaplarda yazılanların çoğuna aykırı olan buna başka bir görüş daha eklemek isterim. Bana göre timestamp with time zoneçok az geçerli kullanım durumu var ve timestamp without time zonegenel olarak tercih edilmeli.

Öncelikle, çok özel gereksinimleri olmayan tüm uygulamalar için önerilen "UTC her yer" desenini anlamalısınız. Bu sadece uygulamanızın tüm zaman damgalarını UTC'de, her yerde, her zaman temsil etmesi gerektiği anlamına gelir. Elbette, kullanıcılara yerel tarih / saat göstereceksiniz, ancak fikir görünümü oluştururken bunları programınızın en sonuna dönüştürmektir. Bu, UTC zaman damgasını (bir veritabanından yüklediğiniz) ve kullanıcının zaman dilimini (tarayıcıdan gelen) yerel bir zaman damgasında birleştirmek için doğru yerdir.

Bu modeli takip ediyorsanız, o timestamp with time zonezaman bir anti-kalıptır. Tüm bu tür PostgreSQL'in PostgreSQL TimeZoneoturum değişkeninizi temel alarak zaman damgalarını okurken ve yazarken zaman dilimi dönüşümleri gerçekleştirmesini sağlar . Uygulamanızın en ucundaki zaman dilimleriyle uğraşmak yerine, veritabanınızla iletişim kurarak onları kendi kalbine soktunuz. TimeZoneGereksiz bir başarısızlık ve karışıklık noktası ekleyerek, PostgreSQL'in her zaman her zaman doğru bir şekilde yapılandırılmış olmasına özen göstermelisiniz .

Ve ne için? UTC her yerde düzenini izliyorsanız, uygulamanız yine de yalnızca UTC zaman damgalarına sahiptir; Öyleyse neden veritabanından onlardan saat dönüşümleri yapmasını istiyorsun? Onları bir timestamp without time zonesütunda saklayabilir ve her zaman UTC gibi davranabilirsiniz. Dönüşüm yok, saat dilimi yok, komplikasyon yok.


2
Zaman damgasının savunucularının da "UTC her yerde" modelini desteklediğini düşünüyorum. Bu sadece kural sadece uygulama / API geliştiricilerini uygulamak için güvenmek yerine veritabanı düzeyinde yürürlüğe girer mi? Bu uygulamayı zorlayabiliyorsan, neden olmasın? Ayrıca, tüm postgres bağlantılarının saat dilimini UTC'ye ayarlamasını zorlayabilirsiniz. Yapmasalar bile, ISO formatı tz ofsetini içerecektir. Öyleyse bu her yerde UTC ile aynı şey değil, zorlandı mı?
iamnat

3
İlk olarak, PostgreSQL TimeZone UTC dışında bir şeye ayarlanmışsa ve zaman damgası kullanıyorsanız, programınız UTC olmayan zaman damgalarını okuyor demektir. Bu basitçe "her yerde UTC" kalıbı değildir ve müşteri dilinize bağlı olarak birçok komplikasyon oluşturabilir veya olmayabilir. Ya her yerde
UTC'sin

İkincisi, bir kez daha, başvurunuzun her yerinde UTC iseniz, zaman damgalarınız için ISO biçiminde gönderilecek bir tz ofseti yoktur. Özellikler diller arasında değişecektir, ancak ideal olarak bir UTC zaman damgası dışında hiçbir şeyi temsil edemeyen bir istemci tipi kullanıyor olmalısınız (örn. Bir InstanceNodaTime / JodaTime). Temel olarak "her yerde UTC" nin neredeyse takip edildiği veya biraz takip ettiği bir durumu
anlatıyorsunuz

Bir kez daha, varsayılan olarak yapılandırılan yerel makine saat dilimini yanlışlıkla koruyarak, bazı sunuculara kurulmuş yeni bir PostgreSQL örneğini hayal etmek çok kolaydır. Uygulamalar bu sunucudan okunur ve tamamen zaman diliminde (sunucunun bulunduğu yerde) yerel zaman damgaları alır. Neden bu ek komplikasyonu istiyoruz?
Shay Rojansky,

1
Olabilirdi ama sonra kullanımı daha az mantıklı olurdu timestamptz. Bu türün amacı, saat dilimi dönüşümlerini PostgreSQL'e okunan ve yazılan değerler olarak gerçekleştirmektir (dahili olarak veritabanında, zaman damgası her zaman UTC olarak kaydedilir). Her zaman oturum saat dilimini UTC'ye ayarlamak bu dönüşümleri etkili bir şekilde devre dışı bırakır, bu nedenle neden kullanılsın timestamptz? Başka bir deyişle, eğer veritabanındaki değerler UTC ise ve veritabanına giren ve çıkan değerler daima UTC ise, neden veritabanında zaman dilimi farkındalığı var?
Shay Rojansky

2

Zaman datedamgası ayrıca saat dilimi bilgilerini içermez, ancak çoğu kişi kullanır.

Tabii ki, kendi başına bir cevap değil.

Her zaman aynı saat diliminde olan veya bilinen bir saat dilimine göre depolanan zaman damgaları ve tarihlerin kullanımı timestampve kullanımı geçerlidir date.

Saat dilimi her zaman aynı veya örtülü ise, saklamamaktan ziyade saklamak daha çok kaymazdır (gereksiz bilgi).

Zaman damgaları, uygulama günlüklerinde kullanılan gibi teknik bilgilerin depolanması veya performans ölçümleri için de kullanılabilir. Bu durumda, saat dilimi de önemsiz olabilir.


Diğer taraftan, dağıtılmış bir sistem üzerinde veya sistemin parçalarının farklı zaman dilimleri arasında dağıtılacağı herhangi bir sistemde çalışıyorsanız veya çalışıyorsanız, timestamp with timezonebazı sistemler çalışacak şekilde tasarlanmasına rağmen, kullanılmaması gereken bir kalıp olarak kabul edilebilir. bir saat diliminde, örneğin UTC. Bu durumda, zaman dilimi mantığı uygulama katmanına itilebilir - ancak bunun bir anti-model olduğunu düşünüyorum, evet.


Anladığım kadarıyla bazı durumlarda kullanmanın zararı timestamp without timezoneyok, ama bana bir şey satın aldı mı? Aksi halde, timestamp with timezone datatür her zaman eşit veya daha uygunsa neden rahatsız etmeliyim ?
Marcus Junius Brutus,

Gereksiz bilgiyi saklamamak ana argüman olur. Tarih aritmetiğinin timestamp without timezonede daha hızlı olacağını tahmin ediyorum, ancak bu muhtemelen yalnızca milyarlarca satır işliyorsanız önemlidir ...
Colin 't Hart

1
@ Colin'tHart timestampve timestamptzher ikisi de aynı şekilde saklanır. A'da saklanan zaman dilimi bilgisi yoktur timestamptz, bunun yerine depolamak için UTC'ye dönüştürülür. Her timestamptzzaman, söz konusu zaman damgalarının mutlak zamanı belirttiği zaman kullanın derim . Hepsi bu timestamptzdemek oluyor. Bu konuda burada yazdım .
fphilipe

2

Başvurunuz tek bir zaman dilimiyle sınırlıysa, yerel saatte tarih / saat kaydetme ve işleme koyma gibi görünebilir ama bunun bir hata olduğuna inanıyorum.

Gün ışığından yararlanma zamanından standart zamana geçildiğinde, yerel saatte bir saat tekrarlanır (farkın bir saat olduğu varsayılarak). Yaşadığım yerde bu genellikle saat 2 civarında olur, bu nedenle yerel saat 01:58, 01:59, 01:00 saatleri arasındadır ve yalnızca saat başı 02:00 'ye kadar ilerler.

Yerel saati kullanarak olayları zamana göre sıralamaya çalışırsanız, bu, iki ayrı saatteki olayların birbirine karışması anlamına gelir ve gerçekte oldukları sırayla görünmez.

Karşılaştırma yapmak gerekirse UTC bu sorunu yaşamaz ve temiz bir şekilde sipariş verir. Bu nedenle, sadece bir zaman dilimiyle çalışırken bile, DB'nin UTC'de zamanları depolamasını ve işlemesini ve giriş / gösterim için yerel zamana / zamandan dönüştürmesini istiyorsunuz. Bu, TIMESTAMP İLE ZAMAN BÖLGESİ'nin davranışıdı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.