Перетворення Long в дату в Java повертає 1970 рік


118

У мене є список із довгими значеннями (наприклад: 1220227200, 1220832000, 1221436800 ...), який я завантажив із веб-сервісу. Я повинен перетворити його на Дати. На жаль, таким чином, наприклад:

Date d = new Date(1220227200);

повертає 1 січня 1970 року. Хтось знає інший спосіб його правильного перетворення?


Чи можете ви сказати, яких цінностей ви очікуєте? Питання секунд / мілісекунд може бути правильним, але 1220227200 - це не 1/1/1970. Схоже, ви передаєте 0 конструктору. Ще якийсь код може допомогти.
SJuan76

1
@mmmiki - ви повинні прийняти відповідь
Стюарт

повертається 15 січня 1970 року, тут не 1 січня.
njzk2

FYI, жахливі недоліки класів дати, таких як java.util.Date, java.util.Calendarі java.text.SimpleDateFormatтепер є застарілими , витіснені класами java.time, вбудованими в Java 8 та новіших версій.
Василь Бурк

Відповіді:


161

DateКонструктор (натисніть на лінк!) Приймає час як longв мілісекундах , а НЕ секунд. Вам потрібно помножити його на 1000 і переконатися, що ви подаєте його як long.

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

Це показано тут

Нд 31 серпня 20:00:00 GMT-04: 00 2008


22
Або, як варіант, використовувати Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));більш чисте і менш магічне число .
Priidu Neemre

56

тл; д-р

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.

Знайте свої дані

Люди використовують різні точності, відслідковуючи час як число з епохи . Отже, коли ви отримуєте кілька чисел, які слід інтерпретувати як підрахунок з епохи, ви повинні визначити:

  • Яка епоха?
    У багатьох системах епох було використано в різних системах. Найчастіше використовується час POSIX / Unix , де епоха - перший момент 1970 року в UTC. Але не варто вважати цю епоху.
  • Яка точність?
    Ми говоримо секунди, мілісекунди , мікросекунди або наносекунди з епохи?
  • Який часовий пояс?
    Зазвичай відлік часу, оскільки епоха знаходиться в часовому поясі UTC / GMT, тобто взагалі не зміщений часовий пояс. Але іноді, коли залучаються недосвідчені програмісти або незнаючі програмісти часу, може виникати часовий пояс.

У вашому випадку, як зазначали інші, вам здається, що вам здали секунди з епохи Unix. Але ви передаєте ці секунди конструктору, який очікує мілісекунд. Тож рішення - помножити на 1000.

Уроки:

  • Визначте, не припускайте, значення отриманих даних.
  • Прочитайте док .

Графік, що показує різні деталі роздільної здатності в системах дати та часу, включаючи цілі секунди, мілісекунди, мікросекунди та наносекунди.

Ваші дані

Ваші дані здаються цілими секундами. Якщо припустити епоху початку 1970 року, і якщо припустити часовий пояс UTC, то 1,220,227,200це перший момент першого вересня 2008 року.

Joda-Time

Класи java.util.Date та .Calendar у комплекті з Java, як відомо, не викликають труднощів. Уникайте їх. Використовуйте замість цього або бібліотеку Joda -Time, або новий пакет java.time, що вкладається в Java 8 (і натхненний Joda-Time).

Зауважте, що на відміну від juDate, DateTimeв Joda-Time справді знає свій призначений часовий пояс . Отже, у прикладі коду Joda-Time 2.4, наведеному нижче, зауважимо, що ми спочатку аналізуємо мілісекунди, використовуючи стандартне припущення про UTC. Потім, по-друге, ми призначаємо часовий пояс Парижа для коригування. Той самий момент на часовій шкалі Всесвіту, але різний час настінного годинника . Для демонстрації ми знову налаштовуємо на UTC. Майже завжди краще чітко вказати бажаний / очікуваний часовий пояс, а не покладатися на неявний дефолт (часто причина неприємностей у роботі з датою).

Нам потрібні мілісекунди, щоб побудувати DateTime. Тому візьміть свій внесок на секунди і помножте на тисячу. Зауважте, що результат повинен бути 64-бітовим, longоскільки ми переповнюємо 32-бітний 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".

Подайте цю кількість, яка зараховується до конструктора. Цей конкретний конструктор припускає, що це число походить з епохи Unix 1970 року. Тому відрегулюйте часовий пояс за бажанням після будівництва.

