Instant ve LocalDateTime arasındaki fark nedir?


256

Bunu biliyorum:

  • Instant , bilgi işlem için bir "teknik" zaman damgası temsilidir (nanosaniye).
  • LocalDateTime , insanlar için saat dilimlerini içeren tarih / saat temsilidir.

Yine de, IMO'nun çoğu, uygulama kullanım durumlarının çoğu için tür olarak alınabilir. Örneğin: Şu anda tarihlere göre bir sonraki çalıştırmayı hesaplamam gereken bir toplu iş çalıştırıyorum ve bu iki tür arasında (Anında ve zaman dilimi bölümünün nanosaniye hassas avantajı dışında) artılarını / eksilerini bulmakta zorlanıyorum / LocalDateTime).

Yalnızca Instant veya LocalDateTime öğesinin kullanılması gereken bazı uygulama örneklerini adlandırabilir misiniz?

Düzenleme: Hassasiyet ve zaman dilimi ile ilgili LocalDateTime için yanlış belgelere dikkat edin


Anında Arama daha basittir ve UTC için standardı sarar. Toplu bir cron için bu kadar mantıklı bir seçim değil.
Joop Eggen

37
Yanlış tanım. LocalDateTimeyok değil bir saat dilimi var!
Basil Bourque

Yanıtlar:


834

Java'da hem modern hem de eski tüm tarih-saat türlerinin tablosu

tl; Dr.

Instantve LocalDateTimetamamen farklı iki hayvandır: Biri bir anı temsil eder, diğeri bunu temsil etmez.

  • Instant bir anı, zaman çizgisindeki belirli bir noktayı temsil eder.
  • LocalDateTimetarih ve günün saatini temsil eder. Ancak bir saat dilimi veya UTC'den uzak olan bu sınıf bir anı temsil edemez . Dünyadaki tüm zaman dilimlerinin aralığı olan yaklaşık 26 ila 27 saat aralığında potansiyel anları temsil eder .

Yanlış Varsayım

LocalDateTime daha çok insanlar için saat dilimlerini içeren tarih / saat temsilidir.

Sizin ifade hatalıdır: Bir LocalDateTimesahiptir hiçbir zaman dilimini . Saat dilimi olmaması, o sınıfın tüm noktasıdır.

Bu sınıfın dokümanı için:

Bu sınıf bir saat dilimini saklamaz veya temsil etmez. Bunun yerine, doğum günleri için kullanıldığı gibi, bir duvar saatinde görüldüğü gibi yerel saatle birlikte tarihin bir açıklamasıdır. Ofset veya zaman dilimi gibi ek bilgiler olmadan zaman çizgisinde bir anı temsil edemez.

Yani Local…“imarlı değil, ofsetsiz” demek.

Instant

resim açıklamasını buraya girin

Bir Instantde zaman çizelgesi üzerinde bir andır UTC , bir sayım nanosaniye 1970 UTC (temelde, asıl mesele detayları için sınıf belgeye bakın) ilk andan çağında beri. İş mantığınızın, veri depolama alanınızın ve veri alışverişinizin çoğu UTC'de olması gerektiğinden, bu sık kullanılan bir sınıftır.

Instant instant = Instant.now() ;  // Capture the current moment in UTC.

OffsetDateTime

resim açıklamasını buraya girin

Sınıf OffsetDateTimesınıfı, bir anı UTC'nin önünde veya arkasında birkaç saat-dakika-saniye bağlamıyla tarih ve saat olarak temsil eder. Ofset miktarı, saat-dakika-saniye sayısı, ZoneOffsetsınıf tarafından temsil edilir .

Saat-dakika-saniye sayısı sıfırsa, OffsetDateTimea UTC ile aynı anı temsil eder Instant.

ZoneOffset

resim açıklamasını buraya girin

ZoneOffsetSınıf temsil eden bir ofset-UTC'den öncesinde UTC ya da arkasındaki UTC saat-dakika-saniye sayısı.

A ZoneOffsetsadece birkaç saat-dakika-saniye, başka bir şey değil. Bir bölge çok daha fazladır, bir adı ve dengelenecek değişiklik geçmişine sahiptir. Yani bir bölge kullanmak her zaman sadece bir ofset kullanmak için tercih edilir.

ZoneId

resim açıklamasını buraya girin

Bir saat dilimiZoneId sınıf tarafından temsil edilir .

