Me gustaría formatear una duración en segundos con un patrón como H: MM: SS. Las utilidades actuales en java están diseñadas para formatear un tiempo pero no una duración.¿Cómo formatear una duración en Java? (Por ejemplo, formato H: MM: SS)
Respuesta
Si está utilizando una versión de Java anterior a la 8 ... puede usar Joda Time y PeriodFormatter
. Si realmente tiene una duración (es decir, una cantidad de tiempo transcurrida, sin referencia a un sistema de calendario), probablemente debería estar usando Duration
en su mayor parte; luego puede llamar al toPeriod
(especificando lo que PeriodType
desea reflejar ya sea 25 horas se convierte en 1 día y 1 hora o no, etc.) para obtener un Period
que puede formatear.
Si está utilizando Java 8 o posterior: normalmente sugeriría usar java.time.Duration
para representar la duración. A continuación, puede llamar al getSeconds()
o similar para obtener un número entero para el formato de cadena estándar según la respuesta de Bobince, si es necesario, aunque debe tener cuidado de que la duración sea negativa, ya que probablemente desee un único signo negativo la cadena de salida. Así que algo como:
public static String formatDuration(Duration duration) {
long seconds = duration.getSeconds();
long absSeconds = Math.abs(seconds);
String positive = String.format(
"%d:%02d:%02d",
absSeconds/3600,
(absSeconds % 3600)/60,
absSeconds % 60);
return seconds < 0 ? "-" + positive : positive;
}
Formateo de esta manera es razonablemente simple, si molesto manual. Para , el análisis de se convierte en una cuestión más difícil en general ... Todavía podría utilizar Joda Time incluso con Java 8 si así lo desea, por supuesto.
Si no desea arrastrar bibliotecas, es bastante sencillo hacerlo usted mismo usando un formateador, o un atajo relacionado, por ejemplo. número entero dado de segundos s:
String.format("%d:%02d:%02d", s/3600, (s % 3600)/60, (s % 60));
No tiene que ser un número entero. Si tiene dos fechas, simplemente conecte date1.getTime() - date2.getTime() en la ecuación anterior que utiliza la primitiva larga y aún funciona. – Josh
¿Qué sucede si la diferencia de tiempo es más de 24 horas? – Rajish
@Rajish: ¡tendrías que preguntarle al OP qué es lo que querían en ese caso! Por supuesto, puede separarlo en 's/86400, (s% 86400)/3600 ...' por días si es necesario ... – bobince
Esto va a ser una de las nuevas características de Java 7
Parece que se ha retrotraído a Java 8. – Boann
No, ni siquiera está programado para Java-9.Entonces, las opciones son escribir una solución alternativa o usar una biblioteca de terceros (Joda-Time, Time4J, Apache-Commons, etc.). –
Está en Java 8 y también se transfiere a Java 6 y 7. –
long duration = 4 * 60 * 60 * 1000;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());
log.info("Duration: " + sdf.format(new Date(duration - TimeZone.getDefault().getRawOffset())));
¡Hah! Simplemente golpee la pared con la normalización de la zona horaria cuando use este método. Tienes que agregar 'sdf.setTimeZone (TimeZone.getTimeZone (" GMT + 0 "));' antes de usar la función 'format'. – Rajish
que utilizan Apache común de DurationFormatUtils así:
DurationFormatUtils.formatDuration(millis, "**H:mm:ss**", true));
La forma más fácil posible (en el estilo de Apache commons). Incluso tiene el método formatDurationHMS que probablemente usará la mayor parte del tiempo. – Marko
Esta es una opción de trabajo.
public static String showDuration(LocalTime otherTime){
DateTimeFormatter df = DateTimeFormatter.ISO_LOCAL_TIME;
LocalTime now = LocalTime.now();
System.out.println("now: " + now);
System.out.println("otherTime: " + otherTime);
System.out.println("otherTime: " + otherTime.format(df));
Duration span = Duration.between(otherTime, now);
LocalTime fTime = LocalTime.ofNanoOfDay(span.toNanos());
String output = fTime.format(df);
System.out.println(output);
return output;
}
Llame al método con
System.out.println(showDuration(LocalTime.of(9, 30, 0, 0)));
produce algo así como:
otherTime: 09:30
otherTime: 09:30:00
11:31:27.463
11:31:27.463
Esto fallará para duraciones mayores a 23: 59: 59.999. –
Esto podría ser una especie de hacky, pero es una buena solución si uno está empeñado en lograr esto usando Java 8's java.time
:
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
import java.time.temporal.TemporalField;
import java.time.temporal.UnsupportedTemporalTypeException;
public class TemporalDuration implements TemporalAccessor {
private static final Temporal BASE_TEMPORAL = LocalDateTime.of(0, 1, 1, 0, 0);
private final Duration duration;
private final Temporal temporal;
public TemporalDuration(Duration duration) {
this.duration = duration;
this.temporal = duration.addTo(BASE_TEMPORAL);
}
@Override
public boolean isSupported(TemporalField field) {
if(!temporal.isSupported(field)) return false;
long value = temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
return value!=0l;
}
@Override
public long getLong(TemporalField field) {
if(!isSupported(field)) throw new UnsupportedTemporalTypeException(new StringBuilder().append(field.toString()).toString());
return temporal.getLong(field)-BASE_TEMPORAL.getLong(field);
}
public Duration getDuration() {
return duration;
}
@Override
public String toString() {
return dtf.format(this);
}
private static final DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.optionalStart()//second
.optionalStart()//minute
.optionalStart()//hour
.optionalStart()//day
.optionalStart()//month
.optionalStart()//year
.appendValue(ChronoField.YEAR).appendLiteral(" Years ").optionalEnd()
.appendValue(ChronoField.MONTH_OF_YEAR).appendLiteral(" Months ").optionalEnd()
.appendValue(ChronoField.DAY_OF_MONTH).appendLiteral(" Days ").optionalEnd()
.appendValue(ChronoField.HOUR_OF_DAY).appendLiteral(" Hours ").optionalEnd()
.appendValue(ChronoField.MINUTE_OF_HOUR).appendLiteral(" Minutes ").optionalEnd()
.appendValue(ChronoField.SECOND_OF_MINUTE).appendLiteral(" Seconds").optionalEnd()
.toFormatter();
}
Acabo de probar esto, y me di cuenta de que si llamaba al formato para "hh: mm: ss" cuando no tenía ninguna hora o minutos para formatear (por ejemplo, 'Duración.deSegundos (20)'), entonces obtenía un 'UnsupportedTemporalTypeException'). Simplemente eliminé el código comprobando si la diferencia es '== 01'. Pensé que '01' era algún tipo de valor de enmascaramiento que no completo, ¿puedes explicarlo? – Groostav
Esto realmente funcionó muy bien. En mi caso, incluso agregué milisegundos ... En cuanto al método 'isSupported', devuelve la información si hay un campo válido para mostrar en la cadena legible por humanos. De todos modos, el "enmascaramiento" en realidad no es una máscara. El código muestra 'return value! = 0l' not' return value! = 01'. Por favor haz uso de copiar y pegar la próxima vez. – MrJames
No se supone que la interfaz 'TemporalAccessor' se use mal durante las duraciones. JSR-310 ha diseñado la interfaz 'TemporalAmount' para este propósito. –
Aquí hay una muestra más de cómo formatear la duración. Tenga en cuenta que esta muestra muestra tanto duración positiva como negativa como duración positiva.
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.SECONDS;
import java.time.Duration;
public class DurationSample {
public static void main(String[] args) {
//Let's say duration of 2days 3hours 12minutes and 46seconds
Duration d = Duration.ZERO.plus(2, DAYS).plus(3, HOURS).plus(12, MINUTES).plus(46, SECONDS);
//in case of negative duration
if(d.isNegative()) d = d.negated();
//format DAYS HOURS MINUTES SECONDS
System.out.printf("Total duration is %sdays %shrs %smin %ssec.\n", d.toDays(), d.toHours() % 24, d.toMinutes() % 60, d.getSeconds() % 60);
//or format HOURS MINUTES SECONDS
System.out.printf("Or total duration is %shrs %smin %sec.\n", d.toHours(), d.toMinutes() % 60, d.getSeconds() % 60);
//or format MINUTES SECONDS
System.out.printf("Or total duration is %smin %ssec.\n", d.toMinutes(), d.getSeconds() % 60);
//or format SECONDS only
System.out.printf("Or total duration is %ssec.\n", d.getSeconds());
}
}
Mi biblioteca Time4J ofrece una solución basada en patrones (similar a Apache DurationFormatUtils
, pero más flexible):
Duration<ClockUnit> duration =
Duration.of(-573421, ClockUnit.SECONDS) // input in seconds only
.with(Duration.STD_CLOCK_PERIOD); // performs normalization to h:mm:ss-structure
String fs = Duration.formatter(ClockUnit.class, "+##h:mm:ss").format(duration);
System.out.println(fs); // output => -159:17:01
Este código demuestra las capacidades para manejar el desbordamiento hora y firmar el manejo, consulta la API del formateador de duración based on pattern.
String duration(Temporal from, Temporal to) {
final StringBuilder builder = new StringBuilder();
for (ChronoUnit unit : new ChronoUnit[]{YEARS, MONTHS, WEEKS, DAYS, HOURS, MINUTES, SECONDS}) {
long amount = unit.between(from, to);
if (amount == 0) {
continue;
}
builder.append(' ')
.append(amount)
.append(' ')
.append(unit.name().toLowerCase());
from = from.plus(amount, unit);
}
return builder.toString().trim();
}
Esto será más fácil con Java 9. Un Duration
todavía no es formattable (lo que yo sepa), pero se agregan métodos para obtener las horas, minutos y segundos, lo que hace que la tarea algo más sencillo:
Duration diff = // ...;
String hms = String.format("%d:%02d:%02d",
diff.toHoursPart(),
diff.toMinutesPart(),
diff.toSecondsPart());
¿Qué hay de la siguiente función, que devuelve ya sea + H: MM: SS o + H: MM: SS.sss
public static String formatInterval(final long interval, boolean millisecs)
{
final long hr = TimeUnit.MILLISECONDS.toHours(interval);
final long min = TimeUnit.MILLISECONDS.toMinutes(interval) %60;
final long sec = TimeUnit.MILLISECONDS.toSeconds(interval) %60;
final long ms = TimeUnit.MILLISECONDS.toMillis(interval) %1000;
if(millisecs) {
return String.format("%02d:%02d:%02d.%03d", hr, min, sec, ms);
} else {
return String.format("%02d:%02d:%02d", hr, min, sec);
}
}
- 1. Cómo formatear una fecha en formato MM/dd/aaaa HH: mm: ss en JavaScript?
- 2. Formato de fecha en dd/mm/aaaa hh: mm: ss
- 3. Convertir TimeSpan de formato "hh: mm: ss" a "hh: mm"
- 4. Tiempo en cadena con formato HH: MM: SS (programación C)
- 5. ¿cómo puedo definir NSTimeInterval al formato mm: ss en iphone?
- 6. Cómo convertir los segundos en este formato "HH: mm: ss"
- 7. Cómo formatear el valor de tiempo en HH: MM: SS en la etiqueta de datos
- 8. Hora actual en HH: MM: ¿formato SS am/pm?
- 9. ¿Convertir tiempo en formato HH: MM: SS a segundos solamente?
- 10. Cómo mostrar un intervalo de segundos en formato hh: mm: ss en Reporting Services
- 11. Muestra la hora actual en este formato: HH: mm: ss
- 12. SQL Server Formato Fecha DD.MM.YYYY HH: MM: SS
- 13. Formato TimeSpan a mm: ss para lapsos positivos y negativos
- 14. Conversión de marca de tiempo en Oracle para YYYY-MM-DD HH: MM: SS formato
- 15. Usando un NSTimer para HH: MM: SS?
- 16. ¿Cómo puedo formatear DateTime en formato web UTC?
- 17. Ruby on Rails: ¿cómo mostrar una fecha en el formato que necesito? Conversión de AAAA-MM-DD HH: MM: SS UTC a MM/DD/AAAA
- 18. ¿Cómo formateo la hora en [h]: formato mm excel usando la función de formateo() en VBA
- 19. NSTimeInterval a HH: mm: ss?
- 20. ¿Cómo se convierte el formato de tiempo de YYYY-MM-DDTHH: mm: ss.000Z al formato de hora MM/DD/YYYY en Python?
- 21. RegEx - Validación de tiempo ((h) h: mm)
- 22. ¿Hay un nombre para el formato de fecha "AAAA-MM-DD HH: MM: SS"?
- 23. ¿Cómo puedo comparar dos cadenas de tiempo en el formato HH: MM: SS?
- 24. C - Convertir time_t a cadena con formato AAAA-MM-DD HH: MM: SS
- 25. Mysql: Configure el formato de DATETIME en 'DD-MM-YYYY HH: MM: SS' al crear una tabla
- 26. ¿Cómo puedo convertir una indicación de fecha y hora de aaaa-MM-ddThh: mm: ss: formato SSSZ a MM/dd/aaaa hh: mm: ss.SSS? De ISO8601 a UTC
- 27. Obteniendo la hora actual como una cadena YYYY-MM-DD-HH-MM-SS
- 28. ¿Cómo puedo formatear una fecha json en formato dd/mm/aa en javascript?
- 29. Cómo convertir la fecha en formato "AAAA-MM-DD hh: mm: ss" a UNIX marca de tiempo
- 30. Cómo mostrar la fecha en formato HH: mm: ss en JasperReports?
¿Todavía recomendaría usar la biblioteca Joda Time cuando usa Java 8? –
@ TimBüthe: No, empezaría a usar java.time en ese caso. (Aunque no puedo encontrar inmediatamente un equivalente de PeriodFormatter ...) –
PeriodFormatter no está incluido. Esa es una de las diferencias entre Java 8 Date Time API y Joda Time. –