Das Konvertieren von Long to Date in Java gibt 1970 zurück

118

Ich habe eine Liste mit langen Werten (zum Beispiel: 1220227200, 1220832000, 1221436800 ...), die ich vom Webdienst heruntergeladen habe. Ich muss es in Daten umwandeln. Leider so zum Beispiel:

Date d = new Date(1220227200);

gibt den 1. Januar 1970 zurück. Kennt jemand einen anderen Weg, um es richtig zu konvertieren?

mmmiki
quelle
Können Sie sagen, welche Werte Sie erwarten? Die Frage der Sekunden / Millisekunden mag gültig sein, aber 1220227200 ist nicht der 1.1.1970. Es sieht so aus, als würden Sie 0 an den Konstruktor übergeben. Etwas mehr Code könnte helfen.
SJuan76
1
@mmmiki - Sie sollten eine Antwort akzeptieren
Stewart
es kehrt am 15. Januar 1970 zurück, hier nicht am 1. Januar.
NJZK2
Zu Ihrer Information, die schrecklich fehlerhaft Datum Zeitklassen wie java.util.Date, java.util.Calendarund java.text.SimpleDateFormatsind jetzt Erbe , durch die verdrängte java.time Klassen in Java gebaut 8 und höher.
Basil Bourque

Antworten:

161

Der DateKonstruktor (klicken Sie auf den Link!) Akzeptiert die Zeit wie longin Millisekunden , nicht in Sekunden. Sie müssen es mit 1000 multiplizieren und sicherstellen, dass Sie es als angeben long.

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

Dies zeigt hier

So 31. August 20:00:00 GMT-04: 00 2008

BalusC
quelle
22
Oder verwenden Sie alternativ Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));eine sauberere und weniger magische Lösung.
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.

Kennen Sie Ihre Daten

Menschen verwenden seit einer Epoche verschiedene Präzisionen, um die Zeit als Zahl zu verfolgen . Wenn Sie also einige Zahlen erhalten, die seit einer Epoche als Zählung interpretiert werden sollen, müssen Sie Folgendes bestimmen:

  • Welche Epoche?
    Viele Epochendaten wurden in verschiedenen Systemen verwendet. Am häufigsten wird die POSIX / Unix-Zeit verwendet , bei der die Epoche der erste Moment des Jahres 1970 in UTC ist. Aber Sie sollten diese Epoche nicht annehmen .
  • Welche Präzision?
    Sprechen wir seit der Epoche über Sekunden, Millisekunden , Mikrosekunden oder Nanosekunden ?
  • Welche Zeitzone?
    Normalerweise hat eine Zählung seit der Epoche in der UTC / GMT-Zeitzone, dh sie hat überhaupt keinen Zeitzonenversatz. Aber manchmal, wenn unerfahrene oder datumsunabhängige Programmierer involviert sind, kann es eine implizite Zeitzone geben.

In Ihrem Fall scheinen Ihnen, wie andere angemerkt haben, Sekunden seit der Unix-Epoche gegeben worden zu sein. Sie übergeben diese Sekunden jedoch an einen Konstruktor, der Millisekunden erwartet. Die Lösung besteht also darin, mit 1.000 zu multiplizieren.

Gewonnene Erkenntnisse:

  • Bestimmen Sie nicht die Bedeutung der empfangenen Daten.
  • Lesen Sie das Dokument .

Diagramm, das verschiedene Granularitäten der Auflösung in Datums- / Zeitsystemen zeigt, einschließlich ganzer Sekunden, Millisekunden, Mikrosekunden und Nanosekunden.

Deine Daten

Ihre Daten scheinen in ganzen Sekunden zu sein. Wenn wir eine Epoche von Anfang 1970 annehmen und wenn wir eine UTC-Zeitzone annehmen, dann 1,220,227,200ist dies der erste Moment des ersten Tages im September 2008.

Joda-Zeit

Die mit Java gebündelten Klassen java.util.Date und .Calendar sind notorisch problematisch. Vermeide sie. Verwenden Sie stattdessen entweder die Joda-Time- Bibliothek oder das neue Java.time-Paket, das in Java 8 enthalten ist (und von Joda-Time inspiriert wurde).

Beachten Sie, dass a DateTimein Joda-Time im Gegensatz zu juDate seine eigene zugewiesene Zeitzone wirklich kennt . Beachten Sie im folgenden Beispielcode für Joda-Time 2.4, dass wir zuerst die Millisekunden unter Verwendung der Standardannahme von UTC analysieren. Zweitens weisen wir eine Zeitzone von Paris zu, um sie anzupassen. Gleicher Moment in der Zeitleiste des Universums, aber andere Wanduhrzeit . Zur Demonstration stellen wir uns erneut auf UTC ein. Es ist fast immer besser, die gewünschte / erwartete Zeitzone explizit anzugeben, als sich auf einen impliziten Standard zu verlassen (häufig die Ursache für Probleme bei der Arbeit mit Datum und Uhrzeit).

Wir brauchen Millisekunden, um eine DateTime zu erstellen. Nehmen Sie also Ihre Eingabe von Sekunden und multiplizieren Sie mit tausend. Beachten Sie, dass das Ergebnis ein 64-Bit sein muss, longda wir ein 32-Bit überlaufen würden 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".

Geben Sie diese Anzahl von Millisekunden an den Konstruktor weiter. Dieser spezielle Konstruktor geht davon aus, dass die Anzahl aus der Unix-Epoche von 1970 stammt. Passen Sie die Zeitzone nach der Konstruktion wie gewünscht an.

