Pregunta

Tengo el siguiente código que toma una cadena de milisegundos (será de una alimentación RSS, por lo que habrá una cadena, el siguiente programa es un programa de prueba rápida) y convierte esos milis en un objeto de fecha.

public static void main(String[] args) {
    String ms = "1302805253";
    SimpleDateFormat dateFormatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(Long.parseLong(ms));

    try {
        String dateFormat = dateFormatter.format(calendar.getTime());
        System.out.println("Date Format = " + dateFormat);

        Date dateParse = dateFormatter.parse(dateFormatter.format(calendar.getTime()));
        System.out.println("Date Parse  = " + dateParse);
    } catch (ParseException e) {
        // TODO: handle exception
    }
}


Output:
    Date Format = Fri, 16 Jan 1970 02:53:25 GMT
    Date Parse  = Fri Jan 16 03:53:25 GMT 1970

Como puede ver, entre el formato del objeto calendario y el análisis de la cadena resultante, se está perdiendo una hora. Además, el formato de la salida ha cambiado. ¿Alguien puede ayudarme en cuanto a por qué está sucediendo esto y cómo evitarlo? Quiero que el objeto de fecha sea el mismo formato que la salida de "formato de fecha".

¿Fue útil?

Solución

Creo que está sucediendo porque el Reino Unido no Realmente Use GMT en 1970, y Java tiene un error en torno a eso ... formato Una fecha en 1970 como si el Reino Unido estuviera usando GMT, pero sin cambiar realmente el desplazamiento. Ejemplo simple:

Date date = new Date(0);
SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy HH:mm:ss zzz");
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(sdf.format(date));

Resultado:

01 Jan 1970 01:00:00 GMT

Tenga en cuenta que afirma que es 1 a.m. GMT ... que es incorrecto. Eso estaba 1 AM en Europa/Londres, pero Europa/Londres no estaba observando GMT.

Tiempo de Joda Hace esto bien, ya que imprime BST, pero a Joda Time no le gusta analizador Valores con abreviaturas de la zona horaria. Sin embargo, puede lograr que use la zona horaria salpicaduras en cambio:

import org.joda.time.*;
import org.joda.time.format.*;

public class Test {
    public static void main(String[] args) throws Exception {
        DateTime date = new DateTime(0, DateTimeZone.forID("Europe/London"));

        DateTimeFormatter formatter = DateTimeFormat.forPattern(
            "dd MMM yyyy HH:mm:ss Z");

        String text = formatter.print(date); // 01 Jan 1970 01:00:00 +0100
        System.out.println(text);

        DateTime parsed = formatter.parseDateTime(text);
        System.out.println(parsed.equals(date)); // true
    }
}

Otros consejos

los Respuesta de Jon Skeet es correcto.

java.time

Ejecutemos la misma entrada a través de Java.Time para ver los resultados.

Especificar un Nombre de la zona horaria adecuada. Nunca use la abreviatura de 3-4 letras como BST, EST, o IST ya que no son verdaderas zonas horarias, no estandarizadas, y ni siquiera únicas (!). Entonces usamos Europe/London.

los Instant la clase representa un momento en la línea de tiempo en UTC con una resolución de nanosegundos.

String input = "1302805253";
long millis = Long.parseLong ( input );
Instant instant = Instant.ofEpochMilli ( millis );

Aplicar una zona horaria para producir un ZonedDateTime objeto.

ZoneId zoneId = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = instant.atZone ( zoneId );

Volcado a la consola. Vemos de hecho que Europe/London El tiempo es una hora por delante de UTC en ese momento. Entonces la hora del día es 02 horas en lugar de 01 horas. Ambos representan el mismo momento simultáneo en la línea de tiempo, recién visto a través de las lentes de dos diferentes tiempos de pared.

System.out.println ( "input: " + input + " | instant: " + instant + " | zdt: " + zdt );

Entrada: 1302805253 | Instantáneo: 1970-01-16T01: 53: 25.253Z | ZDT: 1970-01-16T02: 53: 25.253+01: 00 [Europa/Londres

Segundos enteros

Por cierto, sospecho que su cadena de entrada representa entero segundos desde la época de 1970 UTC en lugar de milisegundos. Interpretó que como segundos obtenemos una fecha en 2011, en el mes que se publicó esta pregunta.

String output = Instant.ofEpochSecond ( Long.parseLong ( "1302805253" ) ).atZone ( ZoneId.of ( "Europe/London" ) ).toString ();

2011-04-14T19: 20: 53+01: 00 [Europa/Londres

Acerca de Java.time

los java.time El marco está integrado en Java 8 y más tarde. Estas clases suplantan las viejas clases problemáticas de fecha de fecha como java.util.Date, .Calendar, & java.text.SimpleDateFormat.

los Joda-tiempo proyecto, ahora en modo de mantenimiento, aconseja la migración a Java.Time.

Para aprender más, ver el Tutorial de Oracle. Y buscar desbordamiento de la pila de búsqueda para muchos ejemplos y explicaciones.

Gran parte de la funcionalidad de Java.Time está en el puerto posterior a Java 6 y 7 en Threeten-backport y más adaptado a Androide en Threetenabp.

los Threeten-Extra El proyecto extiende Java.Time con clases adicionales. Este proyecto es un campo de pruebas para posibles adiciones futuras a Java.Time.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top