tl; dr
Apakah ada cara, baik dalam kode atau dengan argumen JVM, untuk mengesampingkan waktu saat ini, seperti yang disajikan melalui System.currentTimeMillis, selain secara manual mengubah jam sistem pada mesin host?
Iya.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock
Di java.time
Kami memiliki solusi baru untuk masalah penggantian jam pluggable untuk memfasilitasi pengujian dengan nilai waktu-tanggal palsu . The paket java.time di Jawa 8 meliputi kelas abstrak java.time.Clock
, dengan tujuan yang jelas:
untuk memungkinkan jam alternatif dicolokkan sebagai dan ketika diperlukan
Anda dapat memasang implementasi Anda sendiri Clock
, meskipun Anda mungkin dapat menemukan satu sudah dibuat untuk memenuhi kebutuhan Anda. Untuk kenyamanan Anda, java.time termasuk metode statis untuk menghasilkan implementasi khusus. Implementasi alternatif ini dapat bermanfaat selama pengujian.
Irama diubah
Berbagai tick…
metode menghasilkan jam yang menambah momen saat ini dengan irama yang berbeda.
Default Clock
melaporkan waktu yang diperbarui sesering milidetik di Java 8 dan di Jawa 9 sebagus nanodetik (tergantung pada perangkat keras Anda). Anda dapat meminta momen aktual saat ini untuk dilaporkan dengan rincian yang berbeda.
Jam palsu
Beberapa jam bisa berbohong, menghasilkan hasil yang berbeda dari jam hardware OS host.
fixed
- Melaporkan momen tunggal yang tidak berubah (tidak bertambah) sebagai momen saat ini.
offset
- Melaporkan momen saat ini tetapi digeser oleh Duration
argumen yang diteruskan .
Misalnya, kunci pada saat pertama Natal paling awal tahun ini. dengan kata lain, ketika Santa dan rusa kutubnya berhenti pertama kali . Zona waktu paling awal saat ini tampaknya berada Pacific/Kiritimati
di +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 );
Gunakan jam tetap khusus itu untuk selalu mengembalikan momen yang sama. Kami mendapatkan momen pertama hari Natal di Kiritimati , dengan UTC menunjukkan waktu jam dinding empat belas jam sebelumnya, jam 10 pagi pada tanggal 24 Desember sebelumnya.
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 [Pasifik / Kiritimati]
Lihat kode langsung di IdeOne.com .
Waktu sebenarnya, zona waktu berbeda
Anda dapat mengontrol zona waktu mana yang ditetapkan oleh Clock
implementasi. Ini mungkin berguna dalam beberapa pengujian. Tapi saya tidak merekomendasikan ini dalam kode produksi, di mana Anda harus selalu menentukan secara eksplisit opsi ZoneId
atau ZoneOffset
argumen.
Anda dapat menentukan UTC sebagai zona default.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
Anda dapat menentukan zona waktu tertentu. Tentukan nama zona waktu yang tepat dalam format continent/region
, seperti America/Montreal
, Africa/Casablanca
, atau Pacific/Auckland
. Jangan pernah menggunakan singkatan 3-4 huruf seperti EST
atau IST
karena mereka bukan zona waktu yang sebenarnya, tidak terstandarisasi, dan bahkan tidak unik (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Anda dapat menentukan zona waktu default JVM saat ini harus menjadi default untuk Clock
objek tertentu .
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Jalankan kode ini untuk membandingkan. Perhatikan bahwa mereka semua melaporkan momen yang sama, titik yang sama pada timeline. Mereka hanya berbeda dalam waktu jam dinding ; dengan kata lain, tiga cara untuk mengatakan hal yang sama, tiga cara untuk menampilkan momen yang sama.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles
adalah zona default JVM saat ini di komputer yang menjalankan kode ini.
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 [America / Los_Angeles]
The Instant
kelas selalu dalam UTC dengan definisi. Jadi ketiga Clock
penggunaan terkait zona ini memiliki efek yang persis sama.
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
Jam default
Implementasi yang digunakan secara default Instant.now
adalah implementasi yang dikembalikan oleh Clock.systemUTC()
. Ini adalah implementasi yang digunakan ketika Anda tidak menentukan Clock
. Lihat sendiri di kode sumber Java 9 pra-rilis untukInstant.now
.
public static Instant now() {
return Clock.systemUTC().instant();
}
Default Clock
untuk OffsetDateTime.now
dan ZonedDateTime.now
adalah Clock.systemDefaultZone()
. Lihat kode sumber .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Perilaku implementasi standar berubah antara Java 8 dan Java 9. Di Java 8, momen saat ini ditangkap dengan resolusi hanya dalam milidetik meskipun kemampuan kelas untuk menyimpan resolusi nanodetik . Java 9 menghadirkan implementasi baru yang mampu mengabadikan momen saat ini dengan resolusi nanodetik - tentu saja tergantung pada kemampuan jam perangkat keras komputer Anda.
Tentang java.time
The java.time kerangka dibangun ke Jawa 8 dan kemudian. Kelas-kelas ini menggantikan tua merepotkan warisan kelas tanggal-waktu seperti java.util.Date
, Calendar
, & SimpleDateFormat
.
Untuk mempelajari lebih lanjut, lihat Tutorial Oracle . Dan cari Stack Overflow untuk banyak contoh dan penjelasan. Spesifikasi adalah JSR 310 .
Proyek Joda-Time , sekarang dalam mode pemeliharaan , menyarankan migrasi ke kelas java.time .
Anda dapat bertukar objek java.time secara langsung dengan database Anda. Gunakan driver JDBC yang sesuai dengan JDBC 4.2 atau yang lebih baru. Tidak perlu untuk string, tidak perlu untuk java.sql.*
kelas. Hibernate 5 & JPA 2.2 mendukung java.time .
Di mana mendapatkan kelas java.time?