tl; Dr.
Instant
ve LocalDateTime
tamamen farklı iki hayvandır: Biri bir anı temsil eder, diğeri bunu temsil etmez.
Instant
bir anı, zaman çizgisindeki belirli bir noktayı temsil eder.
LocalDateTime
tarih 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 LocalDateTime
sahiptir 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
Bir Instant
de 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
Sınıf OffsetDateTime
sı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ı, ZoneOffset
sınıf tarafından temsil edilir .
Saat-dakika-saniye sayısı sıfırsa, OffsetDateTime
a UTC ile aynı anı temsil eder Instant
.
ZoneOffset
ZoneOffset
Sınıf temsil eden bir ofset-UTC'den öncesinde UTC ya da arkasındaki UTC saat-dakika-saniye sayısı.
A ZoneOffset
sadece 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
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/Region
gibi America/Montreal
, Africa/Casablanca
ya da Pacific/Auckland
. Hiçbir zaman gibi 2-4 harfli bir kısaltma kullanın EST
veya IST
oldukları 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
ZonedDateTime
Kavramsal olarak Instant
bir 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. ZonedDateTime
Sı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
"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 Instant
ve ZonedDateTime
sı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 LocalDateTime
gelecekteki 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 LocalDateTime
ve ZoneId
a'yı ayrı olarak saklayın. Daha sonra, bir program oluştururken, anında LocalDateTime::atZone( ZoneId )
bir ZonedDateTime
nesne 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ü Instant
dan 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 LocalDateTime
saat 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
& LocalDateTime
sınıflarını daha geniş bir bağlama yerleştirmeye yardımcı olabilir .
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?
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 .