tl; dr
Esiste un modo, nel codice o con argomenti JVM, per sovrascrivere l'ora corrente, come presentata tramite System.currentTimeMillis, oltre a modificare manualmente l'orologio di sistema sul computer host?
Sì.
Instant.now(
Clock.fixed(
Instant.parse( "2016-01-23T12:34:56Z"), ZoneOffset.UTC
)
)
Clock
In java.time
Abbiamo una nuova soluzione al problema di una sostituzione dell'orologio collegabile per facilitare i test con falsi valori di data e ora. Il pacchetto java.time in Java 8 include una classe astratta java.time.Clock
, con uno scopo esplicito:
per consentire il collegamento di orologi alternativi come e quando richiesto
È possibile collegare la propria implementazione di Clock
, anche se probabilmente è possibile trovarne uno già realizzato per soddisfare le proprie esigenze. Per comodità, java.time include metodi statici per produrre implementazioni speciali. Queste implementazioni alternative possono essere utili durante i test.
Cadenza alterata
I vari tick…
metodi producono orologi che incrementano il momento attuale con una cadenza diversa.
L'impostazione predefinita Clock
riporta un tempo aggiornato con la frequenza di millisecondi in Java 8 e Java 9 e nanosecondi (a seconda dell'hardware). Puoi chiedere che il vero momento attuale venga segnalato con una granularità diversa.
Falsi orologi
Alcuni orologi possono mentire, producendo un risultato diverso da quello dell'orologio hardware del sistema operativo host.
fixed
- Riporta un singolo momento immutabile (non incrementale) come il momento corrente.
offset
- Riporta il momento attuale ma spostato Duration
dall'argomento passato .
Ad esempio, blocca nel primo momento del primo Natale di quest'anno. in altre parole, quando Babbo Natale e le sue renne si fermano per la prima volta . Il primo fuso orario al giorno d'oggi sembra essere Pacific/Kiritimati
alle +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 );
Utilizzare quello speciale orologio fisso per restituire sempre lo stesso momento. Abbiamo il primo momento del giorno di Natale a Kiritimati , con UTC che mostra un orologio da parete di quattordici ore prima, alle 10 di mattina della data precedente del 24 dicembre.
Instant instant = Instant.now( clockEarliestXmasThisYear );
ZonedDateTime zdt = ZonedDateTime.now( clockEarliestXmasThisYear );
instant.toString (): 24-12-2016T10: 00: 00Z
zdt.toString (): 25-12-2016T00: 00 + 14: 00 [Pacifico / Kiritimati]
Vedi codice live su IdeOne.com .
Ora vera, fuso orario diverso
È possibile controllare quale fuso orario è assegnato dall'implementazione Clock
. Questo potrebbe essere utile in alcuni test. Ma non lo consiglio nel codice di produzione, dove dovresti sempre specificare esplicitamente l'opzione ZoneId
o gli ZoneOffset
argomenti.
È possibile specificare che UTC sia la zona predefinita.
ZonedDateTime zdtClockSystemUTC = ZonedDateTime.now ( Clock.systemUTC () );
È possibile specificare qualsiasi fuso orario particolare. Specificare un nome proprio fuso orario nel formato continent/region
, come ad esempio America/Montreal
, Africa/Casablanca
o Pacific/Auckland
. Non usare mai il 3-4 lettera sigla come ad esempio EST
o IST
come sono non fusi orari veri e propri, non standardizzati, e nemmeno unico (!).
ZonedDateTime zdtClockSystem = ZonedDateTime.now ( Clock.system ( ZoneId.of ( "America/Montreal" ) ) );
È possibile specificare che il fuso orario predefinito corrente della JVM dovrebbe essere il valore predefinito per un Clock
oggetto particolare .
ZonedDateTime zdtClockSystemDefaultZone = ZonedDateTime.now ( Clock.systemDefaultZone () );
Esegui questo codice per confrontare. Si noti che riportano tutti lo stesso momento, lo stesso punto nella sequenza temporale. Differiscono solo nel tempo dell'orologio da parete ; in altre parole, tre modi per dire la stessa cosa, tre modi per mostrare lo stesso momento.
System.out.println ( "zdtClockSystemUTC.toString(): " + zdtClockSystemUTC );
System.out.println ( "zdtClockSystem.toString(): " + zdtClockSystem );
System.out.println ( "zdtClockSystemDefaultZone.toString(): " + zdtClockSystemDefaultZone );
America/Los_Angeles
era la zona predefinita corrente JVM sul computer che eseguiva questo codice.
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]
La Instant
classe è sempre in UTC per definizione. Quindi questi tre Clock
usi relativi alla zona hanno esattamente lo stesso effetto.
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
Orologio predefinito
L'implementazione utilizzata di default per Instant.now
è quella restituita da Clock.systemUTC()
. Questa è l'implementazione utilizzata quando non si specifica a Clock
. Guarda tu stesso nel codice sorgente Java 9 pre-release perInstant.now
.
public static Instant now() {
return Clock.systemUTC().instant();
}
L'impostazione predefinita Clock
per OffsetDateTime.now
e ZonedDateTime.now
è Clock.systemDefaultZone()
. Vedi il codice sorgente .
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
Il comportamento delle implementazioni predefinite è cambiato tra Java 8 e Java 9. In Java 8, il momento attuale viene catturato con una risoluzione solo in millisecondi nonostante la capacità delle classi di memorizzare una risoluzione di nanosecondi . Java 9 offre una nuova implementazione in grado di catturare il momento attuale con una risoluzione di nanosecondi, a seconda, ovviamente, della capacità dell'orologio hardware del tuo computer.
Informazioni su java.time
Il framework java.time è integrato in Java 8 e versioni successive. Queste classi soppiantare la vecchia fastidiosi legacy classi data-time come java.util.Date
, Calendar
, e SimpleDateFormat
.
Per saperne di più, consulta il tutorial Oracle . E cerca Stack Overflow per molti esempi e spiegazioni. La specifica è JSR 310 .
Il progetto Joda-Time , ora in modalità manutenzione , consiglia la migrazione alle classi java.time .
Puoi scambiare oggetti java.time direttamente con il tuo database. Utilizzare un driver JDBC conforme a JDBC 4.2 o successivo. Non c'è bisogno di stringhe, non c'è bisogno di java.sql.*
classi. Hibernate 5 e JPA 2.2 supportano java.time .
Dove ottenere le classi java.time?