La conversione da Long to Date in Java restituisce 1970


118

Ho una lista con valori lunghi (ad esempio: 1220227200, 1220832000, 1221436800 ...) che ho scaricato dal servizio web. Devo convertirlo in date. Purtroppo in questo modo, ad esempio:

Date d = new Date(1220227200);

restituisce 1 gen 1970. Qualcuno sa un altro modo per convertirlo correttamente?


Potresti dire quali valori ti aspetti? La questione dei secondi / millisecondi può essere valida, ma 1220227200 non è 1/1/1970. Sembra che tu stia passando 0 al costruttore. Un po 'di codice in più potrebbe aiutare.
SJuan76,

1
@mmmiki - dovresti accettare una risposta
Stewart

ritorna il 15 gennaio 1970, qui, non il 1 gennaio.
njzk2

Cordiali saluti, le classi data-ora terribilmente imperfette come java.util.Date, java.util.Calendare java.text.SimpleDateFormatsono ora legacy , soppiantate dalle classi java.time integrate in Java 8 e versioni successive.
Basil Bourque

Risposte:


161

Il Datecostruttore (fare clic sul collegamento!) Accetta l'ora longin millisecondi , non in secondi. Devi moltiplicarlo per 1000 e assicurarti di fornirlo come long.

Date d = new Date(1220227200L * 1000);

Questo mostra qui

Domenica 31 agosto 20:00:00 GMT-04: 00 2008


22
O in alternativa, usa Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));per una soluzione più pulita e meno magica .
Priidu Neemre

56

tl; dr

java.time.Instant                    // Represent a moment as seen in UTC. Internally, a count of nanoseconds since 1970-01-01T00:00Z.
.ofEpochSecond( 1_220_227_200L )     // Pass a count of whole seconds since the same epoch reference of 1970-01-01T00:00Z.

Conosci i tuoi dati

Le persone usano varie precisioni nel tracciare il tempo come un numero da un'epoca . Quindi, quando ottieni dei numeri da interpretare come un conteggio da un'epoca, devi determinare:

  • Quale epoca?
    Molte epoche date sono state utilizzate in vari sistemi. Comunemente usato è il tempo POSIX / Unix , dove l'epoca è il primo momento del 1970 in UTC. Ma non dovresti dare per scontato quest'epoca.
  • Quale precisione?
    Stiamo parlando di secondi, millisecondi , microsecondi o nanosecondi dall'epoca?
  • Quale fuso orario?
    Di solito un conteggio poiché epoch è nel fuso orario UTC / GMT, cioè non ha alcun offset di fuso orario. Ma a volte, quando si coinvolgono programmatori inesperti o ignoranti di data e ora, potrebbe esserci un fuso orario implicito.

Nel tuo caso, come altri hanno notato, sembra che ti siano stati dati secondi dall'epoca di Unix. Ma stai passando quei secondi a un costruttore che si aspetta millisecondi. Quindi la soluzione è moltiplicare per 1.000.

Lezioni imparate:

  • Determina, non dare per scontato, il significato dei dati ricevuti.
  • Leggi il documento .

Grafico che mostra varie granularità di risoluzione nei sistemi data-ora, inclusi secondi interi, millisecondi, microsecondi e nanosecondi.

I tuoi dati

I tuoi dati sembrano essere in secondi interi. Se assumiamo un'epoca dell'inizio del 1970 e se assumiamo il fuso orario UTC, allora 1,220,227,200è il primo momento del primo giorno di settembre 2008.

Joda-Time

Le classi java.util.Date e .Calendar in bundle con Java sono notoriamente problematiche. Evitali. Utilizza invece la libreria Joda-Time o il nuovo pacchetto java.time in bundle in Java 8 (e ispirato a Joda-Time).

Nota che a differenza di juDate, a DateTimein Joda-Time conosce veramente il proprio fuso orario assegnato . Quindi, nell'esempio del codice Joda-Time 2.4 visto di seguito, nota che prima analizziamo i millisecondi utilizzando l'ipotesi predefinita di UTC. Quindi, in secondo luogo, assegniamo un fuso orario di Parigi da regolare. Stesso momento nella linea temporale dell'Universo, ma diverso tempo dell'orologio da parete . Per dimostrazione, ci adattiamo di nuovo, a UTC. Quasi sempre meglio specificare esplicitamente il fuso orario desiderato / previsto piuttosto che fare affidamento su un valore predefinito implicito (spesso causa di problemi nel lavoro data-ora).

Abbiamo bisogno di millisecondi per costruire un DateTime. Quindi prendi il tuo input di secondi e moltiplica per mille. Tieni presente che il risultato deve essere un 64 bit, longpoiché andremmo in overflow a 32 bit int.

long input = 1_220_227_200L;  // Note the "L" appended to long integer literals.
long milliseconds = ( input * 1_000L ); // Use a "long", not the usual "int". Note the appended "L".

Fornisci quel conteggio di millisecondi al costruttore. Quel particolare costruttore presume che il conteggio sia dell'epoca Unix del 1970. Quindi regola il fuso orario come desideri, dopo la costruzione.

Utilizza nomi di fuso orario corretti , una combinazione di continente e città / regione. Non utilizzare mai codici di 3 o 4 lettere ESTcome non sono né standardizzati né univoci.

DateTime dateTimeParis = new DateTime( milliseconds ).withZone( DateTimeZone.forID( "Europe/Paris" ) );

Per la dimostrazione, regolare di nuovo il fuso orario.

DateTime dateTimeUtc = dateTimeParis.withZone( DateTimeZone.UTC );
DateTime dateTimeMontréal = dateTimeParis.withZone( DateTimeZone.forID( "America/Montreal" ) );

