Преобразование Long в Date в Java возвращает 1970 - PullRequest
99 голосов
/ 20 сентября 2011

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

Date d = new Date(1220227200);

возвращает 1 января 1970 года. Кто-нибудь знает другой способ преобразовать его правильно?

Ответы [ 11 ]

141 голосов
/ 20 сентября 2011

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

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

Это показано здесь

Вс 31 августа 20:00:00 GMT-04:00 2008

45 голосов
/ 18 декабря 2013

ТЛ; др

Instant.ofEpochSecond( 1_220_227_200L )

Знай свои данные

Люди используют различную точность во времени отслеживания как число с эпохи . Поэтому, когда вы получаете некоторые числа, которые будут интерпретироваться как число, начиная с эпохи, вы должны определить:

  • Какая эпоха?
    Многие даты эпох использовались в различных системах. Обычно используется POSIX / Unix time , где эпоха - это первый момент 1970 года в UTC. Но вы не должны предполагать эту эпоху.
  • Какая точность?
    Говорим ли мы секунды, миллисекунды , микросекунды или наносекунды со времен эпохи?
  • Какой часовой пояс?
    Обычно отсчет с эпохи находится в UTC / часовой пояс GMT, то есть часовой пояс вообще не имеет смещения. Но иногда, когда речь идет о неопытных или не знающих дату программистах, может быть подразумеваемый часовой пояс.

В вашем случае, как отмечали другие, вам, похоже, дали секунды с эпохи Unix. Но вы передаете эти секунды конструктору, который ожидает миллисекунды. Таким образом, решение заключается в умножении на 1000.

Извлеченные уроки:

  • Определите, не предполагайте, значение полученных данных.
  • Читать Документ .

Graph showing various granularities of resolution in date-time systems including whole seconds, milliseconds, microseconds, and nanoseconds.

Ваши данные

Ваши данные, кажется, в целых секундах. Если мы предположим эпоху начала 1970 года и если предположим часовой пояс UTC, то 1,220,227,200 - это первый момент первого дня сентября 2008 года.

Joda-Time

Классы java.util.Date и .Calendar, связанные с Java, общеизвестно проблематичны. Избежать их. Вместо этого используйте Joda-Time библиотеку или новый java.time пакет , связанный с Java 8 (и вдохновленный Joda-Time).

Обратите внимание, что в отличие от j.u.Date, 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.

Структура Java-времени определяется 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 );
37 голосов
/ 20 сентября 2011

Похоже, ваши длинные - секунды, а не миллисекундыКонструктор даты занимает время как миллис, поэтому

Date d = new Date(timeInSeconds * 1000);
9 голосов
/ 18 декабря 2013

Только установить время в мельницах на объекте Calendar

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 голосов
/ 20 сентября 2011

Это, вероятно, временные метки в секундах , а не в миллисекундах , которые требуются для нового Java-конструктора Date (long).Просто умножьте их на 1000, и все будет в порядке.

5 голосов
/ 24 мая 2013

Длинные значения, скорее всего, соответствуют Epoch отметкам времени, а значения:

1220227200 = понедельник, 01 сентября 2008 г., 00:00:00 по Гринвичу

1220832000 = Пн, 8 сентября 2008 00:00:00 по Гринвичу

1221436800 = Пн, 15 сентября 2008 00:00:00 по Гринвичу

Можно преобразовать эти длинные значения в 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
4 голосов
/ 17 февраля 2013

Попробуйте это:

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
2 голосов
/ 20 сентября 2011

1220227200 соответствует 15 января 1980 года (и действительно, новая Дата (1220227200) .toString () возвращает «Чт 15 января 03:57:07 CET 1970»). Если вы передаете длинное значение в дату, то есть до 01.01.1970, она фактически вернет дату 01.01.1970. Убедитесь, что ваши значения не в этой ситуации (ниже, чем 82800000).

1 голос
/ 02 ноября 2018

Попробуйте с настройкой формата даты.

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

Примечание. Проверьте цикл на 24 часа или 12 часов.

0 голосов
/ 20 сентября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...