Java 8 java.time sınıfları neden getMillis () yöntemini kullanmıyor?


64

Java 8, java.time paketindeki tarihler ve saatler için tamamen yeni bir kütüphaneye sahiptir; bu, JodaTime'ı daha önce kullanmak zorunda kalan veya kendi tarih işleme yardımcı yöntemlerini kullanmakta güçlük çeken herkese çok açık bir şeydir. Bu paketteki birçok sınıf, zaman damgalarını temsil eder ve zaman damgasından getHour()saat almak, zaman damgasından getMinute()dakika getNano()almak, zaman damgasından nanos almak vb. Gibi yardımcı yöntemlere sahiptir .

getMillis()Zaman damgasının millisini elde etmek için bir metot bulunmadığını fark ettim . Bunun yerine, birinin yöntemini çağırması gerekir get(ChronoField.MILLI_OF_SECOND). Bana göre kütüphanede bir tutarsızlık gibi görünüyor. Böyle bir yöntemin neden eksik olduğunu bilen veya Java 8'in hala geliştirilme aşamasında olduğunu bilen var mı, daha sonra eklenmesi olasılığı var mı?

https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html

Burada tanımlanan sınıflar, instantlar, süreler, tarihler, saatler, zaman dilimleri ve dönemler dahil olmak üzere ana tarih-zaman kavramlarını temsil eder. Proleptik Gregoryen kurallarını izleyen fiili dünya takvimi olan ISO takvim sistemine dayanır. Tüm sınıflar değişmez ve iplikte güvenlidir.

Her tarih saat örneği, API'ler tarafından rahatlıkla kullanılabilen alanlardan oluşur. Alanlara daha düşük seviyeli erişim için java.time.temporalpakete bakın . Her sınıf, tarih ve saatlerin her türünü yazdırma ve ayrıştırma desteği içerir. java.time.formatÖzelleştirme seçenekleri için pakete bakın ...

Bu tür bir sınıf örneği:
https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html

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

LocalDateTimegenellikle yıl-ay-gün-saat-dakika-saniye olarak görülen bir tarih-saati 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 hassasiyetine göre gösterilir. Örneğin, "2 Ekim 2007, 13: 45.30.123456789" değeri bir LocalDateTime...


get()Tek tek, benzersiz adlar vermek yerine, tüm denilen bir çok yöntemi çözmek için polimorfizm kullanmak istiyormuş gibi görünüyorlar . Eğer sizi rahatsız ediyorsa, orijinal sınıfı miras alan bir sınıf yazın ve kendi getMillis()yönteminizi yeni sınıfa koyun .
Robert Harvey,

@RobertHarvey java.time paketindeki çoğu sınıf değişmezdir ve genişletilemez.
assylias

2
@RobertHarvey Benim için soru, bunu nasıl çözebilirim değil. Sadece tuhaf bir tutarsızlık yarattı ve bunun ilginç bir açıklaması olup olmadığını merak ettim.
Tarmo

Bazı mimarilerin / OS'lerin milisaniyeleri güvenilir bir şekilde desteklemediği fikrine sahibim. Başka bir deyişle, sistem zamanı milisaniyeye, yalnızca santi veya karargâhına geri alınamaz.
Marco

Bkz stackoverflow.com/a/23945792/40064 aracılığıyla bunu yapmak için bir yol üzerinde Instantsınıfın
Wim Deblauwe

Yanıtlar:


63

JSR-310 , milisaniye yerine nanosaniye dayalıdır. Bu nedenle, en az sayıda mantıklı yöntem kümesi saat, dakika, saniye ve nanosaniye'ye dayanmaktadır. Bir nanosaniye üssü olma kararı, projenin orijinal kararlarından biriydi ve kesinlikle doğru olduğuna inandığım karardı.

