Преобразование Long в Date в Java возвращает 1970

119

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

Date d = new Date(1220227200);

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

мммики
источник
Не могли бы вы сказать, каких ценностей вы ожидаете? Вопрос о секундах / миллисекундах может быть правильным, но 1220227200 - это не 01.01.1970. Похоже, вы передаете 0 конструктору. Еще немного кода может помочь.
SJuan76
1
@mmmiki - вы должны принять ответ
Стюарт
здесь он возвращается 15 января 1970 года, а не 1 января.
njzk2
FYI, то ужасно испорчено классы даты и времени , такие как java.util.Date, java.util.Calendarи java.text.SimpleDateFormatтеперь наследие , вытесняется java.time классов , встроенных в Java 8 и более поздних версий.
Basil Bourque,

Ответы:

161

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

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

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

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

BalusC
источник
22
Или, Date d = new Date(TimeUnit.SECONDS.toMillis(1220227200L));в качестве альтернативы, используйте для более чистого и менее сложного решения.
Прииду Нимре, 24
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 времени

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

Обратите внимание, что в отличие от juDate, a 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 года. Поэтому настройте часовой пояс по желанию после построения.

Используйте правильные названия часовых поясов , сочетание континента и города / региона. Никогда не используйте трех- или четырехбуквенные коды, 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 .

An Instant- это момент на временной шкале в формате UTC с разрешением наносекунды. Его эпоха - это первый момент 1970 года по всемирному координированному времени.

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 (<long number>) с 1970 года, когда понял, что
задаю
40

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

Date d = new Date(timeInSeconds * 1000);
Codemwnci
источник
4
@ f1sh: Я не голосовал против, но исходный ответ был другим. Он отредактировал его в течение 5-минутного периода отсрочки.
BalusC
Спасибо за разъяснения. Это собственный недостаток у SO ...: - /
f1sh
10

Только установите время в мельницах на объекте 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

Вероятно, это временные метки в секундах, а не в миллисекундах, которые требуются для конструктора java new Date (long). Просто умножьте их на 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
Джек Г.
источник
4

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

Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(1220227200 * 1000);
System.out.println(cal.getTime());
Мохаммад Намвар
источник
3

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

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

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

Abhimanyu
источник
2

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

Шиванский дракон
источник
0

Новая дата (число) возвращает дату в numberмиллисекундах после 1 января 1970 года. Скорее всего, ваш формат даты не показывает часы, минуты и секунды, чтобы вы могли видеть, что это совсем немного после 1 января 1970 года.

Вам нужно проанализировать дату в соответствии с правильной маршрутизацией синтаксического анализа. Я не знаю, что такое 1220227200, но если это секунды после 1 ЯНВАРЯ 1970, умножьте его, чтобы получить миллисекунды. Если это не так, преобразуйте его каким-либо образом в миллисекунды после 1970 года (если вы хотите продолжать использовать java.util.Date).

Эдвин Бак
источник
0

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

Leifg
источник