Verwenden Sie die richtigen Zeitzonennamen , eine Kombination aus Kontinent und Stadt / Region. Verwenden Sie niemals 3- oder 4-Buchstaben-Codes, ESTda diese weder standardisiert noch eindeutig sind.

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

Passen Sie zur Demonstration die Zeitzone erneut an.

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

Zur Konsole werfen. Beachten Sie, wie unterschiedlich das Datum in Montréal ist, da der neue Tag in Europa begonnen hat, aber noch nicht in Amerika.

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

Beim Ausführen.

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

Die Macher von Joda-Time haben uns gebeten, so bald wie möglich auf den Ersatz, das java.time- Framework , umzusteigen . Während Joda-Time weiterhin aktiv unterstützt wird, werden alle zukünftigen Entwicklungen für die java.time-Klassen und ihre Erweiterungen im ThreeTen-Extra-Projekt durchgeführt.

Das Java-Time-Framework wird von JSR 310 definiert und in Java 8 und höher integriert. Die java.time-Klassen wurden im ThreeTen-Backport- Projekt auf Java 6 und 7 und im ThreeTenABP- Projekt auf Android zurückportiert .

An Instantist ein Moment auf der Zeitachse in UTC mit einer Auflösung von Nanosekunden. Seine Epoche ist der erste Moment des Jahres 1970 in UTC.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

Wenden Sie einen Versatz von UTC ZoneOffset an, um eine zu erhalten OffsetDateTime.

Besser noch, wenn bekannt, wenden Sie eine Zeitzone ZoneIdan, um eine zu erhalten ZonedDateTime.

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

Tabelle aller Datums- und Uhrzeittypen in Java, sowohl moderne als auch ältere

Basil Bourque
quelle
1
Prost Kumpel. Tolle Erklärung. Ich bekam eine neue DateTime (<lange Nummer>) von 1970, als mir klar wurde, dass ich sie in Sekunden gab und in Millisekunden benötigte
Suyash Dixit
40

Es sieht so aus, als wären Ihre Longs Sekunden und keine Millisekunden. Der Datumskonstruktor benötigt also Zeit als Millis

Date d = new Date(timeInSeconds * 1000);
Codemwnci
quelle
4
@ f1sh: Ich habe nicht abgelehnt, aber die ursprüngliche Antwort war anders. Er hat es innerhalb von 5 Minuten bearbeitet.
BalusC
Danke für die Klarstellung. Das ist der eigene Nachteil, den SO hat ...: - /
f1sh
11

Stellen Sie die Zeit nur in Mühlen für das Kalenderobjekt ein

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());
Marlon
quelle
9

Dies sind wahrscheinlich Zeitstempel in Sekunden und nicht in Millisekunden, die für den Java New Date (Long) -Konstruktor erforderlich sind. Multiplizieren Sie sie einfach mit 1000 und Sie sollten in Ordnung sein.

Magnus Winter
quelle
23
besser 30000 Millisekunden zu langsam
SJuan76
5

Die langen Werte höchstwahrscheinlich entsprechen Epoch Zeitstempel, und die Werte sind:

1220227200 = Mo, 01. September 2008 00:00:00 GMT

1220832000 = Mo, 08. September 2008 00:00:00 GMT

1221436800 = Mo, 15. September 2008 00:00:00 GMT

Man kann diese langen Werte in java.util.Date konvertieren , wobei man berücksichtigt, dass java.util.Date Millisekunden verwendet - wie zuvor angedeutet, aber mit einigen Fehlern - wie folgt:

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

Um das Datum korrekt anzuzeigen, können Sie jetzt java.text.DateFormat verwenden, wie im Folgenden dargestellt:

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

Nachfolgend sind die Ergebnisse der Anzeige des konvertierten Long-Werts in java.util.Date ohne Verwendung und Verwendung des DateFormat aufgeführt:

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
Jack G.
quelle
4

Versuche dies:

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

1220227200 entspricht dem 15. Januar 1980 (und tatsächlich gibt das neue Datum (1220227200) .toString () "Do 15. Januar 03:57:07 MEZ 1970" zurück). Wenn Sie einen langen Wert an ein Datum übergeben, das vor dem 01.01.1970 liegt, wird tatsächlich ein Datum vom 01.01.1970 zurückgegeben. Stellen Sie sicher, dass sich Ihre Werte nicht in dieser Situation befinden (niedriger als 82800000).

Shivan Drache
quelle
2

Versuchen Sie dies, indem Sie das Datumsformat anpassen.

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

Hinweis: Überprüfen Sie den 24-Stunden- oder 12-Stunden-Zyklus.

abhimanyu
quelle
0

Neues Datum (Nummer) gibt ein Datum zurück, das numberMillisekunden nach dem 1. Januar 1970 liegt. Wahrscheinlich zeigt Ihr Datumsformat keine Stunden, Minuten und Sekunden an, damit Sie sehen, dass es nur ein wenig nach dem 1. Januar 1970 ist.

Sie müssen das Datum gemäß dem korrekten Parsing-Routing analysieren. Ich weiß nicht, was ein 1220227200 ist, aber wenn es Sekunden nach dem 1. Januar 1970 ist, multiplizieren Sie ihn, um Millisekunden zu erhalten. Wenn dies nicht der Fall ist, konvertieren Sie es nach 1970 auf irgendeine Weise in Millisekunden (wenn Sie weiterhin java.util.Date verwenden möchten).

Edwin Buck
quelle
0

Funktioniert bei mir. Sie möchten es wahrscheinlich mit 1000 multiplizieren, da Sie die Sekunden von 1970 erhalten und die Millisekunden ab dem 1. Januar 1970 übergeben müssen

leifg
quelle