Örneğin Paris'te Montréal'den daha erken yeni bir gün geçiyor . Bu nedenle , belirli bir bölge için öğle saatlerini (Güneş doğrudan yukarıdayken) daha iyi yansıtmak için saatin ellerini hareket ettirmemiz gerekir . Batı Avrupa / Afrika'daki UTC çizgisinden doğuya / batıya doğru ne kadar uzak olursa ofset o kadar büyük olur.

Bir saat dilimi, yerel bir topluluk veya bölge tarafından uygulanan ayarlamalar ve anormallikleri ele almak için bir dizi kuraldır. En yaygın anomali, Yaz Saati Uygulaması (DST) olarak bilinen çok popüler bir oyundur .

Bir saat dilimi geçmiş kuralların, mevcut kuralların ve yakın gelecek için onaylanan kuralların geçmişine sahiptir.

Bu kurallar beklediğinizden daha sık değişir. Tarih-saat kütüphanenizin kurallarını, genellikle 'tz' veritabanının bir kopyasını güncel tuttuğunuzdan emin olun . Oracle bir Timezone Updater Tool yayınlayarak Java 8'de güncel kalmak her zamankinden daha kolay .

Bir belirtme uygun bir zaman dilimi adı biçiminde Continent/Regiongibi America/Montreal, Africa/Casablancaya da Pacific/Auckland. Hiçbir zaman gibi 2-4 harfli bir kısaltma kullanın ESTveya ISToldukları gibi değil , gerçek zaman dilimleri, değil standardize ve hatta benzersiz değil (!).

Saat Dilimi = Ofset + Ayarlama Kuralları

ZoneId z = ZoneId.of( Africa/Tunis ) ; 

ZonedDateTime

resim açıklamasını buraya girin

ZonedDateTimeKavramsal olarak Instantbir atanmış olarak düşünün ZoneId.

ZonedDateTime = (Anında + ZoneId)

Geçerli anı, belirli bir bölgenin (bir zaman dilimi) halkının kullandığı duvar saati zamanında görüldüğü gibi yakalamak için:

ZonedDateTime zdt = ZonedDateTime.now( z ) ;  // Pass a `ZoneId` object such as `ZoneId.of( "Europe/Paris" )`. 

Neredeyse tüm arka uç, veritabanı, iş mantığı, veri kalıcılığı, veri alışverişi UTC olmalıdır. Ancak kullanıcılara sunum için kullanıcının beklediği bir saat dilimine ayarlamanız gerekir. ZonedDateTimeSınıfın amacı ve bu tarih-saat değerlerinin Dize temsillerini oluşturmak için kullanılan biçimlendirici sınıflarıdır .

ZonedDateTime zdt = instant.atZone( z ) ;
String output = zdt.toString() ;                 // Standard ISO 8601 format.

Öğesini kullanarak yerelleştirilmiş biçimde metin oluşturabilirsiniz DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH ) ; 
String outputFormatted = zdt.format( f ) ;

mardi 30 avril 2019 à 23 sa 22 dk 55 s heure de l'Inde

LocalDate, LocalTime,LocalDateTime

Yalnızca <code> LocalDate </code> için bir takvim gösteren diyagram.

<code> LocalTime </code> için yalnızca bir saat gösteren diyagram.

<code> LocalDateTime </code> için bir takvim artı saati gösteren diyagram.

"Yerel" tarih saat sınıfları, LocalDateTime, LocalDate, LocalTime, yaratık farklı bir türüdür. Herhangi bir bölgeye veya saat dilimine bağlı değildir. Zaman çizelgesine bağlı değiller. Siz onları zaman çizelgesinde bir nokta bulmak için bir bölgeye uygulayana kadar gerçek bir anlamı yoktur .

Bu sınıf adlarındaki “Yerel” kelimesi, başlatılmayanlara karşı sezgisel olabilir. Sözcük, herhangi bir yer veya her yer anlamına gelir , ancak belirli bir yer anlamına gelmez .

Bu nedenle, iş uygulamaları için "Yerel" türler, zaman çizelgesinde belirli bir anı değil, yalnızca olası bir tarih veya saat hakkındaki genel fikri temsil ettiği için sıklıkla kullanılmaz. İş uygulamaları, bir faturanın geldiği anı, nakliye için gönderilen bir ürünü, bir çalışanı işe aldığını veya taksi garajdan ayrıldığını umursuyor. Bu yüzden iş uygulaması geliştiricileri en yaygın olarak sınıfları kullanır Instantve ZonedDateTimesınıflar.

