Как применить часовой пояс при форматировании DateTime?

У меня есть дата и время как 2011-01-11 01:51:10 и часовой пояс как America/Los_Angeles

Я хочу получить локализованную дату и время для этого значения. Это то, что я делаю

val formatter1: DateTimeFormatter = DateTimeFormatter.ofPattern("y-M-d H:m:s");
val m1: LocalDateTime = LocalDateTime.parse("2011-01-11 01:51:10", formatter1);
println("DateTime: " + m1.atZone(ZoneId.of("America/Los_Angeles")))

Значение, которое я получаю, равно

DateTime: 2011-01-11T01:51:10-08:00[America/Los_Angeles]

Как преобразовать его в локализованную дату и время с примененным к нему смещением -08:00 и без [America/Los_Angeles]?


person daydreamer    schedule 28.02.2016    source источник
comment
Я не уверен, что понимаю. LocalDateTime не имеет понятия часового пояса.   -  person Tunaki    schedule 29.02.2016
comment
конечно, я бы хотел, чтобы время переместилось назад 8 hours, применив смещение   -  person daydreamer    schedule 29.02.2016
comment
Во что вы пытаетесь преобразовать в? Какой-то другой часовой пояс? УНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ? Как указано в настоящее время, вы создаете ZonedDateTime, который является местным временем и часовым поясом, который вы указали. (1:51:10 по тихоокеанскому времени), оттуда ничего с ним не сделаешь. Вы, вероятно, хотите .toInstant() или .withZoneSameInstant(someOtherZone).   -  person Matt Johnson-Pint    schedule 29.02.2016
comment
Термин «локализованный» означает изменение языка и не связан с часовыми поясами, но я не понимаю, как ваш шаблон чувствителен к локали и не содержит никакой информации о часовых поясах. Вы имеете в виду локализацию отображения в другом часовом поясе со смещением -08:00, сохраняя тот же момент? Это совсем другое и не имеет ничего общего с i18n.   -  person Meno Hochschild    schedule 29.02.2016


Ответы (4)


Сначала вам нужно указать, в каком часовом поясе находится время, которое вы проанализировали. Затем укажите другой, в который нужно преобразовать.

DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("y-M-d H:m:s");
LocalDateTime m1 = LocalDateTime.parse("2011-01-11 01:51:10", formatter1);
ZonedDateTime z1 = m1.atZone(ZoneId.of("UTC"));
ZonedDateTime z2 = z1.withZoneSameInstant(ZoneId.of("America/Los_Angeles"));

System.out.println(z2.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
person softarn    schedule 29.02.2016
comment
Огромное спасибо @softarn. У меня была большая путаница с пониманием API - person daydreamer; 29.02.2016

Похоже, вы используете java.time API с ZonedDateTime. Вероятно, вам следует использовать его вместо LocalDateTime, так как у LocalDateTime нет часового пояса. Из документов:

Дата без часового пояса в календарной системе ISO-8601, например 2007-12-03.

Этот класс не хранит и не представляет время или часовой пояс. Вместо этого это описание даты, используемой для дней рождения. Он не может представлять мгновение на временной шкале без дополнительной информации, такой как смещение или часовой пояс.

А затем ZonedDateTime docs утверждает, что:

Дата-время с часовым поясом в календарной системе ISO-8601, например 2007-12-03T10:15:30+01:00 Европа/Париж.

Этот класс обрабатывает преобразование из локальной временной шкалы LocalDateTime в мгновенную временную шкалу Instant. Разница между двумя временными шкалами — это смещение от UTC/Greenwich, представленное ZoneOffset.

Используя ZonedDateTime, ваш код будет выглядеть так:

import java.time._
import java.time.format._

val zoneId = ZoneId.of("America/Los_Angeles")
val formatter = DateTimeFormatter.ofPattern("y-M-d H:m:s").withZone(zoneId)
val zdt = ZonedDateTime.parse("2011-01-11 01:51:10", formatter)

Результат, который вы увидите в консоли, будет таким:

zdt: java.time.ZonedDateTime = 2011-01-11T01:51:10-08:00[America/Los_Angeles]

Это происходит потому, что вы используете по умолчанию toString метод ZonedDateTime и выглядит как DateTimeFormatter.ISO_OFFSET_DATE_TIME - это именно то, что вам нужно. Итак, ваш код должен быть:

import java.time._
import java.time.format._

val zoneId = ZoneId.of("America/Los_Angeles")
val formatter = DateTimeFormatter.ofPattern("y-M-d H:m:s").withZone(zoneId)
val zdt = ZonedDateTime.parse("2011-01-11 01:51:10", formatter)
val formatted: String = zdt.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)
person marcospereira    schedule 28.02.2016
comment
Ответ 2011-01-11T01:51:10-08:00[America/Los_Angeles] вместо 2011-01-11T17:51:10 - person daydreamer; 29.02.2016
comment
Я зашел так далеко, но ответ по-прежнему 2011-01-11T01:51:10-08:00 - person daydreamer; 29.02.2016
comment
Вы хотите получить локализованную дату с другим часовым поясом? Не могли бы вы отредактировать свой вопрос, чтобы предоставить нам информацию о точном результате, который вы хотите? - person marcospereira; 29.02.2016

Пожалуйста, ознакомьтесь с моим полным ответом на этот вопрос. Ответ

    String dateTime = "MM/dd/yyyy HH:mm:ss";
    String date = "09/17/2017 20:53:31";
    Integer gmtPSTOffset = -8;
    ZoneOffset offset = ZoneOffset.ofHours(gmtPSTOffset);

    // String to LocalDateTime
    LocalDateTime ldt = LocalDateTime.parse(date, DateTimeFormatter.ofPattern(dateTime));
    // Set the generated LocalDateTime's TimeZone. In this case I set it to UTC
    ZonedDateTime ldtUTC = ldt.atZone(ZoneOffset.UTC);
    System.out.println("UTC time with Timezone          : "+ldtUTC);

    // Convert above UTC to PST. You can pass ZoneOffset or ZoneId for 2nd parameter
    LocalDateTime ldtPST = LocalDateTime.ofInstant(ldtUTC.toInstant(), offset);
    System.out.println("PST time without offset         : "+ldtPST);

    // If you want UTC time with timezone
    ZoneId zoneId = ZoneId.of( "America/Los_Angeles" );
    ZonedDateTime zdtPST = ldtUTC.toLocalDateTime().atZone(zoneId);
    System.out.println("PST time with Offset and TimeZone   : "+zdtPST);
person Neero    schedule 07.12.2017

вероятно, вы хотите получить время UTC, а затем применить к нему смещение часового пояса. Это довольно легко сделать со временем Джоды. Например:

DateTime.now().minus(timezoneOffset) 

где timezoneOffset — это int, который будет представлять сдвиг времени в вашем местоположении. Поправьте меня если я ошибаюсь.

person Artemis    schedule 28.02.2016
comment
Часовой пояс != Смещение. Вы не будете знать смещение заранее, и вычитание его в любом случае является неправильным подходом. Кроме того, OP уже показывает использование API времени Java 8, поэтому время Joda не подходит. Сохраните это для Java 7 и ниже. - person Matt Johnson-Pint; 29.02.2016