Millis için bir yöntem eklemek, nanosaniye ile örtüşürdü, bariz olmayan bir yoldur. Kullanıcılar, nano alanın örneğin nano saniyeli mi yoksa milli nano-mi olduğunu düşünmek zorunda kalacaklardı. Kafa karıştırıcı ek bir yöntem eklemek arzu edilmez, bu yüzden yöntem ihmal edildi. Belirtildiği gibi, alternatif get(MILLI_OF_SECOND)mevcuttur.

FWIW, getMillis()yöntemi gelecekte eklemeye karşı çıkacağım .


1
Bu soruya bazı çok iyi cevaplar aldım ancak kısa olduğu için cevabınız benim favorim ve yine de çok iyi bir noktaya değiniyor ve bu yaklaşımın gereği beni gerçekten ikna ediyor. Teşekkür ederim.
Tarmo

12
@ s3ib, eğer yanıtlayıcının profilini kontrol edersen, sorduğun API için bir teknik özellik adayı olduğunu göreceksin . Bu alır gibi yetkili bir cevap yapar değil mi :)
gnat

Öyleyse yapmak zorunda instant.getEpochSecond * 1000 + instant.getNano / 1000000kalmanız, eski (bu noktada, hepsi) Java API'leri, Javascript, vb.
nilskp

10
hayır, bu durumda sadece instant.toEpochMilli () download.java.net/jdk8/docs/api/java/time/…
JodaStephen

20

OpenJDK'nın bir parçası olmadan önce, threeten github'taydı ve ondan önce sourceforge'deydi. O zamanlar, jsr-310'da bir şartname lideri olan Stephen Colebourne, sourceforge sitesinde bulabileceğiniz bir anket yaptı .

The fourth question on the survey covered the method names for LocalTime:
1) getHourOfDay(), getMinuteOfHour(), getSecondOfMinute(), getNanoOfSecond()
2) getHour(), getMinute(), getSecond(), getNanoOfSecond()
3) getHour(), getMinute(), getSecond(), getNano()
4) another idea

sadece% 6,23'ü cevap 4'ü seçti ve aralarında yaklaşık% 15'i a getMillis(), yani toplam oyların% 1'inden azını istedi .

Muhtemelen bu yüzden getMillisilk sırada yer almadı ve openjdk posta listesiyle ilgili hiçbir şey bulamadım, bu yüzden mesele daha sonra tartışılmayacaktı.


3
İnsanlara birkaç seçenek vermenin, ideal tercihleri ​​"öteki" altında olsa bile, bu seçimlerden birini seçmelerinin daha muhtemel olduğunu düşünüyorum. Yine de yanılıyor olabilirim.
Allon Guralnek,

2
@AllonGuralnek Evet, kesinlikle - ancak milisaniye bileşeni Date API'sinde önemliydi çünkü her şey çağdan beri bir kaç milisaniye dayanıyordu. Yeni API'de IMO ile daha az ilgilidir. Çoğu durumda, ikinci bir hassasiyete veya mevcut en iyi hassasiyete ihtiyacınız vardır (nanos). Yanılıyor olabilirim.
assylias

1
Bu , hangi yöntemlerin bulunması gerektiğini değil, yöntemlerin isimlendirilmesi hakkında soru soruyor gibi görünüyor .
svick

1
Doğru, üzgünüm, açık değildim: Anketten gelen soruyu kastediyor, bu soruya doğrudan bakmadığı anlamına geliyordu.
Şubat'ta svick

15

Belirsiz UTC zamanlarını temsil eden sınıflar (bunlar Instant, OffsetDateTime, ZonedDateTime), Java döneminden mutlak ofsete erişmek için, yani java.util.Date'de 'milisaniye zamanı' olarak adlandırdığınız, yani java.util.Date dediğiniz şey için iki yardımcı yönteme sahiptir. milisaniyede almak

long getEpochSecond()
int getNano()

1000L*getEpochSecond() + getNano() / 1000000L;

Bunun yerine neden seçildiğinin bazı nedenleri , bazıları kolaylık sağlamak için çıkardığım jsr 310 posta listesindelong getEpochMillis() tartışıldı :