Peki ne zaman kullanırdık LocalDateTime? Üç durumda: belirli bir tarih ve günün saatini birden fazla konuma uygulamak istediğimiz, randevu aldığımız veya planladığımız henüz belirlenmemiş bir saat dilimimiz. Bu üç vakanın hiçbirinin zaman çizelgesinde belirli bir belirli nokta olmadığına, bunların hiçbirinin bir an olmadığına dikkat edin.

Günün bir saati, birden çok an

Bazen belirli bir tarihte belirli bir günün saatini temsil etmek isteriz, ancak bunu saat dilimleri boyunca birden çok bölgeye uygulamak isteriz.

Örneğin, "Noel 25 Aralık 2015 gece yarısı başlar" dır LocalDateTime. Gece yarısı Paris'te Montréal'den farklı anlarda, tekrar Seattle ve Auckland'da farklı anlarda .

LocalDate ld = LocalDate.of( 2018 , Month.DECEMBER , 25 ) ;
LocalTime lt = LocalTime.MIN ;   // 00:00:00
LocalTime ldt = LocalDateTime.of( ld , lt ) ;  // Xmas morning anywhere. 

Başka bir örnek, "Acme Company, dünya çapında her fabrikada öğlen 12: 30'da başlayacak bir politikaya sahiptir LocalTime. Gerçek anlamda, Stuttgart fabrikasında 12:30 veya Rabat fabrikasında 12:30 veya Sydney fabrikasında 12:30 anını belirlemek için zaman çizelgesine uygulamanız gerekir .

Rezervasyon randevuları

Kullanılacak diğer bir durum da LocalDateTimegelecekteki olayları rezerve etmektir (örn: Diş Hekimi randevuları). Bu randevular, gelecekte politikacıların saat dilimini yeniden tanımlamasını riske atacağınız kadar uzak olabilir. Politikacılar genellikle çok az uyarı verir, hatta hiç uyarı vermezler. Politikacıların saatle nasıl oynayabileceklerine bakılmaksızın "23 Ocak önümüzdeki 15:00" demek isterseniz, o zaman bir anı kaydedemezsiniz; bu bölge Yaz Saati Uygulamasını benimsemiş veya bırakmışsa saat 15:00 ya da 16:00 olur. Örneğin.

Randevular için, a LocalDateTimeve ZoneIda'yı ayrı olarak saklayın. Daha sonra, bir program oluştururken, anında LocalDateTime::atZone( ZoneId )bir ZonedDateTimenesne oluşturmak için çağrı yaparak bir anı belirleyin .

ZonedDateTime zdt = ldt.atZone( z ) ;  // Given a date, a time-of-day, and a time zone, determine a moment, a point on the timeline.

Gerekirse, UTC'ye ayarlayabilirsiniz. Bir Özü Instantdan ZonedDateTime.

Instant instant = zdt.toInstant() ;  // Adjust from some zone to UTC. Same moment, same point on the timeline, different wall-clock time.

Bilinmeyen bölge

Bazı insanlar LocalDateTimesaat diliminin veya ofsetin bilinmediği bir durumda kullanabilirler .

Bu davayı uygunsuz ve akılsız olarak düşünüyorum. Bir bölge veya ofset amaçlanıyor ancak belirsizse, verileriniz kötüdür. Bu, amaçlanan para birimini bilmeden bir ürünün fiyatını depolamak gibi bir şey olacaktır. İyi bir fikir değil.

Tüm tarih-saat türleri

Tamlık için, Java'da hem modern hem de eski olan ve SQL standardı tarafından tanımlanan tüm olası tarih-saat türlerinin bir tablosu. Bu, Instant& LocalDateTimesınıflarını daha geniş bir bağlama yerleştirmeye yardımcı olabilir .

SQL standardının yanı sıra Java'daki (hem modern hem de eski) tüm tarih-saat türlerinin tablosu.

JDBC 4.2 tasarımında Java ekibi tarafından yapılan garip seçimlere dikkat edin. En çok kullanılan iki sınıf hariç tüm java.time zamanlarını desteklemeyi seçtiler : Instant& ZonedDateTime.

Ama endişelenme. Kolayca ileri geri dönüştürebiliriz.

Dönüştürme Instant.

