2015-03-05 19 views
7

Ho un'origine dati con gli oggetti DateTime joda time memorizzati. Devo convertirli in oggetti Java ZonedDateTime, mantenendo il fuso orario originale.Come convertire da org.joda.time.DateTime a java.time.ZonedDateTime

Non è sufficiente mantenere l'offset poiché alcuni oggetti DateTime rappresentano attività giornaliere ripetitive e queste attività devono essere eseguite in un momento specifico in un fuso orario specifico per ogni data. Devono quindi seguire le transizioni TimeZone specificate, ad esempio l'ora legale e quella invernale. Non posso dire l'utilizzo finale degli oggetti DateTime, quindi ho bisogno di mantenere le informazioni sul fuso orario su tutti gli oggetti per essere sicuri.

Come convertire da org.joda.time.DateTime in java.time.ZonedDateTime?

Will tutti

ord.joda.time.DateTimeZone.getId()

mappa per l'id del disponibile in

java.time.ZoneId

risposta

15

Non tutti i fusi orari gli archi di Joda-Time corrisponderanno a java.time ma la stragrande maggioranza sarà basata entrambi sui dati tz IANA. Confronta DateTimeZone.getAvailableIDs() a ZoneId.getAvailableZoneIds() per determinare la mancata corrispondenza. Identificatori aggiuntivi possono essere mappati usando ZoneId.of(String, Map).

per eseguire la conversione principale nel modo più efficiente, è necessario passare in ogni campo:

ZonedDateTime zdt = ZonedDateTime.ofLocal(
    LocalDateTime.of(
     dt.getYear(), 
     dt.getMonthOfYear(), 
     dt.getDayOfMonth(), 
     dt.getHourOfDay(), 
     dt.getMinuteOfHour(), 
     dt.getSecondOfMinute(), 
     dt.getMillisOfSecond() * 1_000_000), 
    ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS), 
    ZoneOffset.ofTotalSeconds(dt.getZone().getOffset(dt)/1000)); 

Nota l'uso del ZoneId.SHORT_IDS come Map in questo caso.

Per una soluzione più semplice che gestisce la maggior parte dei casi d'uso, ma con prestazioni inferiori, utilizzare questo:

ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime(); 
+0

C'è un sottoinsieme specifico che non è nell'uno o nell'altro? Forse alcune delle vecchie zone di compatibilità POSIX? Mi auguro che tutte le moderne zone di stile "Area/Località" siano disponibili in entrambi. –

+2

L'unica differenza è ROC, che è stata sostituita da ROK. È possibile accedere alle zone EST, HST e MST utilizzando 'ZoneId.SHORT_IDS'. Altrimenti, eventuali differenze sono solo dalla versione successiva del database del fuso orario in Joda-Time. – JodaStephen

+1

@JodaStephen invece di 'ZoneId.of (dt.getZone().getID(), ZoneId.SHORT_IDS)) '' would not 'dt.toTimeZone(). toZoneId()' funziona allo stesso modo? sembra lasciare il nitty grintoso a JodaTime e Java rispettivamente. – NomeN

3

Si dovrebbe evitare di fornire ogni campo separatamente, se si sta lavorando con le transizioni di risparmio di luce del giorno. Convertire invece usando epochMillis, come nell'esempio seguente.

Instant instant = Instant.ofEpochMilli(dt.getMillis()); 
ZoneId zoneId = ZoneId.of(dt.getZone().getId(), ZoneId.SHORT_IDS); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId); 

Altrimenti si perderà un'ora alla data di transizione. Ad esempio, la Germania è passata dall'ora legale (GMT + 2) all'orario invernale (GMT + 1) il 29.10.2017 alle 03:00 GMT + 2, che diventa 02:00 GMT + 1. In quel giorno, hai 2 istanze di 02:00 - una precedente con GMT + 2 e una successiva con GMT + 1.

Poiché si sta lavorando con ZoneIds e non con offset, non c'è modo di sapere quale delle 2 istanze desiderate. Per impostazione predefinita, viene assunto il primo durante la conversione. Sia 02:00 GMT + 2 e 02:00 GMT + 1 saranno convertiti in 02:00 GMT + 2 se fornisci hourOfDay insieme a ZoneId.