Yanıtlar:
Farklılıklar, tarih / saat türleri için PostgreSQL belgelerinde ele alınmıştır . Evet, tedavisi TIMEveya TIMESTAMPbiri WITH TIME ZONEveyaWITHOUT TIME ZONE . Değerlerin nasıl saklandığını etkilemez; nasıl yorumlandıklarını etkiler.
Saat dilimlerinin bu veri türleri üzerindeki etkileri özellikle dokümanlarda yer almaktadır. Fark, sistemin değer hakkında makul bir şekilde bildikleri şeyden kaynaklanır:
Değerin bir parçası olarak bir saat dilimi ile, değer istemcide yerel bir saat olarak görüntülenebilir.
Değerin bir parçası olarak saat dilimi olmadan, varsayılan varsayılan saat dilimi UTC'dir, bu nedenle o saat dilimi için oluşturulur.
Davranış en az üç faktöre bağlı olarak değişir:
WITH TIME ZONEveya WITHOUT TIME ZONE).İşte bu faktörlerin kombinasyonlarını kapsayan örnekler:
foo=> SET TIMEZONE TO 'Japan';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+09
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 06:00:00+09
(1 row)
foo=> SET TIMEZONE TO 'Australia/Melbourne';
SET
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 00:00:00+11
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP;
timestamp
---------------------
2011-01-01 00:00:00
(1 row)
foo=> SELECT '2011-01-01 00:00:00+03'::TIMESTAMP WITH TIME ZONE;
timestamptz
------------------------
2011-01-01 08:00:00+11
(1 row)
timestamp with time zoneve timestamp without time zonePostgres'te * saat dilimi bilgilerinin gerçekte saklanmadığını anlamalıdır . Bunu veri türü doc sayfasına bir bakışta doğrulayabilirsiniz: Her iki tür de aynı sayıda sekizli alır ve kaydedilen değer aralığına sahiptir, bu nedenle zaman dilimi bilgilerini depolamak için yer yoktur. Sayfanın metni bunu doğrular. Bir yanlış adlandırma: "tz olmadan", "veri eklenirken ofseti yoksay" ve "tz ile", UTC'ye ayarlamak için ofseti kullan "anlamına gelir.
Söz konusu PostgreSQL belgelerinden daha anlaşılır bir şekilde açıklamaya çalışıyorum.
Her iki TIMESTAMPdeğişken de adların önerdiğine rağmen bir saat dilimi (veya bir uzaklık) depolamaz. Fark, depolama biçiminde değil, depolanan verilerin yorumlanmasında (ve amaçlanan uygulamada):
TIMESTAMP WITHOUT TIME ZONEyerel tarih saatini saklar (duvar takvimi tarihi ve duvar saati saati olarak da bilinir). Saat dilimi PostgreSQL'in anlayabileceği kadarıyla belirtilmemiş (uygulamanız ne olduğunu biliyor olsa da). Bu nedenle, PostgreSQL giriş veya çıkışta saat dilimi ile ilgili bir dönüştürme yapmaz. Değer veritabanına olarak girildiyse '2011-07-01 06:30:30', daha sonra hangi saat diliminde görüntülediğiniz hiçbir materyal yoksa, yine de 2011 yılı, 07, ay 01, 06 saat, 30 dakika ve 30 saniye (bazı formatlarda) der. Ayrıca, herhangi bir ofset veya giriş belirttiğiniz saat dilimi PostgreSQL tarafından göz ardı edilir, böylece '2011-07-01 06:30:30+00've '2011-07-01 06:30:30+05'sadece aynıdır '2011-07-01 06:30:30'. Java geliştiricileri için: buna benzer java.time.LocalDateTime.
TIMESTAMP WITH TIME ZONEUTC zaman çizgisinde bir nokta saklar. Görünüşü (kaç saat, dakika vb.) Saat diliminize bağlıdır, ancak her zaman aynı "fiziksel" anı ifade eder (gerçek bir fiziksel olayın anı gibi). Giriş dahili olarak UTC'ye dönüştürülür ve bu şekilde kaydedilir. Bunun için, girdinin ofseti bilinmelidir, bu nedenle girdi hiçbir kesin ofset veya zaman dilimi (zaman) içermediğinde '2011-07-01 06:30:30', PostgreSQL oturumunun geçerli saat diliminde olduğu varsayılır, aksi takdirde açıkça belirtilen ofset veya saat dilimi kullanılır. (olduğu gibi '2011-07-01 06:30:30+05'). Çıktı, PostgreSQL oturumunun geçerli saat dilimine dönüştürülmüş olarak görüntülenir. Java geliştiricileri için: java.time.Instant(ancak daha düşük çözünürlükle), ancak JDBC ve JPA 2 ile benzerdir .java.time.OffsetDateTimejava.util.Date veyajava.sql.Timestamp
Bazıları her iki TIMESTAMPvaryasyonun UTC tarih-saatini sakladığını söylüyor . Bir tür, ama bence bu şekilde koymak kafa karıştırıcı. UTC saat dilimi ile oluşturulan TIMESTAMP WITHOUT TIME ZONEa TIMESTAMP WITH TIME ZONE, yerel tarih saatindekilerle aynı yıl, ay, gün, saat, dakika, saniye ve mikrosaniye verir. Ancak, UTC yorumunun söylediği zaman çizgisindeki noktayı temsil etmek anlamına gelmez, sadece yerel tarih-saat alanlarının kodlanma şekli. (Gerçek zaman dilimi UTC olmadığından, zaman çizgisindeki bazı noktalar kümesi; ne olduğunu bilmiyoruz.)
TIMESTAMP WITH TIME ZONEyanı yoktur Instant. Her ikisi de UTC'de zaman çizelgesinde bir noktayı temsil eder. Instantbence OffsetDateTime, daha fazla kendi kendini belgelediği için tercih edilir : A TIMESTAMP WITH TIME ZONEher zaman veritabanından UTC olarak alınır ve Instanther zaman UTC'de bulunur, bu nedenle doğal bir eşleşme olurken, bir OffsetDateTimebaşka ofsetleri taşıyabilir.
OffsetDateTimeeşlenen Java türü olarak bahsedilmektedir . InstanceHala bir yerde gayri resmi olarak desteklenip desteklenmediğinden emin değilim .
'2011-07-01 06:30:30+00've '2011-07-01 06:30:30+05' yok sayılır ama yapmak mümkün insert into test_table (date) values ('2018-03-24T00:00:00-05:00'::timestamptz);ve doğru utc dönüştürecektir. tarih saat dilimi olmadan zaman damgasıdır. Zaman damgası ile zaman damgasının ana değerinin ne olduğunu anlamaya çalışıyorum ve sorun yaşıyorum.
::timestamptz. Bununla birlikte, dizeyi dönüştürürsünüz TIMESTAMP WITH TIME ZONEve daha sonra ne zaman dönüştürülürse WITHOUT TIME ZONE, oturum saat diliminizden (belki UTC) görüldüğü gibi o anın "duvar takvimi" gününü ve duvar saati saatini depolar. Yine de yalnızca belirtilmemiş ofseti olan (bölge yok) yerel bir zaman damgası olacaktır.
İşte size yardımcı olacak bir örnek. Saat dilimine sahip bir zaman damganız varsa, bu zaman damgasını başka bir saat dilimine dönüştürebilirsiniz. Temel saat dilimine sahip değilseniz, doğru şekilde dönüştürülmez.
SELECT now(),
now()::timestamp,
now() AT TIME ZONE 'CST',
now()::timestamp AT TIME ZONE 'CST'
Çıktı:
-[ RECORD 1 ]---------------------------
now | 2018-09-15 17:01:36.399357+03
now | 2018-09-15 17:01:36.399357
timezone | 2018-09-15 08:01:36.399357
timezone | 2018-09-16 02:01:36.399357+03
timestampve ne timestamptzanlama geldiğini anlamalısınız . timestamptzsaatin (UTC) mutlak bir noktası anlamına gelirken timestamp, belirli bir saat diliminde saatin ne gösterdiğini gösterir. Böylece, timestamptzbir saat dilimine dönüştürürken New York'ta saatin bu mutlak noktada ne gösterdiğini soruyorsunuz ? oysa a'yı dönüştürürken , New York'ta saat x'i gösterdiğinde mutlak noktanın netimestamp olduğunu soruyorsunuz ?
AT TIME ZONEZaten anlamak bile yapı, kendi teaser bir beyin WITHvs WITHOUT TIME ZONEtürlerini. Bu yüzden onları açıklamak için ilginç bir seçim. (: ( AT TIME ZONEbir WITH TIME ZONEzaman damgasını bir WITHOUT TIME ZONEzaman damgasına dönüştürür ve tam tersi ... tam olarak açık değildir.)
now()::timestamp AT TIME ZONE 'CST''CST' bölgesi için saatin hangi saatte yerel saatinizin şu anda gösterildiğini göstermediğiniz sürece mantıklı değil