Qualcuno sa di una libreria Java che può stampare un numero in millisecondi nello stesso modo in cui lo fa C #?
Ad esempio, 123456 ms come long verrebbe stampato come 4d1h3m5s.
Qualcuno sa di una libreria Java che può stampare un numero in millisecondi nello stesso modo in cui lo fa C #?
Ad esempio, 123456 ms come long verrebbe stampato come 4d1h3m5s.
%
e /
per dividere il numero in parti. Quasi più facile di alcune delle risposte proposte.
/
e %
.
Risposte:
Joda Time ha un ottimo modo per farlo usando un PeriodFormatterBuilder .
Vincita veloce: PeriodFormat.getDefault().print(duration.toPeriod());
per esempio
//import org.joda.time.format.PeriodFormatter;
//import org.joda.time.format.PeriodFormatterBuilder;
//import org.joda.time.Duration;
Duration duration = new Duration(123456); // in milliseconds
PeriodFormatter formatter = new PeriodFormatterBuilder()
.appendDays()
.appendSuffix("d")
.appendHours()
.appendSuffix("h")
.appendMinutes()
.appendSuffix("m")
.appendSeconds()
.appendSuffix("s")
.toFormatter();
String formatted = formatter.print(duration.toPeriod());
System.out.println(formatted);
PeriodType.daysTime()
o .standard()
non ha aiutato
Ho costruito una soluzione semplice, usando Java 8 Duration.toString()
e un po 'di regex:
public static String humanReadableFormat(Duration duration) {
return duration.toString()
.substring(2)
.replaceAll("(\\d[HMS])(?!$)", "$1 ")
.toLowerCase();
}
Il risultato sarà simile a:
- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s
Se non vuoi spazi tra di loro, rimuovili replaceAll
.
Duration::toString
è formattato secondo lo standard ISO 8601 ben definito e ben utilizzato.
.replaceAll("\\.\\d+", "")
prima della chiamata a toLowerCase()
.
Apache commons-lang fornisce una classe utile per ottenere questo risultato anche DurationFormatUtils
ad es.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (H: m: s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, cfr. ISO8601
JodaTime ha una Period
classe che può rappresentare tali quantità e può essere renderizzata (tramite IsoPeriodFormat
) in formato ISO8601 , ad PT4D1H3M5S
es.
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
Se il formato non è quello desiderato, è PeriodFormatterBuilder
possibile assemblare layout arbitrari, incluso lo stile C # 4d1h3m5s
.
new Period(millis).toString()
utilizza ISOPeriodFormat.standard()
per impostazione predefinita.
Con Java 8 puoi anche utilizzare il toString()
metodo java.time.Duration
per formattarlo senza librerie esterne utilizzando una rappresentazione basata su ISO 8601 secondi come PT8H6M12.345S.
Ecco come puoi farlo usando il codice JDK puro:
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.Duration;
long diffTime = 215081000L;
Duration duration = DatatypeFactory.newInstance().newDuration(diffTime);
System.out.printf("%02d:%02d:%02d", duration.getDays() * 24 + duration.getHours(), duration.getMinutes(), duration.getSeconds());
org.threeten.extra.AmountFormats.wordBased
Il progetto ThreeTen-Extra , gestito da Stephen Colebourne, l'autore di JSR 310, java.time e Joda-Time , ha una AmountFormats
classe che funziona con le classi di data e ora standard di Java 8. Tuttavia, è abbastanza prolisso, senza opzioni per un output più compatto.
Duration d = Duration.ofMinutes(1).plusSeconds(9).plusMillis(86);
System.out.println(AmountFormats.wordBased(d, Locale.getDefault()));
1 minute, 9 seconds and 86 milliseconds
Java 9+
Duration d1 = Duration.ofDays(0);
d1 = d1.plusHours(47);
d1 = d1.plusMinutes(124);
d1 = d1.plusSeconds(124);
System.out.println(String.format("%s d %sh %sm %ss",
d1.toDaysPart(),
d1.toHoursPart(),
d1.toMinutesPart(),
d1.toSecondsPart()));
2 giorni 1h 6m 4s
Un'alternativa all'approccio builder di Joda-Time sarebbe una soluzione basata su modelli . Questo è offerto dalla mia libreria Time4J . Esempio di utilizzo della classe Duration.Formatter (aggiunti alcuni spazi per una maggiore leggibilità - la rimozione degli spazi produrrà lo stile C # desiderato):
IsoUnit unit = ClockUnit.MILLIS;
Duration<IsoUnit> dur = // normalized duration with multiple components
Duration.of(123456, unit).with(Duration.STD_PERIOD);
Duration.Formatter<IsoUnit> f = // create formatter/parser with optional millis
Duration.Formatter.ofPattern("D'd' h'h' m'm' s[.fff]'s'");
System.out.println(f.format(dur)); // output: 0d 0h 2m 3.456s
Questo formattatore può anche stampare durate di java.time
-API (tuttavia, le funzionalità di normalizzazione di quel tipo sono meno potenti):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
L'aspettativa dell'OP che "123456 ms come long sarebbe stampato come 4d1h3m5s" è calcolata in modo ovviamente sbagliato. Presumo la sciatteria come ragione. Lo stesso formattatore di durata definito sopra può essere utilizzato anche come parser. Il codice seguente mostra che "4d1h3m5s" corrisponde piuttosto a 349385000 = 1000 * (4 * 86400 + 1 * 3600 + 3 * 60 + 5)
:
System.out.println(
f.parse("4d 1h 3m 5s")
.toClockPeriodWithDaysAs24Hours()
.with(unit.only())
.getPartialAmount(unit)); // 349385000
Un altro modo è usare la classe net.time4j.PrettyTime
(che è utile anche per l'output localizzato e la stampa di tempi relativi come "ieri", "domenica prossima", "4 giorni fa" ecc.):
String s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.NARROW);
System.out.println(s); // output: 2m 3s 456ms
s = PrettyTime.of(Locale.ENGLISH).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds, and 456 milliseconds
s = PrettyTime.of(Locale.UK).print(dur, TextWidth.WIDE);
System.out.println(s); // output: 2 minutes, 3 seconds and 456 milliseconds
La larghezza del testo controlla se le abbreviazioni vengono utilizzate o meno. Anche il formato dell'elenco può essere controllato scegliendo la lingua appropriata. Ad esempio, l'inglese standard utilizza la virgola Oxform, mentre il Regno Unito no. L'ultima versione v5.5 di Time4J supporta più di 90 lingue e utilizza traduzioni basate sul repository CLDR (uno standard del settore).
Una versione Java 8 basata sulla risposta di user678573 :
private static String humanReadableFormat(Duration duration) {
return String.format("%s days and %sh %sm %ss", duration.toDays(),
duration.toHours() - TimeUnit.DAYS.toHours(duration.toDays()),
duration.toMinutes() - TimeUnit.HOURS.toMinutes(duration.toHours()),
duration.getSeconds() - TimeUnit.MINUTES.toSeconds(duration.toMinutes()));
}
... poiché non c'è PeriodFormatter in Java 8 e nessun metodo come getHours, getMinutes, ...
Sarei felice di vedere una versione migliore per Java 8.
Mi rendo conto che questo potrebbe non adattarsi esattamente al tuo caso d'uso, ma PrettyTime potrebbe essere utile qui.
PrettyTime p = new PrettyTime();
System.out.println(p.format(new Date()));
//prints: “right now”
System.out.println(p.format(new Date(1000*60*10)));
//prints: “10 minutes from now”
Duration
definito nello standard ragionevole, ISO 8601 :PnYnMnDTnHnMnS
doveP
significa "Periodo" e segna l'inizio,T
separa la parte della data dalla parte dell'ora e in mezzo ci sono occorrenze opzionali di un numero con un singolo -abbreviazione di lettere. Ad esempio,PT4H30M
= quattro ore e mezza.