¿Alguien sabe de una biblioteca de Java que pueda imprimir un número en milisegundos de la misma manera que lo hace C #?
Por ejemplo, 123456 ms como un largo se imprimiría como 4d1h3m5s.
¿Alguien sabe de una biblioteca de Java que pueda imprimir un número en milisegundos de la misma manera que lo hace C #?
Por ejemplo, 123456 ms como un largo se imprimiría como 4d1h3m5s.
%
y /
para dividir el número en partes. Casi más fácil que algunas de las respuestas propuestas.
/
y %
.
Respuestas:
Joda Time tiene una manera bastante buena de hacer esto usando un PeriodFormatterBuilder .
Victoria rapida: PeriodFormat.getDefault().print(duration.toPeriod());
p.ej
//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()
no ayudó
Creé una solución simple, usando Java 8 Duration.toString()
y un poco de expresión regular:
public static String humanReadableFormat(Duration duration) {
return duration.toString()
.substring(2)
.replaceAll("(\\d[HMS])(?!$)", "$1 ")
.toLowerCase();
}
El resultado se verá así:
- 5h
- 7h 15m
- 6h 50m 15s
- 2h 5s
- 0.1s
Si no quiere espacios entre ellos, simplemente elimínelos replaceAll
.
Duration::toString
está formateada de acuerdo con el estándar ISO 8601 bien definido y usado .
.replaceAll("\\.\\d+", "")
antes de llamar a toLowerCase()
.
Apache commons-lang proporciona una clase útil para hacer esto también DurationFormatUtils
ej.
DurationFormatUtils.formatDurationHMS( 15362 * 1000 ) )
=> 4: 16: 02.000 (H: m: s.millis)
DurationFormatUtils.formatDurationISO( 15362 * 1000 ) )
=> P0Y0M0DT4H16M2.000S, cf. ISO8601
JodaTime tiene una Period
clase que puede representar tales cantidades y se puede renderizar (vía IsoPeriodFormat
) en formato ISO8601 , por ejemplo PT4D1H3M5S
,
Period period = new Period(millis);
String formatted = ISOPeriodFormat.standard().print(period);
Si ese formato no es el que desea, entonces le PeriodFormatterBuilder
permite ensamblar diseños arbitrarios, incluido su estilo C # 4d1h3m5s
.
new Period(millis).toString()
usa el ISOPeriodFormat.standard()
predeterminado.
Con Java 8 también puede utilizar el toString()
método de java.time.Duration
para formatearlo sin bibliotecas externas utilizando la representación basada en segundos ISO 8601 como PT8H6M12.345S.
A continuación, le indicamos cómo puede hacerlo utilizando código 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
El proyecto ThreeTen-Extra , mantenido por Stephen Colebourne, autor de JSR 310, java.time y Joda-Time , tiene una AmountFormats
clase que funciona con las clases estándar de fecha y hora de Java 8. Sin embargo, es bastante detallado, sin opción para una salida más compacta.
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 d 1h 6m 4s
Una alternativa al enfoque de construcción de Joda-Time sería una solución basada en patrones . Esto lo ofrece mi biblioteca Time4J . Ejemplo usando la clase Duration.Formatter (se agregaron algunos espacios para una mayor legibilidad; eliminar los espacios producirá el estilo C # deseado):
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
Este formateador también puede imprimir duraciones de java.time
-API (sin embargo, las características de normalización de ese tipo son menos poderosas):
System.out.println(f.format(java.time.Duration.ofMillis(123456))); // output: 0d 0h 2m 3.456s
La expectativa del OP de que "123456 ms como un largo se imprimirían como 4d1h3m5s" se calcula de una manera obviamente incorrecta. Asumo el descuido como razón. El mismo formateador de duración definido anteriormente también se puede utilizar como analizador. El siguiente código muestra que "4d1h3m5s" corresponde más bien 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
Otra forma es usar la clase net.time4j.PrettyTime
(que también es buena para resultados localizados e imprimir tiempos relativos como "ayer", "próximo domingo", "hace 4 días", etc.):
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
El ancho del texto controla si se usan o no abreviaturas. El formato de la lista también se puede controlar eligiendo la configuración regional adecuada. Por ejemplo, el inglés estándar utiliza la coma Oxform, mientras que el Reino Unido no. La última versión v5.5 de Time4J admite más de 90 idiomas y utiliza traducciones basadas en el repositorio CLDR (un estándar de la industria).
Una versión de Java 8 basada en la respuesta del usuario 678573 :
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()));
}
... ya que no hay PeriodFormatter en Java 8 y no hay métodos como getHours, getMinutes, ...
Me alegraría ver una versión mejor para Java 8.
Me doy cuenta de que esto podría no ajustarse exactamente a su caso de uso, pero PrettyTime podría ser útil aquí.
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
definido en el estándar sensible, ISO 8601 :PnYnMnDTnHnMnS
dondeP
significa "Período" y marca el comienzo,T
separa la parte de la fecha de la parte del tiempo, y en el medio hay apariciones opcionales de un número con un solo -abreviatura de la letra. Por ejemplo,PT4H30M
= cuatro horas y media.