Konwersja Long na Date w Javie zwraca 1970


119

Mam listę z długimi wartościami (na przykład: 1220227200, 1220832000, 1221436800 ...), które pobrałem z serwisu internetowego. Muszę przekonwertować go na daty. Niestety w ten sposób na przykład:

Date d = new Date(1220227200);

zwraca 1 stycznia 1970. Czy ktoś zna inny sposób na poprawną konwersję?


Czy możesz powiedzieć, jakich wartości oczekujesz? Kwestia sekund / milisekund może być prawidłowa, ale 1220227200 to nie 1/1/1970. Wygląda na to, że przekazujesz konstruktorowi 0. Może trochę więcej kodu pomoże.
SJuan76,

1
@mmmiki - powinieneś zaakceptować odpowiedź
Stewart

zwraca 15 stycznia 1970, a nie 1 stycznia.
njzk2

FYI, strasznie wadliwe klasy daty i godziny, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą teraz starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i nowsze.
Basil Bourque

Odpowiedzi:


161

DateKonstruktor (kliknij w link!) Przyjmuje jako czas longw milisekundach , a nie sekundach. Musisz go pomnożyć przez 1000 i upewnić się, że podałeś jako long.

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

To widać tutaj

Niedziela, 31 sierpnia, 20:00:00 GMT-04: 00 2008


22
Lub alternatywnie, użyj Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));do czystszego i mniej magicznego rozwiązania.
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.

Poznaj swoje dane

Ludzie używają różnych dokładności w śledzeniu czasu jako liczby od epoki . Więc kiedy otrzymasz kilka liczb, które mają być zinterpretowane jako liczba od epoki, musisz określić:

  • Jakiej epoki?
    W różnych systemach używano dat z wielu epok . Powszechnie używany jest czas POSIX / Unix , gdzie epoka to pierwsza chwila 1970 roku w UTC. Ale nie powinieneś zakładać tej epoki.
  • Jaka precyzja?
    Czy mówimy o sekundach, milisekundach , mikrosekundach czy nanosekundach od epoki?
  • W jakiej strefie czasowej?
    Zwykle licznik, ponieważ epoka jest w strefie czasowej UTC / GMT, to znaczy w ogóle nie ma przesunięcia strefy czasowej. Ale czasami, gdy angażujemy niedoświadczonych lub nie znających się na czasie programistów, może istnieć domniemana strefa czasowa.

W twoim przypadku, jak zauważyli inni, wydaje się, że od ery Uniksa dano ci kilka sekund. Ale przekazujesz te sekundy konstruktorowi, który oczekuje milisekund. Więc rozwiązaniem jest pomnożenie przez 1000.

Zdobyta wiedza:

  • Określ, nie zakładaj, znaczenie otrzymanych danych.
  • Przeczytaj dokument .

Wykres przedstawiający różne poziomy rozdzielczości w systemach daty i czasu, w tym pełne sekundy, milisekundy, mikrosekundy i nanosekundy.

Twoje dane

Twoje dane wydają się być w całych sekundach. Jeśli przyjmiemy epokę początku 1970 roku i przyjmiemy strefę czasową UTC, to 1,220,227,200jest to pierwsza chwila pierwszego dnia września 2008 roku.

Joda-Time

Klasy java.util.Date i .Calendar dołączone do języka Java są notorycznie kłopotliwe. Unikaj ich. Zamiast tego użyj biblioteki Joda-Time lub nowego pakietu java.time dołączonego do języka Java 8 (i zainspirowanego Joda-Time).

Zauważ, że w przeciwieństwie do juDate, a DateTimew Joda-Time naprawdę zna swoją przypisaną strefę czasową . W poniższym przykładzie kodu Joda-Time 2.4 zauważ, że najpierw analizujemy milisekundy przy użyciu domyślnego założenia UTC. Następnie, po drugie, przypisujemy strefę czasową Paryża do dostosowania. Ten sam moment na osi czasu Wszechświata, ale inny zegar ścienny . W celach demonstracyjnych ponownie dostosowujemy się do UTC. Prawie zawsze lepiej jest jawnie określić żądaną / oczekiwaną strefę czasową niż polegać na domyślnej wartości domyślnej (często jest to przyczyna problemów w pracy z datą i godziną).

Potrzebujemy milisekund, aby skonstruować DateTime. Więc weź sekundy i pomnóż przez tysiąc. Zauważ, że wynik musi być 64-bitowy, longponieważ przepełnilibyśmy 32-bitowy 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".

Podaj tę liczbę milisekund do konstruktora. Ten konkretny konstruktor zakłada, że ​​licznik pochodzi z uniksowej epoki 1970. Po zakończeniu konstrukcji dostosuj strefę czasową według potrzeb.

