Convierta la marca de tiempo en milisegundos a hora con formato de cadena en Java

126

Estoy tratando de convertir un valor largo ( número de milisegundos transcurridos desde el 1/1/1970, es decir, Epoch ) a la hora del formato h:m:s:ms.

El valor largo que uso como marca de tiempo, lo obtengo del campo timestampde un evento de registro de log4j.

Hasta ahora he intentado lo siguiente y falla:

logEvent.timeStamp/ (1000*60*60)
TimeUnit.MILLISECONDS.toMinutes(logEvent.timeStamp)

pero obtengo un valor incorrecto:

1289375173771 for logEvent.timeStamp
358159  for logEvent.timeStamp/ (1000*60*60) 
21489586 for TimeUnit.MILLISECONDS.toMinutes(logEvent.timeStamp)

¿Cómo hago esto?

Cratilo
fuente

Respuestas:

188

Prueba esto:

Date date = new Date(logEvent.timeSTamp);
DateFormat formatter = new SimpleDateFormat("HH:mm:ss.SSS");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
String dateFormatted = formatter.format(date);

Consulte SimpleDateFormat para obtener una descripción de otras cadenas de formato que la clase acepta.

Vea el ejemplo ejecutable usando una entrada de 1200 ms.

manolowar
fuente
8
Comentario: HH imprimirá la hora en esa fecha (0-23), no la cantidad total de horas transcurridas desde 1970. Solo digo.
JohnyTex
44
Y no lo olvides. Old SimpleDateFormat no se puede usar multiproceso.
keiki
para importar SimpleDateFormat, use la importación como sigue:import java.text.*;
Naveen Kumar RB
1
Para su información, las viejas clases problemáticas de fecha y hora como java.util.Date, java.util.Calendary java.text.SimpleDateFormatahora son heredadas , suplantadas por las clases java.time integradas en Java 8 y posteriores. Ver Tutorial de Oracle . Ver: stackoverflow.com/a/4142428/642706
Basil Bourque
1
¿Cuál es el tipo de logevent? ¿Puedes por favor poner en la pregunta?
Raulp
127
long millis = durationInMillis % 1000;
long second = (durationInMillis / 1000) % 60;
long minute = (durationInMillis / (1000 * 60)) % 60;
long hour = (durationInMillis / (1000 * 60 * 60)) % 24;

String time = String.format("%02d:%02d:%02d.%d", hour, minute, second, millis);
Brajendra Pandey
fuente
13
Me gusta su solución mejor que la respuesta aceptada, ya que es un poco más explícita y no sufre problemas con la configuración regional. Aunque te pierdas la parte final: millis = millis% 1000, que con razón pondría milisegundos al final de la cadena formateada.
Ondrej Burkert
77
@WesleyDeKeirsmaeker, en general, la legibilidad es más importante que la concisión.
Alphaaa
2
¿Por qué resto con 24 por horas?
baboo
2
La división no es asociativa: 50000 / (1000 * 60) = 0.8333333333 mientras que 50000/1000 * 60 = 3000.
farnett
3
'millis = millis% 1000' falta: D \ ny si necesita días, aquí tiene: 'días largos = (millis / (1000 * 60 * 60 * 24));'
Adreamus
38

Le mostraré tres formas de (a) obtener el campo de minutos de un valor largo, y (b) imprimirlo usando el formato de Fecha que desee. Uno usa java.util.Calendar , otro usa Joda-Time , y el último usa el marco java.time integrado en Java 8 y versiones posteriores.

El marco java.time suplanta las antiguas clases de fecha y hora agrupadas, y está inspirado en Joda-Time, definido por JSR 310, y ampliado por el proyecto ThreeTen-Extra.

El marco java.time es el camino a seguir cuando se usa Java 8 y versiones posteriores. De lo contrario, como Android, use Joda-Time. Las clases java.util.Date/.Calendar son notoriamente problemáticas y deben evitarse.

java.util.Date & .Calendar

final long timestamp = new Date().getTime();

// with java.util.Date/Calendar api
final Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(timestamp);
// here's how to get the minutes
final int minutes = cal.get(Calendar.MINUTE);
// and here's how to get the String representation
final String timeString =
    new SimpleDateFormat("HH:mm:ss:SSS").format(cal.getTime());
System.out.println(minutes);
System.out.println(timeString);

Joda-Time

// with JodaTime 2.4
final DateTime dt = new DateTime(timestamp);
// here's how to get the minutes
final int minutes2 = dt.getMinuteOfHour();
// and here's how to get the String representation
final String timeString2 = dt.toString("HH:mm:ss:SSS");
System.out.println(minutes2);
System.out.println(timeString2);

Salida:

24
09: 24: 10: 254
24
09: 24: 10: 254

java.time

long millisecondsSinceEpoch = 1289375173771L;
Instant instant = Instant.ofEpochMilli ( millisecondsSinceEpoch );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , ZoneOffset.UTC );

DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "HH:mm:ss:SSS" );
String output = formatter.format ( zdt );

System.out.println ( "millisecondsSinceEpoch: " + millisecondsSinceEpoch + " instant: " + instant + " output: " + output );

milisegundos Desde la época: 1289375173771 instantáneo: 2010-11-10T07: 46: 13.771Z salida: 07: 46: 13: 771

