tl; Dr.
Ana makinede sistem saatini manuel olarak değiştirmenin dışında, System.currentTimeMillis aracılığıyla sunulan geçerli saati geçersiz kılmanın kod içinde veya JVM bağımsız değişkenleriyle bir yolu var mı?
Evet.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock Java.time içinde
Sahte tarih-saat değerleriyle testi kolaylaştırmak için tak-çıkar saat değişimi sorununa yeni bir çözümümüz var . Java.time paket içinde Java 8 soyut bir sınıf içeren java.time.Clockbir hedefiyle,:
alternatif saatlerin gerektiğinde ve gerektiği zaman takılmasına izin vermek için
Kendi uygulamanızı takabilirsiniz Clock, ancak muhtemelen ihtiyaçlarınızı karşılamak için zaten yapılmış bir uygulama bulabilirsiniz. Size kolaylık sağlamak için, java.time özel uygulamalar sağlamak için statik yöntemler içerir. Bu alternatif uygulamalar, test sırasında değerli olabilir.
Kadans değişikliği
Çeşitli tick…yöntemler, geçerli anı farklı bir kadansla artıran saatler üretir.
Varsayılan , Java 8'de milisaniyeClock kadar sık ve Java 9'da nanosaniye kadar (donanımınıza bağlı olarak) güncellenen bir zamanı bildirir . Gerçek geçerli anın farklı bir ayrıntı düzeyinde bildirilmesini isteyebilirsiniz.
Yanlış saatler
Bazı saatler yalan söyleyebilir ve ana işletim sisteminin donanım saatinden farklı bir sonuç üretebilir.
fixed - Değişmeyen (artmayan) tek bir anı mevcut an olarak bildirir.
offset- Geçerli anı bildirir, ancak geçirilen Durationbağımsız değişken tarafından değiştirilir .
Örneğin, bu yıl en erken Noel'in ilk anını kilitleyin. başka bir deyişle, Noel Baba ve ren geyikleri ilk durduklarında . En erken saat dilimi bugünlerde gibi görünüyor Pacific/Kiritimatiat +14:00.
LocalDate ld = LocalDate.now( ZoneId.of( "America/Montreal" ) );
LocalDate xmasThisYear = MonthDay.of( Month.DECEMBER , 25 ).atYear( ld.getYear() );
ZoneId earliestXmasZone = ZoneId.of( "Pacific/Kiritimati" ) ;
ZonedDateTime zdtEarliestXmasThisYear = xmasThisYear.atStartOfDay( earliestXmasZone );
Instant instantEarliestXmasThisYear = zdtEarliestXmasThisYear.toInstant();
Clock clockEarliestXmasThisYear = Clock.fixed( instantEarliestXmasThisYear , earliestXmasZone );
Her zaman aynı ana dönmek için o özel sabit saati kullanın. Kiritimati'de Noel gününün ilk anını alıyoruz , UTC'nin duvar saati on dört saat önce, 24 Aralık'ın önceki günü saat 10: 00'da gösteriliyor.
Instant instant = Instant.now( clockEarliestXmasThisYear );
ZonedDateTime zdt = ZonedDateTime.now( clockEarliestXmasThisYear );
instant.toString (): 2016-12-24T10: 00: 00Z
zdt.toString (): 2016-12-25T00: 00 + 14: 00 [Pacific / Kiritimati]
IdeOne.com'da canlı koda bakın .
Gerçek zaman, farklı saat dilimi
ClockUygulama tarafından hangi saat diliminin atanacağını kontrol edebilirsiniz . Bu, bazı testlerde faydalı olabilir. Ancak bunu, isteğe bağlı ZoneIdveya ZoneOffsetbağımsız değişkenleri her zaman açıkça belirtmeniz gereken üretim kodunda önermiyorum .
UTC'nin varsayılan bölge olmasını belirtebilirsiniz.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
Herhangi bir belirli saat dilimini belirtebilirsiniz. Bir belirtme uygun bir zaman dilimi adı biçiminde continent/regiongibi America/Montreal, Africa/Casablancaya da Pacific/Auckland. Hiçbir zaman gibi 3-4 harfli bir kısaltma kullanın ESTveya ISToldukları gibi değil , gerçek zaman dilimleri, değil standardize ve hatta benzersiz değil (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
JVM'nin geçerli varsayılan saat diliminin belirli bir Clocknesne için varsayılan olması gerektiğini belirtebilirsiniz .
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Karşılaştırmak için bu kodu çalıştırın. Hepsinin aynı anı, zaman çizelgesinde aynı noktayı bildirdiklerini unutmayın. Sadece duvar saati süresinde farklılık gösterirler ; başka bir deyişle, aynı şeyi söylemenin üç yolu, aynı anı göstermenin üç yolu.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles bu kodu çalıştıran bilgisayardaki JVM geçerli varsayılan bölgesiydi.
zdtClockSystemUTC.toString (): 2016-12-31T20: 52: 39.688Z
zdtClockSystem.toString (): 2016-12-31T15: 52: 39.750-05: 00 [Amerika / Montreal]
zdtClockSystemDefaultZone.toString (): 2016-12-31T12: 52: 39.762-08: 00 [Amerika / Los_Angeles]
InstantSınıf tanımı gereği UTC her zaman. Yani bölgeyle ilgili bu üç Clockkullanım tamamen aynı etkiye sahiptir.
Instant instantClockSystemUTC = Instant.now ( Clock.systemUTC () );
Instant instantClockSystem = Instant.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Instant instantClockSystemDefaultZone = Instant.now ( Clock.systemDefaultZone () );
instantClockSystemUTC.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystem.toString (): 2016-12-31T20: 52: 39.763Z
instantClockSystemDefaultZone.toString (): 2016-12-31T20: 52: 39.763Z
Varsayılan saat
Varsayılan olarak kullanılan gerçekleme, tarafından Instant.nowdöndürülendir Clock.systemUTC(). Bu, a belirtmediğinizde kullanılan uygulamadır Clock. Java 9 kaynak kodunun ön sürümündeInstant.now kendiniz görün .
public static Instant now() {
return Clock.systemUTC().instant();
}
Varsayılan Clockiçin OffsetDateTime.nowve ZonedDateTime.nowolduğu Clock.systemDefaultZone(). Kaynak koduna bakın .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Varsayılan uygulamaların davranışı Java 8 ve Java 9 arasında değişti. Java 8'de, sınıfların çözünürlüğü nanosaniye depolayabilmesine rağmen, mevcut an yalnızca milisaniye cinsinden bir çözünürlükle yakalanır . Java 9, mevcut anı nanosaniye çözünürlükle yakalayabilen yeni bir uygulama getiriyor - elbette, bilgisayar donanım saatinizin kapasitesine bağlı olarak.
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 .
Daha fazla bilgi edinmek için Oracle Eğitimi'ne bakın . Ve birçok örnek ve açıklama için Stack Overflow'da arama yapın. Spesifikasyon JSR 310 .
Şu anda bakım modunda olan Joda-Time projesi, java.time'a geçişi tavsiye ediyor sınıflarına .
Sen değiştirebilir java.time sizin veritabanı ile doğrudan nesneleri. JDBC 4.2 veya üstü ile uyumlu bir JDBC sürücüsü kullanın . Dizelere gerek yok, derslere gerek yok . Hibernate 5 ve JPA 2.2 java.time desteğijava.sql.* .
Java.time derslerini nereden edinebilirim?