Scarica su console. Nota come la data è diversa a Montréal, poiché il nuovo giorno è iniziato in Europa ma non ancora in America.

System.out.println( "dateTimeParis: " + dateTimeParis );
System.out.println( "dateTimeUTC: " + dateTimeUtc );
System.out.println( "dateTimeMontréal: " + dateTimeMontréal );

Quando corri.

dateTimeParis: 2008-09-01T02:00:00.000+02:00
dateTimeUTC: 2008-09-01T00:00:00.000Z
dateTimeMontréal: 2008-08-31T20:00:00.000-04:00

java.time

I creatori di Joda-Time ci hanno chiesto di migrare al suo sostituto, il framework java.time non appena sarà conveniente. Sebbene Joda-Time continui ad essere attivamente supportato, tutto lo sviluppo futuro verrà effettuato sulle classi java.time e sulle loro estensioni nel progetto ThreeTen-Extra.

Il framework java-time è definito da JSR 310 e integrato in Java 8 e versioni successive. Le classi java.time sono state portate indietro su Java 6 e 7 nel progetto ThreeTen-Backport e su Android nel progetto ThreeTenABP .

Un Instantè un momento sulla timeline in UTC con una risoluzione di nanosecondi. La sua epoca è il primo momento del 1970 in UTC.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

Applica un offset da UTC ZoneOffset per ottenere un file OffsetDateTime.

Meglio ancora, se noto, applica un fuso orario ZoneIdper ottenere un file ZonedDateTime.

ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

Tabella di tutti i tipi di data e ora in Java, sia moderni che legacy


1
Salute, amico. Ottima spiegazione. Stavo ricevendo un nuovo DateTime (<numero lungo>) dal 1970 quando mi sono reso conto che lo stavo dando in pochi secondi e richiesto in millisecondi
Suyash Dixit,

40

Sembra che i tuoi lunghi siano secondi e non millisecondi. Il costruttore di date impiega il tempo in millisecondi, quindi

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh: non ho votato negativamente, ma la risposta originale era diversa. Lo ha modificato entro un periodo di grazia di 5 minuti.
BalusC

grazie per il chiarimento. Questo è l'unico svantaggio che SO ha ...: - /
f1sh

11

Impostare l'ora in mulini solo sull'oggetto Calendario

Calendar c = Calendar.getInstance();
c.setTimeInMillis(1385355600000l);
System.out.println(c.get(Calendar.YEAR));
System.out.println(c.get(Calendar.MONTH));
System.out.println(c.get(Calendar.DAY_OF_MONTH));
// get Date
System.out.println(c.getTime());

9

Quelli sono probabilmente timestamp in secondi e non in millisecondi che è richiesto per il nuovo costruttore java Date (long). Basta moltiplicarli per 1000 e dovresti stare bene.


23
più propriamente 30000 millisecondi troppo lenti
SJuan76

5

I valori lunghi, molto probabilmente, corrispondono ai timestamp di Epoch e i valori sono:

1220227200 = Lunedì 1 settembre 2008 00:00:00 GMT

1220832000 = Lunedì 8 settembre 2008 00:00:00 GMT

1221436800 = lunedì, 15 settembre 2008 00:00:00 GMT

Si può convertire questi valori lunghi per java.util.Date , tenendo conto del fatto java.util.Date utilizza millisecs - come già accennato, ma con qualche difetto - in questo modo:

// note: enforcing long literals (L), without it the values would just be wrong.
Date date = new Date(1220227200L * 1000L); 

Ora, per visualizzare correttamente la data, è possibile utilizzare java.text.DateFormat come illustrato di seguito:

DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println("Wrong date time value: " + date);
System.out.println("Correct date time value: " + df.format(date));

Di seguito sono riportati i risultati della visualizzazione del valore long convertito in java.util.Date senza utilizzare e utilizzare DateFormat:

Date wrong (off by 2 hours): Mon Sep 01 02:00:00 CEST 2008
Correct date : Monday, 1 September 2008 00:00:00 o'clock UTC

4

Prova questo:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());

2

1220227200 corrisponde al 15 gennaio 1980 (e in effetti la nuova data (1220227200) .toString () restituisce "Thu Jan 15 03:57:07 CET 1970"). Se si passa un valore long a una data, cioè antecedente al 01/01/1970, restituirà infatti una data del 01/01/1970. Assicurati che i tuoi valori non siano in questa situazione (inferiore a 82800000).


2

Prova questo con la regolazione del formato della data.

long longtime = 1212580300;
SimpleDateFormat dateFormat = new SimpleDateFormat("MMddyyHHmm");
Date date = (Date) dateFormat.parseObject(longtime + "");
System.out.println(date);

Nota: verificare il ciclo di 24 ore o 12 ore.


0

Nuova data (numero) restituisce una data che è in numbermillisecondi dopo il 1 ° gennaio 1970. È probabile che il formato della data non mostri ore, minuti e secondi per vedere che è solo un po 'dopo il 1 ° gennaio 1970.

È necessario analizzare la data in base al percorso di analisi corretto. Non so cosa sia un 1220227200, ma se sono secondi dopo il 1 gennaio 1970, moltiplicalo per ottenere millisecondi. Se non lo è, convertilo in qualche modo in millisecondi dopo il 1970 (se vuoi continuare a usare java.util.Date).


0

Per me va bene. Probabilmente vorrai multiplzarlo con 1000, poiché quello che ottieni sono i secondi del 1970 e devi passare i millisecondi dal 1 gennaio 1970

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.