Sean Patrick Floyd
fuente
1
¿Hay alguna razón de rendimiento o alguna otra razón, debería preferir Joda sobre el calendario?
Cratylus
1
en casos simples como este, no. En general: la API de Joda está mejor diseñada. por ejemplo, las fechas de Java son mutables. Las fechas de Joda no lo son. Joda también es más amigable con los programadores, puede acceder a casi todas las funciones desde la clase DateTime sin tener que realizar conversiones entre Fecha y Calendario
Sean Patrick Floyd
¿Tiene alguna dependencia que deba tener en cuenta?
Cratylus
2
Buena respuesta, pero sugiero también especificar la zona horaria en lugar de confiar implícitamente en la zona horaria predeterminada actual de la JVM. Entonces, la llamada al constructor de DateTime tendría un segundo argumento, un DateTimeZoneobjeto. De esta manera:new DateTime( timestamp, DateTimeZone.forID( "America/Montreal" ) )
Basil Bourque
2
@Cratylus Las clases java.time suplantan tanto a Joda-Time como a las antiguas clases de fecha y hora heredadas incluidas en Java. Joda-Time inspiró las clases java.time, ambos proyectos dirigidos por el mismo hombre, Stephen Colbourne.
Basil Bourque
22

Es posible usar apache commons (commons-lang3) y su clase DurationFormatUtils.

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-lang3</artifactId>
  <version>3.1</version>
</dependency>

Por ejemplo:

String formattedDuration = DurationFormatUtils.formatDurationHMS(12313152);
// formattedDuration value is "3:25:13.152"
String otherFormattedDuration = DurationFormatUtils.formatDuration(12313152, DurationFormatUtils.ISO_EXTENDED_FORMAT_PATTERN);
// otherFormattedDuration value is "P0000Y0M0DT3H25M13.152S"

Espero que pueda ayudar ...

YoCha
fuente
8
long second = TimeUnit.MILLISECONDS.toSeconds(millis);
long minute = TimeUnit.MILLISECONDS.toMinutes(millis);
long hour = TimeUnit.MILLISECONDS.toHours(millis);
millis -= TimeUnit.SECONDS.toMillis(second);
return String.format("%02d:%02d:%02d:%d", hour, minute, second, millis);
Lo Ka
fuente
2
Esto no parece correcto. ¿ TimeUnit.MILLISECONDS.toSeconds()Por ejemplo, convierte milisegundos a la misma duración en segundos o los segundos restantes después de restar horas y minutos? La solución requiere lo último.
Derek Mahar
Este método es incorrecto, devuelve 431220: 25873204: 1552392282: 0 si quiero convertir la fecha del 12 de marzo de 2019 a las 13h04 42s
0ddlyoko el
6
public static String timeDifference(long timeDifference1) {
long timeDifference = timeDifference1/1000;
int h = (int) (timeDifference / (3600));
int m = (int) ((timeDifference - (h * 3600)) / 60);
int s = (int) (timeDifference - (h * 3600) - m * 60);

return String.format("%02d:%02d:%02d", h,m,s);
Vivek Pal
fuente
4

Haciendo

logEvent.timeStamp / (1000*60*60)

te dará horas, no minutos. Tratar:

logEvent.timeStamp / (1000*60)

y terminarás con la misma respuesta que

TimeUnit.MILLISECONDS.toMinutes(logEvent.timeStamp)
Nico Huysamen
fuente
Pero TimeUnit.MILLISECONDS.toMinutes (logEvent.timeStamp) también me da basura. ¡21489586 no son minutos!
Cratylus
1
Es el número de minutos transcurridos desde el 01/01/1970.
Nico Huysamen
Ok, entonces, ¿cómo obtengo el formato que quiero? Es decir, 10: 50: 40: 450? No sé cómo usar la cantidad de minutos desde 1970.
Cratylus
Lo siento, solo pensé que querías saber cómo darle sentido. Vea la publicación de Seanizer, eso debería cubrirlo.
Nico Huysamen
3

Prueba esto:

    String sMillis = "10997195233";
    double dMillis = 0;

    int days = 0;
    int hours = 0;
    int minutes = 0;
    int seconds = 0;
    int millis = 0;

    String sTime;

    try {
        dMillis = Double.parseDouble(sMillis);
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }


    seconds = (int)(dMillis / 1000) % 60;
    millis = (int)(dMillis % 1000);

    if (seconds > 0) {
        minutes = (int)(dMillis / 1000 / 60) % 60;
        if (minutes > 0) {
            hours = (int)(dMillis / 1000 / 60 / 60) % 24;
            if (hours > 0) {
                days = (int)(dMillis / 1000 / 60 / 60 / 24);
                if (days > 0) {
                    sTime = days + " days " + hours + " hours " + minutes + " min " + seconds + " sec " + millis + " millisec";
                } else {
                    sTime = hours + " hours " + minutes + " min " + seconds + " sec " + millis + " millisec";
                }
            } else {
                sTime = minutes + " min " + seconds + " sec " + millis + " millisec";
            }
        } else {
            sTime = seconds + " sec " + millis + " millisec";
        }
    } else {
        sTime = dMillis + " millisec";
    }

    System.out.println("time: " + sTime);
LeoZao
fuente
0
    long hours = TimeUnit.MILLISECONDS.toHours(timeInMilliseconds);
    long minutes = TimeUnit.MILLISECONDS.toMinutes(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours));
    long seconds = TimeUnit.MILLISECONDS
            .toSeconds(timeInMilliseconds - TimeUnit.HOURS.toMillis(hours) - TimeUnit.MINUTES.toMillis(minutes));
    long milliseconds = timeInMilliseconds - TimeUnit.HOURS.toMillis(hours)
            - TimeUnit.MINUTES.toMillis(minutes) - TimeUnit.SECONDS.toMillis(seconds);
    return String.format("%02d:%02d:%02d:%d", hours, minutes, seconds, milliseconds);
Joel Richard Koett
fuente