tl; dr
Gibt es eine Möglichkeit, entweder im Code oder mit JVM-Argumenten die aktuelle Zeit zu überschreiben, wie sie über System.currentTimeMillis angezeigt wird, außer die Systemuhr auf dem Host-Computer manuell zu ändern?
Ja.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock
In java.time
Wir haben eine neue Lösung für das Problem des Austauschs einer steckbaren Uhr, um das Testen mit falschen Datums- / Uhrzeitwerten zu erleichtern . Das Paket java.time in Java 8 enthält eine abstrakte Klasse java.time.Clock
mit einem expliziten Zweck:
damit bei Bedarf alternative Uhren angeschlossen werden können
Sie könnten Ihre eigene Implementierung von anschließen Clock
, obwohl Sie wahrscheinlich eine finden können, die bereits für Ihre Anforderungen erstellt wurde. Für Ihre Bequemlichkeit enthält java.time statische Methoden, um spezielle Implementierungen zu erhalten. Diese alternativen Implementierungen können beim Testen hilfreich sein.
Veränderte Trittfrequenz
Die verschiedenen tick…
Methoden erzeugen Uhren, die das aktuelle Moment mit einer anderen Trittfrequenz erhöhen.
Die Standardeinstellung gibt Clock
eine Zeit an, die in Java 8 so häufig wie Millisekunden und in Java 9 so fein wie Nanosekunden aktualisiert wird (abhängig von Ihrer Hardware). Sie können verlangen, dass der wahre aktuelle Moment mit einer anderen Granularität gemeldet wird.
Falsche Uhren
Einige Uhren können lügen und ein anderes Ergebnis als die Hardware-Uhr des Host-Betriebssystems erzeugen.
fixed
- Meldet einen einzelnen unveränderlichen (nicht inkrementierenden) Moment als aktuellen Moment.
offset
- Meldet den aktuellen Moment, wird jedoch durch das übergebene Duration
Argument verschoben .
Schließen Sie zum Beispiel den ersten Moment des frühesten Weihnachtsfestes in diesem Jahr ein. Mit anderen Worten, wenn der Weihnachtsmann und sein Rentier ihren ersten Halt machen . Die früheste Zeitzone scheint heute zu sein , Pacific/Kiritimati
an +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 );
Verwenden Sie diese spezielle feste Uhr, um immer den gleichen Moment zurückzugeben. Wir haben den ersten Moment des Weihnachtstages in Kiritimati , wobei UTC eine Wanduhrzeit von vierzehn Stunden früher anzeigt, 10 Uhr am vorherigen Datum des 24. Dezember.
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]
Siehe Live-Code in IdeOne.com .
Wahre Zeit, andere Zeitzone
Sie können steuern, welche Zeitzone von der Clock
Implementierung zugewiesen wird . Dies kann bei einigen Tests hilfreich sein. Ich empfehle dies jedoch nicht im Produktionscode, wo Sie immer explizit die optionalen ZoneId
oder ZoneOffset
Argumente angeben sollten .
Sie können festlegen, dass UTC die Standardzone ist.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
Sie können eine bestimmte Zeitzone angeben. Geben Sie einen richtigen Zeitzonennamen im Format continent/region
, wie zum Beispiel America/Montreal
, Africa/Casablanca
oder Pacific/Auckland
. Verwenden Sie niemals die Abkürzung für 3-4 Buchstaben, wie EST
oder, IST
da es sich nicht um echte Zeitzonen handelt, die nicht standardisiert und nicht einmal eindeutig (!) Sind.
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
Sie können angeben, dass die aktuelle Standardzeitzone der JVM die Standardzeitzone für ein bestimmtes Clock
Objekt sein soll.
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Führen Sie diesen Code zum Vergleichen aus. Beachten Sie, dass alle denselben Moment und denselben Punkt auf der Zeitachse melden. Sie unterscheiden sich nur in der Wanduhrzeit ; Mit anderen Worten, drei Möglichkeiten, dasselbe zu sagen, drei Möglichkeiten, denselben Moment anzuzeigen.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles
war die aktuelle JVM-Standardzone auf dem Computer, auf dem dieser Code ausgeführt wurde.
zdtClockSystemUTC.toString (): 2016-12-31T20: 52: 39.688Z
zdtClockSystem.toString (): 2016-12-31T15: 52: 39.750-05: 00 [America / Montreal]
zdtClockSystemDefaultZone.toString (): 2016-12-31T12: 52: 39.762-08: 00 [America / Los_Angeles]
Die Instant
Klasse ist per Definition immer in UTC. Diese drei Clock
zonenbezogenen Verwendungen haben also genau den gleichen Effekt.
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
Standarduhr
Die standardmäßig für verwendete Implementierung Instant.now
ist die von Clock.systemUTC()
. Dies ist die Implementierung, die verwendet wird, wenn Sie a nicht angeben Clock
. Überzeugen Sie sich selbst im Java 9-Quellcode vor der Veröffentlichung fürInstant.now
.
public static Instant now() {
return Clock.systemUTC().instant();
}
Der Standardwert Clock
für OffsetDateTime.now
und ZonedDateTime.now
ist Clock.systemDefaultZone()
. Siehe Quellcode .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Das Verhalten der Standardimplementierungen hat sich zwischen Java 8 und Java 9 geändert. In Java 8 wird der aktuelle Moment mit einer Auflösung nur in Millisekunden erfasst, obwohl die Klassen eine Auflösung von Nanosekunden speichern können . Java 9 bietet eine neue Implementierung, mit der der aktuelle Moment mit einer Auflösung von Nanosekunden erfasst werden kann - natürlich abhängig von der Leistungsfähigkeit Ihrer Computerhardware-Uhr.
Über java.time
Das java.time- Framework ist in Java 8 und höher integriert. Diese Klassen verdrängen die lästigen alten Legacy - Datum-Zeit - Klassen wie java.util.Date
, Calendar
, & SimpleDateFormat
.
Das Joda-Time- Projekt, das sich jetzt im Wartungsmodus befindet , empfiehlt die Migration zu den Klassen java.time .
Weitere Informationen finden Sie im Oracle-Lernprogramm . Suchen Sie im Stapelüberlauf nach vielen Beispielen und Erklärungen. Die Spezifikation ist JSR 310 .
Sie können java.time- Objekte direkt mit Ihrer Datenbank austauschen . Verwenden Sie einen JDBC-Treiber, der mit JDBC 4.2 oder höher kompatibel ist . Keine Notwendigkeit für Zeichenfolgen, keine Notwendigkeit für java.sql.*
Klassen.
Woher bekomme ich die java.time-Klassen?
- Java SE 8 , Java SE 9 und höher
- Eingebaut.
- Teil der Standard-Java-API mit einer gebündelten Implementierung.
- Java 9 fügt einige kleinere Funktionen und Korrekturen hinzu.
- Java SE 6 und Java SE 7
- Android
- Spätere Versionen von Android-Bundle-Implementierungen der Klassen java.time.
- Für frühere Android -Geräte ( <26) passt das ThreeTenABP- Projekt ThreeTen-Backport (oben erwähnt) an. Siehe Verwendung von ThreeTenABP… .
Das ThreeTen-Extra- Projekt erweitert java.time um zusätzliche Klassen. Dieses Projekt ist ein Testfeld für mögliche zukünftige Ergänzungen von java.time. Sie können einige nützliche Klassen hier wie finden Interval
, YearWeek
, YearQuarter
, und mehr .