2015-06-10 1 views
2

У меня есть трудное преобразование форматированной строки ISO 8601 в java.time.LocalDateTime, которая находится в UTC.Java Time API, преобразующий ISO 8601 в ZonedDateTime

Более конкретно, я пытаюсь написать XMLAdapter, для которого вы можете ввести в различных ISO 8601 DataFormats в виде строки (т.е. 2002-09-24, 2011-03-22T13:30, 2015-05-24T12:25:15Z, 2015-07-28T11:11:15.321+05:30) и который выдает LocalDateTime в UTC и наоборот.

В системе хранятся все данные о дате и времени в UTC. Когда пользователь запрашивает дату или время, он представляется пользователю на основе собственного ZoneId.

ответ

0

Как следует из названия LocalDateTime содержит как дату, так и время. Например, первый пример строки даты, который у вас есть в вашем вопросе, содержит только информацию о дате, поэтому вы не можете разобрать ее непосредственно в LocalDateTime. Что вы можете сделать, так это сначала разобрать его на LocalDate и установив время на этом объекте, получив LocalDateTime.

LocalDateTime localDateTime = LocalDate.parse("2002-09-24").atStartOfDay(); 

Все даты и времени объекты имеют метод синтаксического анализа, как LocalDate который может занять определенный формат строки. Эти форматы являются различными стандартными форматами ISO, указанными в DateTimeFormatter

Для форматирования пользовательских строк даты и времени в объектах Temporal используйте DateTimeFormatter и укажите произвольный шаблон.

+0

Этот ответ менее оптимален. 'LocalDateTime' намеренно не имеет информации о часовом поясе или смещении-от-UTC. В этой ситуации нет необходимости игнорировать или избавляться от этой важной информации. Кроме того, вы неявно применяете текущий часовой пояс JVM по умолчанию к вашему вызову 'atStartOfDay'. Таким образом, результаты будут зависеть от текущего текущего часового пояса. –

-1
public class LocalDateTimeXmlAdapter extends XmlAdapter<String, LocalDateTime> { 

    private static final Pattern ZONE_PATTERN = Pattern.compile("T.*(\\+|\\-|Z)"); 

    @Override 
    public LocalDateTime unmarshal(String isoDateTime) throws Exception { 
     LocalDateTime utcDateTime; 
     if (ZONE_PATTERN.matcher(isoDateTime).matches()) { 
      OffsetDateTime offsetDateTime = OffsetDateTime.parse(isoDateTime, DateTimeFormatter.ISO_DATE_TIME); 
      ZoneOffset offset = offsetDateTime.getOffset(); 
      utcDateTime = offsetDateTime.toLocalDateTime().plusSeconds(offset.getTotalSeconds()); 
     } else { 
      LocalDateTime localDateTime = LocalDateTime.parse(isoDateTime, DateTimeFormatter.ISO_DATE_TIME); 
      ZoneId zoneId = ZoneId.systemDefault(); // TODO: Get ZoneId from userProfile 
      ZoneOffset offset = ZonedDateTime.now(zoneId).getOffset(); 
      utcDateTime = localDateTime.minusSeconds(offset.getTotalSeconds()); 
     } 
     return utcDateTime; 
    } 

    @Override 
    public String marshal(LocalDateTime utcDateTime) throws Exception { 
     ZoneId zoneId = ZoneId.systemDefault(); // TODO: Get ZoneId from userProfile 
     ZoneOffset offset = ZonedDateTime.now(zoneId).getOffset(); 
     return utcDateTime.plusSeconds(offset.getTotalSeconds()).format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); 
    } 

} 
2

Т.Л., д-р

Instant.parse("2015-05-24T12:25:15Z") 
     .atZone(ZoneId.of("America/Montreal")) 

ZonedDateTime против LocalDateTime

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

Например, LocalDateTime Рождества, начиная с этого года является 2017-12-25T00:00:00, но это не имеет никакого значения, пока не применяется часовой пояс, как Санта доставляет первый на острова Kiribati в их полночь (первый в полночь на Земле), а затем на Новой Зеландии в их более позднюю полночь, затем в Австралию в их более позднюю полночь и так далее, двигаясь на запад к последовательным полуночи.

Кроме того, вы, кажется, смущенно о том, что такое ввод и какой выход.

Instant

Для входа как 2015-05-24T12:25:15Z, который представляет собой момент на временной шкале в формате UTC (Z короток для Zulu и средства UTC). Чтобы представить это, используйте класс Instant. Класс Instant представляет собой момент на временной шкале в UTC с разрешением nanoseconds (до девяти (9) цифр десятичной дроби).

Instant instant = Instant.parse("2015-05-24T12:25:15Z"); 

Как правило, вы должны работать в UTC для большинства бизнес-логик, хранения данных, обмена данными и базы данных. Так что для этого Instant - это все, что вам нужно.

ZonedDateTime

Если вам нужно настроить во временной зону, в том числе для представления пользователя, применить ZoneId получить ZonedDateTime.

Указать proper time zone name в формате continent/region, такие как America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте аббревиатуру 3-4 буквы, такую ​​как EST или IST, так как они не настоящие часовые пояса, не стандартизированные, и даже не уникальные (!).

ZoneId z = ZoneId.of("America/Montreal"); 
ZonedDateTime zdt = instant.atZone(z); 

LocalDate

Если у вас есть дата только значение, синтаксический как LocalDate объекта.

LocalDate localDate = LocalDate.parse("2002-09-24"); 

Чтобы получить первый момент дня на эту дату, укажите часовой пояс. В любой данный момент дата изменяется по всему миру по зонам.

Кроме того, не предполагайте, что день начинается во время 00:00:00. Аномалии, такие как переход на летнее время (DST), могут привести к тому, что первый момент будет примерно 01:00:00. Пусть java.time определяет время начала первого момента.

ZonedDateTime zdt = localDate.atStartOfDay(z); 

О java.time

java.time каркас встроен в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Проект Joda-Time, в настоящее время в maintenance mode, советует перейти на классы java.time.

Чтобы узнать больше, см. Oracle Tutorial. И поиск Stack Overflow для многих примеров и объяснений. Спецификация: JSR 310.

Где получить классы java.time?

  • Java SE 8 и SE 9, а затем
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и SE 7
    • Большая часть функциональности java.time будет обратно портирован на Java 6 & 7 в ThreeTen-Backport.
  • Android

ThreeTen-Extra Проект расширяет java.time с дополнительными классами. Этот проект является доказательством возможных будущих дополнений к java.time. Здесь вы можете найти полезные классы, такие как Interval, YearWeek, YearQuarter и more.