// Storing
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
Instant instant = odt.toInstant() ;

Dönüştürme ZonedDateTime.

// Storing
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject(  , odt ) ;

// Retrieving
OffsetDateTime odt = myResultSet.getObject(  , OffsetDateTime.class ) ;
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = odt.atZone( z ) ; 

Hakkında java.time

Java.time çerçevesi daha sonra Java 8 ve yerleşiktir. Bu sınıflar zahmetli eski yerini mirası gibi tarih-saat sınıfları java.util.Date, Calendar& SimpleDateFormat.

Artık bakım modunda olan Joda-Time projesi java.time sınıflarına geçişi tavsiye ediyor .

Daha fazla bilgi için Oracle Eğiticisine bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310'dur .

Sen değiştirebilir java.time sizin veritabanı ile doğrudan nesneleri. JDBC 4.2 veya üzeri ile uyumlu bir JDBC sürücüsü kullanın . Dizeye gerek yok, sınıflara gerek yok .java.sql.*

Java.time sınıflarını nereden edinebilirsiniz?

Hangi Java veya Android sürümüyle kullanılacak java.time kütüphanesinin tablosu

ThreeTen-Ekstra proje ek sınıfları ile java.time uzanır. Bu proje, java.time'a gelecekteki olası eklemeler için bir kanıt zeminidir. Burada bazı yararlı sınıfları gibi bulabilir Interval, YearWeek, YearQuarter, ve daha .


40
Mükemmel cevap. Bence bazı karışıklıklar (en azından benim) Localadlandırmadan geliyor . Benim sezgim Local, nerede olduğum ve ne zaman olduğum (?!) İle ilgili anlamına gelir, bu da gerçekten a'nın ne olacağına inanmamı sağlar ZonedDateTime.
mkobit

4
Evet kafa karıştırıcı. Bu nedenle java.time , "Yerel" sınıflardan farkı vurgulamak için DateTimeselefi Joda-Time (üreten ZonedDateTime) tarafından kullanılan sınıf adına "Zoned" kelimesini akıllıca ekledi . "Yerel" adını "belirli bir bölgeye uygulanması gerekenler" için kısayol olarak düşünün.
Basil Bourque

2
Kelime ile ön ek yapmak, Localbir şekilde daha iyi bir kelime seçimi olabileceğini düşünmeme rağmen, java.util paketinden ayırmanın bir yolu olabilir.
vphilipnyc

2
@simonh Aksine… Bu yeni çalışan, hayat sigortası da dahil olmak üzere faydalarını tanımlayan işe alma kağıtlarını imzaladığında ve sonra yeni bir işe alım sadece bir kamyonun çarpması ve öldürülmesi için bir kahveye adım attığında, bu kadar çok insan olacak İnsan Kaynakları yöneticileri, sigorta acenteleri ve avukatların yeni istihdamın yürürlüğe girdiği kesin anı bilmek isteyeceklerdir.
Basil Bourque

2
@simonh Evet, "yerel" tarih saatinin uygun olduğu durumlar vardır. Cevabımda bahsedilenlerin yanı sıra, iş dünyasındaki bir başka yaygın durum da, atamaların gelecekte birkaç aydan daha uzun bir süre içinde yapılması ve politikacıların zaman dilimi kurallarını değiştirebilmeleri, genellikle çok az bir önyargı ile. Politikacılar sık ​​sık bu değişiklikleri Yaz Saati Uygulamasını açarken / kapatırken veya DST'de sürekli açık / kapalı kalırken tarihleri ​​değiştirme gibi yaparlar.
Basil Bourque

20

Bir temel fark olduğunu Localparçası LocalDateTime. Almanya'da yaşıyor ve bir LocalDateTimeörnek oluşturuyorsanız ve başka biri ABD'de yaşıyor ve aynı anda başka bir örnek oluşturuyorsa (saatler düzgün ayarlanmışsa) - bu nesnelerin değeri aslında farklı olacaktır. Bu, Instantsaat diliminden bağımsız olarak hesaplanan için geçerli değildir .

LocalDateTimetarih ve saati saat dilimi olmadan depolar, ancak başlangıç ​​değeri saat dilimine bağlıdır. Instantdeğil.

Ayrıca, LocalDateTimegün, saat, ay gibi tarih bileşenlerini işlemek için yöntemler sağlar. An Instantdeğil.

