Domanda

ho il seguente codice che prende una stringa di millisecondi (sarà da un feed RSS così sarà una stringa, l'esempio seguente è un programma di test rapido) e converte tali Millis in un oggetto Date.

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

Come si può vedere, tra la formattazione dell'oggetto di calendario e l'analisi della risultante String, un'ora si sta perdendo. Inoltre, la formattazione dell'output è cambiato. Qualcuno può aiutarmi per spiegare perché questo sta accadendo, e come ottenere intorno ad esso? Voglio che l'oggetto Date per essere lo stesso formato di uscita "Formato data".

È stato utile?

Soluzione

Credo che sta accadendo, perché il Regno Unito non effettivamente usare GMT nel 1970 ha fatto, e Java ha un bug in giro che ... lo farà formato una data nel 1970 come se il Regno Unito sono state usando GMT, ma senza realmente cambiare l'offset. Semplice esempio:

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));

Risultato:

01 Jan 1970 01:00:00 GMT

Si noti che afferma che di 1:00 GMT ... che non è corretto. E ' è stata 01:00 in tempo Europe / London, ma l'Europa / Londra non stava osservando GMT.

Joda Tempo ottiene questo diritto in quanto esso stampa BST - ma Joda il tempo non come < em> analisi i valori con le abbreviazioni di fuso orario. Tuttavia, è possibile ottenere in modo da utilizzare il fuso orario offets , invece:

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
    }
}

Altri suggerimenti

La risposta da Jon Skeet è corretta.

java.time

corriamo lo stesso ingresso attraverso java.time per vedere i risultati.

corretta oraria Nome . Non usare mai il 3-4 lettera sigla come BST, EST, o IST in quanto non sono zone tempo vero, non standardizzati, e nemmeno unico (!). Quindi usiamo Europe/London .

Il Instant classe rappresenta un momento sulla timeline in UTC con una risoluzione di nanosecondi .

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

Applicare un fuso orario per la produzione di un oggetto ZonedDateTime.

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

Dump alla console. Vediamo infatti che il tempo è un Europe/London avanti ora UTC in quel momento. Così il giorno tempo di è ora 02 anziché ore 01. Entrambi rappresentano lo stesso momento simultanea sulla timeline, visto solo attraverso le lenti di due differenti volte parete orologio .

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

ingresso: 1302805253 | istante: 1970-01-16T01: 53: 25.253Z | zdt: 1970-01-16T02: 53: 25,253 + 01: 00 [Europe / London]

secondi interi

A proposito, ho il sospetto la stringa di input rappresenta interi secondi dal periodo del 1970 UTC, piuttosto che millisecondi . Interpretato che come secondi si ottiene una data nel 2011, nel corso del mese a questa Domanda pubblicato.

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

2011-04-14T19: 20: 53 + 01: 00 [Europe / London]

A proposito di java.time

Il java.time quadro è integrato in Java 8 e versioni successive. Queste classi soppiantare le vecchie classi data-ora problematici, come java.util.Date, .Calendar, e java.text.SimpleDateFormat.

Il Joda Time progetto, ora in modalità manutenzione , consiglia migrazione java.time.

Per ulteriori informazioni, vedere la Oracle Tutorial . E cercare Stack Overflow per molti esempi e spiegazioni.

La maggior parte delle funzionalità java.time è di back-porting per Java 6 & 7 a ThreeTen-Backport e in seguito atto a Android in ThreeTenABP .

Il progetto ThreeTen-Extra estende java.time con classi aggiuntive. Questo progetto è un terreno di prova per eventuali future integrazioni java.time.

scroll top