milisaniye hassasiyetinin yeterli olmayacağını varsaymak makul görünüyor. Ancak, nanosaniye hassasiyetinden daha büyük bir şey aşırı görünüyor

...

Bunu uygulamak için tercih ettiğim seçenek 64 bit uzun saniye (imzalı) + 32 bit int nanosaniye (imzasız) olacaktır.

...

Bölünmenin, bilimdeki resmi SI zaman birimi ve evrensel olarak kabul görmüş en standart olan ikinci seviyede olmasını tercih ediyorum.

Gün düzeyinde bölünme, sıçrama saniye işlemlerini gerçekleştirmediği için instantlar için sorunludur. Milisaniye düzeyinde bölmek, Java'nın geri kalanıyla biraz daha iyi bütünleşirken, oldukça garip görünüyor. Ayrıca, desteklenen aralıkta kaybeder.

Önerilen şekilde ikinciye bölmek, 290 milyar yıl boyunca bir dizi nanosaniye instantı verir. Hiç kimse bu hassasiyeti bu zaman dilimi aralığında kullanmamalı olsa da, onu desteklemekten daha kolay bir şekilde desteklemesini öneririm.

Geliştiricilerin çeşitli seçenekler arasındaki farkları anlamaya çalışacaklarını ve sadece yeni sınıfları (yanlış) kullanmayacaklarını umarak, java.util.Date'den JSR310 sınıflarına kasıtlı olarak dönüştürmeyi zorlaştırmak için başka bir neden olduğunu hissediyorum.

LocalDateTimeSınıfın neden bu metotlara sahip olmadığına dair - muhtemelen orada LocalDateTimebulunamamaktadır, çünkü hangi bölgede bulunduğunuzu veya UTC ofsetinizin ne olduğuna karar verene kadar UTC zaman çizelgesine bağlı değildir, kendiniz hangi noktada OffsetDateTimeveya ZonedDateTime(her ikisi de gerekli yöntemlere sahip).

Alternatif olarak, milisaniye cinsinden bir tür süre elde etmek için kendinize ait bir LOCAL_EPOCHsabit tanımlayabilir 1970-01-01T00:00:00ve daha sonra bir şeyi yapabilirsiniz MILLIS.between(LOCAL_EPOCH, localTime). Bununla birlikte, bu değer, yerel saatinizi UTC saati olarak tanımlamazsanız System.currentTimeMilliseconds()ya da tarafından döndürülen herhangi bir değerle uyumlu olmayacaktır java.util.Date.getTime(); ancak bu durumda, InstantO'yu veya ZoneOffset.UTC ile OffsetDateTime özelliğini de kullanabilirsiniz.


4
" LocalDateTime UTC zaman çizelgesine bağlı olmadığından muhtemelen orada olamazlar " => bir LocalDateTime kesinlikle getMillistemelde döndürecek bir yönteme sahip olabilirdi getNanos()/1e6- zamanın anında olmadığı gerçeği bir milisaniye olmasını engellemez bileşen.
assylias,

2
Başka bir nedenin bilerek java.util.Date'den JSR310 sınıflarına dönüştürülmesini zorlaştırmak olduğunu hissediyorum ” Muhtemelen doğru, ama ne yazık ki "dönemden beri millis" zamanın neredeyse evrensel bir temsili haline geldi, yani ihtiyacı olan her şey için Eski Java API'leri, Javascript, başka bir şeyle iletişim kurmak için bu ihmal gerçek bir zorluktur.
nilskp

Kod pasajınız üstte yanlıştır - getEpochSecond'u 1000 ile çarpmanız gerekir.
Tin Man

@ nilskp Onlar iki farklı şey. Soru, getMillis()saniyenin getMillis'inde olduğu gibi soruyor ; "Çağdan beri millilerden" bahsediyorsun. Eski kabul edilen cevabında açıklandığı gibi yoktur. İkincisi olarak zaten mevcuttur Instant.toEpochMillis(). Yani, bir için LocalDateTime, gider:ldt.toInstant(offset).toEpochMillis()
SusanW
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.