Instant'nın nanosaniye hassasiyet avantajı ve LocalDateTime'ın zaman dilimi kısmı dışında

Her iki sınıf da aynı hassasiyete sahiptir. LocalDateTimesaat dilimini saklamaz. Javadocs'u dikkatlice okuyun, çünkü bu tür geçersiz varsayımlarla büyük bir hata yapabilirsiniz: Instant ve LocalDateTime .


bölge + hassasiyeti üzerindeki kısmı yanlış okuduğum için üzgünüm. Yukarıdaki gönderiyi tekrarladığım için üzgünüm: Tek bir saat dilimi uygulaması göz önüne alındığında, hangi kullanım durumlarında LocalDateTime'ı tercih edersiniz?
manuel aldana

1
Tarihlere ve / veya zamanlara ihtiyacım olduğunda LocalDateTime'ı alırdım. Saat, dakika vb. Örneğin, yürütme sürelerini ölçmek için Anında kullanırım veya o zaman orada gerçekleşen dahili bir alan alanını depolarım. Sizin durumunuzda olduğu gibi sonraki koşuları mı hesaplıyorsunuz? LocalDateTime uygun görünüyor, ancak bu bir görüş. Belirttiğiniz gibi, her ikisi de kullanılabilir.
Dariusz

Daha fazla ayrıntı verebilir misiniz LocalDateTime stores date and time without timezone, but it's initial value is timezone dependent? başlangıç ​​değeri nedir ve saat dilimi nasıl bağımlıdır? Teşekkürler.
Maksimum

12

Yanılıyorsunuz LocalDateTime: Herhangi bir saat dilimi bilgisi saklamaz ve nanosaniye hassasiyete sahiptir. Javadoc'tan alıntı yapma (vurgu mayını):

2007-12-03T10: 15: 30 gibi ISO-8601 takvim sisteminde saat dilimi olmayan bir tarih-saat .

LocalDateTime, genellikle yıl-ay-gün-saat-dakika-saniye olarak görülen bir tarih-zamanı temsil eden değişmez bir tarih-saat nesnesidir. Yılın günü, haftanın günü ve yılın haftası gibi diğer tarih ve saat alanlarına da erişilebilir. Zaman nanosaniye hassasiyetle temsil edilir . Örneğin, "2 Ekim 2007, 13: 45.30.123456789" değeri bir LocalDateTime içinde saklanabilir.

İkisi arasındaki fark Instant, Çağ'dan (01-01-1970) bir sapmayı temsil eder ve bu nedenle zaman çizgisinde belirli bir anı temsil eder. InstantDünyanın iki farklı yerinde aynı anda yaratılan iki nesne tamamen aynı değere sahip olacaktır.


Tek bir saat dilimi uygulaması göz önüne alındığında, hangi kullanım senaryolarında LocalDateTime'ı tercih edersiniz veya tam tersi?
manuel aldana

3
@manuelaldana Daha çok bir zevk meselesi. Kullanıcı ile ilgili herhangi bir şey (doğum günü ...) için LocalDateTime ve makine ile ilgili (yürütme süresi ...) herhangi bir şey için Instant tercih ederim.
Tunaki

2
@manuelaldana Var olmayan bir tek saat dilimi uygulaması nadirdir. Yerel Barok müzik kulübünüz için çırpılmış küçük bir uygulama için saat dilimlerini görmezden gelebilirsiniz. Ancak, seyahat eden kişilere (ve saat dilimleri arası) bir etkinlik yayınlamanız gerektiğinde, bu verilerin bir takvim saatine bağlı olmasını isterler, böylece takvim uygulamaları gerektiği gibi ayarlanabilir. Tüm uygulamalarınızda saat dilimleriyle düzgün çalışmayı öğrenmenizi öneririm.
Basil Bourque

@Tunaki Son paragrafta 'ofset' kelimesini kullanmanız dikkat dağıtıcı. Bu kelimenin tarih-saat çalışmasında belirli bir anlamı vardır, bu yüzden burada bu bağlamda kullanılması yararsız olabilir.
Basil Bourque

0

Instant asal meridyen (Greenwich) üzerindeki zamana karşılık gelir.

Oysa LocalDateTimeOS saat dilimi ayarlarına göre ve

ofset veya saat dilimi gibi ek bilgiler olmadan bir anı temsil edemez.


2
Anında Arama, GMT yerine UTC'yi temel alır.
Torsten Ojaperv
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.