Вопрос по datetime, java, datetime-format, timezone – конвертировать время эпохи в дату

17

Я пробовал миллион разных способов сделать это, но безрезультатно. Любая помощь приветствуется.

long millis = getMillisFromServer();
Date date = new Date(millis);
DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
String formatted = format.format(date);

Выше не работает.

По сути, я хочу получить время эпохи и преобразовать его в австралийское время. Мое местное время составляет +05.30, но, конечно, я не хочу, чтобы это было фактором, способствующим этому преобразованию.

РЕДАКТИРОВАТЬ-

Вывод, когда я запускаю ваш точный код,

эпоха 1318388699000

Ср. 12 октября 08:34:59 GMT + 05: 30 2011

10.12.2011 03:04:59

10.12.2011 14:04:59

@Hades: не могли бы вы сказать, в чемпуть ваш код не работает? Что вы видите и чего ожидали? Код работает для меня ... Jon Skeet
Этот код в порядке. Я не понимаю, чего вы хотите достичь, и почему этот код вам не подходит. Не могли бы вы привести пример с вводом и выводом кода? JB Nizet
Возможно, проблема, которую беспокоит ОП, заключается в том, что «Австралия / Сидней» не считается имеющим смещение 05:30, а скорее +10. Видетьideone.com/qydGJ Ray Toal

Ваш Ответ

3   ответа
9

что время эпохи указано в секундах, а объект Date принимает значение Long, которое указывается в миллисекундах. Следовательно, вам придется умножить значение эпохи на 1000, чтобы использовать его как длинное значение. Как ниже: -

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddhhmmss");
sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
Long dateLong=Long.parseLong(sdf.format(epoch*1000));
Как Оле В.В. говорит, что вам нужно умножитьlong ценности. Вы могли бы изменить1000 в1_000L сL в конце объявить его как 64-разрядное целое число. Подчеркивание - это новая функция в последних версиях Java, которая делает числовые литералы более читабельными. Basil Bourque
Чтобы это работалоepoch должен бытьlong, Этоint, ваше умножение переполнится, и вы получите неправильный результат. Также я не думаю, что ОП попросилLong результат, но, возможно, кто-то еще может использовать его. Ole V.V.
большое спасибо! Jboy Flaga
6

был очень хорошим ответом в 2011 году. В эти дни я рекомендую, чтобы никто не использовалDate, DateFormat а такжеSimpleDateFormat классы. Все это более естественно с современным API даты и времени Java.

Чтобы получить объект даты и времени из вашего миллиса:

    ZonedDateTime dateTime = Instant.ofEpochMilli(millis)
            .atZone(ZoneId.of("Australia/Sydney"));

Еслиmillis равняется1318388699000Lэто дает вам2011-10-12T14:04:59+11:00[Australia/Sydney], Если код каким-то странным образом окажется в JVM, которая не знает часового пояса Австралии / Сиднея, вы можете быть уверены, что получите уведомление через исключение.

Если вы хотите, чтобы дата-время в вашем формате строки для представления:

String formatted = dateTime.format(DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss"));

Результат:

12/10/2011 14:04:59

PS Я не знаю, что вы подразумеваете под «вышеописанным не работает». На моем компьютере ваш код в вопросе тоже печатается12/10/2011 14:04:59.

Альмист, всегда хорошая идея дать точный часовой пояс для своих временных операций. Спасибо за сообщение о вашей старой проблеме. @Аид Ole V.V.
Я думаю, что проблема заключалась в том, что телефон, на котором работал Android, находился в другом часовом поясе при конвертации; Я не думаю, что это будет иметь значение при запуске его на компьютере; который я выяснил только позже. Спасибо за обновленный ответ. Hades
27

Хорошо, так что вы не хотите, чтобы вашместный время (которое не Австралия), чтобы внести вклад в результат, но вместо этого австралийский часовой пояс. Ваш существующий код должен быть абсолютно нормальным, хотяСидней в настоящее время UTC + 11, не UTC + 10 .. Короткое, но полное тестовое приложение:

import java.util.*;
import java.text.*;

public class Test {
    public static void main(String[] args) throws InterruptedException {
        Date date = new Date(1318386508000L);
        DateFormat format = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        String formatted = format.format(date);
        System.out.println(formatted);
        format.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
        formatted = format.format(date);
        System.out.println(formatted);
    }
}

Выход:

12/10/2011 02:28:28
12/10/2011 13:28:28

Я бы также предложил вам начать использоватьВремя йода который просто намного лучше API даты / времени ...

: Обратите внимание, что если ваша система не знает оAustralia/Sydney часовой пояс, этобыло бы показать UTC. Например, если я изменю код, собирающийся использоватьTimeZone.getTimeZone("blah/blah") это покажет значение UTC дважды. Я предлагаю вам распечататьTimeZone.getTimeZone("Australia/Sydney").getDisplayName() и посмотри, что там написано ... и проверь свой код на опечатки тоже :)

@Hades: время в Сиднее сейчас UTC + 11, а не UTC + 10. Так что, если единственная проблема в том, что вы видели это часом не так, как вы ожидали, это, вероятно, были ваши ожидания Jon Skeet
проблема в том, когда я конвертирую это .. система печатает +0 по Гринвичу вместо австралийского времени. эпоха 1318388699000 ср 12 октября 08:34:59 GMT + 05: 30 2011 10.10.2011 03:04:59 10.10.2011 14:04:59 Это вывод, когда я запускаю твой код эпохи 1318388699000 ср 12 октября 08 : 34: 59 GMT + 05: 30 2011 10.10.2011 03:04:59 10.10.2011 14:04:59 Hades
@Hades: Что произойдет, если вы запустите точную, но полную программу в моем ответе? А что вы подразумеваете под "система печатает +0 по Гринвичу"? Возможно ли, что ваша система не знает о часовом поясе Австралии / Сиднея? Jon Skeet
1318386508000 <это время эпохи в милисе. Теперь я хочу перевести это в австралийское время. GMT + 10. Местное время на моем телефоне - GMT + 5. (Я хочу игнорировать это) Hades
@Hades: Ах, хорошо, это имеет смысл. Буду редактировать. Jon Skeet

Похожие вопросы