Formattazione di una durata in Java 8 / jsr310

Sto trasferendo un progetto da Joda-Time alle librerie di tempo nativo di java8 e ho avuto un problema. Non sono stato in grado di trovare un formattatore per la durata. Mi piacerebbe avere un formato String personalizzato, per esempio, HHH + MM, dove una durata di 75 ore e 15 minuti si formsrebbe come “75 + 15”. Questo è stato facile da fare con Joda-Time convertendo in period e usando un PeriodFormatter, ma non sono stato in grado di trovare questo tipo di class in Java8. Mi sto perdendo qualcosa?

Non esiste un periodo / durata-formattatore in jsr-310, diverso da JodaTime. Non tutte le funzionalità di JodaTime sono state trasferite su JSR-310 (ad esempio anche su PeriodType). E al contrario, JSR-310 ha alcune caratteristiche che non sono disponibili in JodaTime (ad esempio i numeri dei giorni della settimana localizzati o l’approccio del modello di strategia con i regolatori).

Potrebbe accadere che Java 9 introduca una sorta di formattazione del periodo incorporata (leggi qualcosa su questo da S. Colebourne).

Conclusione: JSR-310 e JodaTime non sono completamente compatibili tra loro, quindi può essere richiesto molto lavoro. Non sarei così entusiasta della migrazione il prima ansible. Hai bisogno di funzioni speciali di JSR-310 che non sono offerte da JodaTime?

Nota aggiuntiva: dovresti anche essere consapevole del fatto che il periodo joda (che include tutte le unità da anni a secondi) non è completamente compatibile con il periodo jsr310 (solo anni, mesi, giorni) o durata jsr310 (solo ore, minuti, secondi e frazione secondi).

Java 8

Stranamente, nessun metodo getter conveniente per questi valori è stato incluso nella prima versione di java.time in Java 8.

Vedere la relativa domanda: Perché non riesco a ottenere una durata in minuti o ore in java.time? .

Java 9 e versioni successive

In Java 9 la class Duration ottiene nuovi metodi per restituire le varie parti di giorni, ore, minuti, secondi, millisecondi / nanosecondi. Vedi questo codice sorgente OpenJDK pre-rilascio .

Data una durata di 49H30M20.123S …

  • toNanosPart() = 123000000
  • toMillisPart() = 123
  • toSecondsPart() = 20
  • toMinutesPart() = 30
  • toHoursPart() = 1
  • toDaysPart() = 2

Non so se vengono aggiunte ulteriori funzionalità di formattazione. Ma almeno sarai in grado di generare più facilmente le tue stringhe dai numeri ottenuti con questi nuovi metodi getter.

Non esiste un metodo integrato, ma è ansible accedere al numero di ore / minuti senza doverli calcolare manualmente. Il tuo formato specifico potrebbe essere simile a:

 Duration d = Duration.of(75, HOURS).plusMinutes(15); long hours = d.toHours(); //75 long minutes = d.minusHours(hours).toMinutes(); //15 String HH_PLUS_MM = hours + "+" + minutes; //75+15 System.out.println(HH_PLUS_MM); 

Se la durata è garantita per essere inferiore a 24 ore, è anche ansible utilizzare questo trucco:

 String hhPlusMm = LocalTime.MIDNIGHT.plus(d).format(DateTimeFormatter.ofPattern("HH+mm")); 

puoi usare DurationFormatUtils da commons-lang3-time (per i minuti devi usare “mm” poiché il formato è lo stesso di SimpleDateFormat ): DurationFormatUtils.formatDuration(interval.toMillis(), "HHH+mm")

Purtroppo non ho trovato alcun modo per escludere parti vuote, come nel mio caso i giorni o le ore potrebbero essere 0, quindi ho dovuto ancora rollare il mio.

Aggiornamento: Ho aperto un problema per questo su commons.lang.time.DurationFormatUtils di Apache JIRA .

So che questa è una vecchia domanda ma di recente mi sono imbattuto nella stessa cosa. Dovrebbe esserci una soluzione migliore di questa, ma questo ha funzionato per me:

 public static String millisToElapsedTime(long millis){ DateFormat fmt = new SimpleDateFormat(":mm:ss.SSS"); fmt.setTimeZone(TimeZone.getTimeZone("UTC")); return (millis/3600000/*hours*/)+fmt.format(new Date(millis)); } 

Quindi, puoi aggiungere questo:

 public static String durationToElapsedTime(Duration d){ return millisToElapsedTime(d.toMillis()); }