Використовуйте належні назви часових поясів , поєднання континенту та міста / регіону. Ніколи не використовуйте 3 або 4 буквених кодів, таких ESTяк вони не є ні стандартизованими, ні унікальними.

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

Для демонстрації знову відрегулюйте часовий пояс.

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

Скиньте до консолі. Зауважте, чим відрізняється дата в Монреалі, оскільки новий день розпочався в Європі, але ще не в Америці.

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

Коли бігають.

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

Виробники Joda-Time попросили нас перейти на її заміну, рамки java.time, як тільки це зручно. Поки Joda-Time продовжує активно підтримуватися, вся майбутня розробка відбуватиметься на класах java.time та їх розширення в проекті ThreeTen-Extra.

Ява-часові рамки визначені JSR 310 та вбудовані в Java 8 та новіші версії. Класи java.time були перенесені назад на Java 6 та 7 у проекті ThreeTen-Backport та на Android у проекті ThreeTenABP .

InstantЦе момент на шкалі часу в UTC з дозволом наносекунд. Його епоха - це перший момент 1970 року в UTC.

Instant instant = Instant.ofEpochSecond( 1_220_227_200L );

Застосуйте зміщення з-за UTC, ZoneOffset щоб отримати OffsetDateTime.

Ще краще, якщо відомо, застосуйте часовий пояс, ZoneIdщоб отримати ZonedDateTime.

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

Таблиця всіх типів дат та часу на Java, як сучасних, так і застарілих


1
Ура, приятель. Чудове пояснення. Я отримував новий DateTime (<довге число>) з 1970 року, коли зрозумів, що даю його за секунди і потрібно в мілісекундах
Suyash Dixit

40

Схоже, ваші довгі секунди, а не мілісекунди. Конструктор дат займає час як міліс, так

Date d = new Date(timeInSeconds * 1000);

4
@ f1sh: Я не заявив, але початкова відповідь була іншою. Він відредагував його протягом 5 хвилин пільгового періоду.
BalusC

дякую за роз’яснення Це власне недолік SO має ...: - /
f1sh

11

Встановіть час у млинах на об’єкті Календар

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

Це, ймовірно, часові позначки в секундах, а не в мілісекундах, що потрібно для нового конструктора Java (довгий). Просто помножте їх на 1000, і ви повинні бути в порядку.


23
правильніше 30000 мілісекунд занадто повільно
SJuan76,

5

Довгі значення, швидше за все, відповідають часовим позначкам епохи , а такі значення:

1220227200 = Пн, 01 вересня 2008 00:00:00 GMT

1220832000 = Пн, 08 вересня 2008 00:00:00 GMT

1221436800 = Пн, 15 вересня 2008 00:00:00 GMT

Можна перетворити ці довгі значення в java.util.Date , беручи до уваги факт java.util.Date, використовує мілісекс - як раніше натякали, але з деяким недоліком - ось так:

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

Тепер, щоб правильно відобразити дату, можна використовувати java.text.DateFormat, як показано далі:

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

Нижче наведені результати відображення перетвореного довгого значення в java.util.Date без використання та використання 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


2

1220227200 відповідає 15 січня 1980 р. (І справді нова дата (1220227200) .toString () повертається "Чт 15 січня 03:57:07 CET 1970"). Якщо ви передасте велике значення даті, тобто до 01.01.1970, воно фактично поверне дату 01.01.1970. Переконайтеся, що ваші значення не знаходяться в цій ситуації (нижче 82800000).


2

Спробуйте це, скоригувавши формат дати.

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

Примітка. Перевірте цикл 24 години або 12 годин.


0

Нова дата (число) повертає дату, яка є numberмілісекундами після 1 січня 1970 року. Коефіцієнти, що ви, формат дати не відображає годин, хвилин і секунд, щоб ви побачили, що це лише трохи після 1 січня 1970 року.

Вам потрібно проаналізувати дату відповідно до правильної маршрутизації розбору. Я не знаю, що таке 1220227200, але якщо через 1 січня 1970 року минуло кілька секунд, то помножте його, щоб отримати мілісекунди. Якщо його немає, то перетворіть його якось у мілісекунди після 1970 року (якщо ви хочете продовжувати використовувати java.util.Date).


0

Працює для мене. Ви, мабуть, хочете помножити його на 1000, оскільки ви отримаєте секунди з 1970 року, і вам доведеться пройти мілісекунди з 1 січня 1970 р.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.