Подтвердить что ты не робот

Как форматировать javax.time.Instant как строку в локальном часовом поясе?

Как мне отформатировать javax.time.Instant как строку в локальном часовом поясе? Ниже приведен локальный Instant to UTC, а не локальный часовой пояс, как я ожидал. Удаление вызова toLocalDateTime() делает то же самое. Как я могу получить местное время вместо этого?

public String getDateTimeString( final Instant instant )
{
    checkNotNull( instant );
    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
    DateTimeFormatter formatter = builder.appendPattern( "yyyyMMddHHmmss" ).toFormatter();
    return formatter.print( ZonedDateTime.ofInstant( instant, TimeZone.UTC ).toLocalDateTime() );
}

Примечание. Мы используем более старую версию 0.6.3 JSR-310.

4b9b3361

Ответ 1

Перед тем, как проголосовать за мой ответ, обратите внимание, что вопрос явно (и жирным шрифтом) относится к старой версии 0.6.3 эталонной реализации JSR-310! Я задал этот вопрос в декабре 2012 года задолго до появления Java 8 и новой библиотеки даты!


Я отказался от классов JSR-310 DateTimeFormatter и ZonedDateTime и вместо этого прибегал к старомодным java.util.Date и java.text.SimpleDateFormat:

public String getDateTimeString( final Instant instant )
{
    checkNotNull( instant );
    DateFormat format = new SimpleDateFormat( "yyyyMMddHHmmss" );
    Date date = new Date( instant.toEpochMillisLong() );
    return format.format( date );
}

Ответ 2

Отвечая на этот вопрос по почти завершенной версии JDK1.8

DateTimeFormatter formatter =
  DateTimeFormatter.ofPattern("yyyyMMddHHmmss").withZone(ZoneId.systemDefault());
return formatter.format(instant);

Ключ в том, что Instant не имеет информации о часовом поясе. Таким образом, он не может быть отформатирован с использованием каких-либо паттенов на основе полей даты/времени, таких как "yyyyMMddHHmmss". Указав зону в DateTimeFormatter, момент форматирования преобразуется в заданный часовой пояс, что позволяет правильно выводить его.

Альтернативный подход заключается в преобразовании в ZonedDateTime:

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
return formatter.format(ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()));

Оба подхода эквивалентны, но обычно я выбирал бы первый, если бы мой объект данных был Instant.

Ответ 3

Почему вы ожидаете, что он будет использовать локальный часовой пояс? Вы явно запрашиваете UTC:

ZonedDateTime.ofInstant(instant, TimeZone.UTC)

Просто укажите вместо этого локальный часовой пояс:

ZonedDateTime.ofInstant(instant, TimeZone.getDefault())

Ответ 4

Попробуйте следующее:

String dateTime = DateTimeFormatter.ISO_ZONED_DATE_TIME.format(
    ZonedDateTime.ofInstant(instant, ZoneId.systemDefault())
);

Это дает:

2014-08-25T21:52:07-07:00[America/Los_Angeles]

Вы можете изменить формат, используя в качестве форматирования что-то отличное от DateTimeFormatter.ISO_ZONED_DATE_TIME. DateTimeFormatter имеет кучу предопределенных форматировщиков, или вы можете определить свои собственные.