Użyj prawidłowych nazw stref czasowych , kombinacji kontynentu i miasta / regionu. Nigdy nie używaj kodów 3- lub 4-literowych, ESTponieważ nie są one ani znormalizowane, ani unikalne.

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

W celu demonstracji ponownie ustaw strefę czasową.

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

Zrzuć na konsolę. Zwróć uwagę, jak różni się data w Montrealu, ponieważ nowy dzień zaczął się w Europie, ale jeszcze nie w Ameryce.

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

Po uruchomieniu.

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

Twórcy Joda-Time poprosili nas o migrację do jego zamiennika, frameworka java.time , tak szybko, jak będzie to wygodne. Chociaż Joda-Time jest nadal aktywnie wspierana, cały przyszły rozwój będzie się odbywał na klasach java.time i ich rozszerzeniach w projekcie ThreeTen-Extra.

Struktura czasu Java jest zdefiniowana przez JSR 310 i wbudowana w Javę 8 i nowszą. Klasy java.time zostały ponownie przeniesione do Javy 6 i 7 w projekcie ThreeTen-Backport oraz do systemu Android w projekcie ThreeTenABP .

Na Instantosi czasu znajduje się moment w UTC z rozdzielczością nanosekund. Jego epoka to pierwszy moment 1970 roku w UTC.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

Zastosuj przesunięcie od UTC, ZoneOffset aby uzyskać plik OffsetDateTime.

Jeszcze lepiej, jeśli jest znana, zastosuj strefę czasową, ZoneIdaby uzyskać ZonedDateTime.

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

Tabela wszystkich typów dat i godzin w Javie, zarówno nowoczesnych, jak i starszych


1
Pozdrawiam kolego. Świetne wyjaśnienie. Dostawałem nowy DateTime (<długa liczba>) od 1970, kiedy zdałem sobie sprawę, że daję go w sekundach i
wymagam

40

Wygląda na to, że długie sekundy to sekundy, a nie milisekundy. Konstruktor daty zajmuje milisekundy, więc

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh: Nie głosowałem przeciw, ale pierwotna odpowiedź była inna. Zredagował go w ciągu 5-minutowego okresu karencji.
BalusC,

Dziękuję za wyjaśnienie. To jest wada SO ...: - /
f1sh

10

Ustaw czas tylko w młynach w obiekcie kalendarza

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

Prawdopodobnie są to sygnatury czasowe w sekundach, a nie w milisekundach, co jest wymagane dla konstruktora Java new Date (long). Po prostu pomnóż je przez 1000 i wszystko będzie dobrze.


23
dokładniej 30000 milisekund za wolno
SJuan76

5

Najprawdopodobniej długie wartości odpowiadają sygnaturom czasowym epoki , a wartości to:

1220227200 = Pon, 01 Wrz 2008 00:00:00 GMT

1220832000 = Pon, 08 Wrz 2008 00:00:00 GMT

1221436800 = pon., 15 września 2008 r. 00:00:00 GMT

Można przekonwertować te długie wartości na java.util.Date , biorąc pod uwagę fakt, że java.util.Date używa miliseków - jak wspomniano wcześniej, ale z pewną wadą - taką jak ta:

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

Teraz, aby poprawnie wyświetlić datę, można użyć java.text.DateFormat, jak pokazano poniżej:

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

Poniżej znajdują się wyniki wyświetlania przekonwertowanej wartości długiej do java.util.Date bez użycia i użycia 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

Spróbuj tego:

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

3

Spróbuj tego, dostosowując format daty.

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

Uwaga: sprawdź cykl 24-godzinny lub 12-godzinny.


2

1220227200 odpowiada 15 stycznia 1980 r. (I rzeczywiście new Date (1220227200) .toString () zwraca „Thu Jan 15 03:57:07 CET 1970”). Jeśli przekażesz długą wartość do daty, czyli przed 01/01/1970, w rzeczywistości zwróci ona datę 01/01/1970. Upewnij się, że wartości nie znajdują się w tej sytuacji (niższe niż 82800000).


0

Nowa data (liczba) zwraca datę, która number milisekundach po 1 stycznia 1970 r. Szanse, że format daty nie pokazuje godzin, minut i sekund, aby zobaczyć, że jest trochę po 1 stycznia 1970 r.

Musisz przeanalizować datę zgodnie z prawidłowym routingiem analizy. Nie wiem, co to jest 1220227200, ale jeśli jest to kilka sekund po 1 stycznia 1970 r., Pomnóż to, aby uzyskać milisekundy. Jeśli tak nie jest, przekonwertuj go w jakiś sposób na milisekundy po 1970 r. (Jeśli chcesz nadal używać java.util.Date).


0

Pracuje dla mnie. Prawdopodobnie chcesz to pomnożyć przez 1000, ponieważ otrzymujesz sekundy z 1970 i musisz minąć milisekundy od 1 stycznia 1970

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.