Дата изменилась при преобразовании из java.util.Date в javax.xml.datatype.XMLGregorianCalendar

Дата Чт 27 сентября 00:00:00 CEST 2018

становится

2018-09-26T22:00:00.000Z

при преобразовании в XMLGregorianCalendar

этим методом:

 public static XMLGregorianCalendar dateToXMLGregorianCalendar(Date date) throws DatatypeConfigurationException{
    GregorianCalendar cal = new GregorianCalendar();
    cal.setTime(date);
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
}

Как я могу избежать этого изменения даты?

Tnx

2 ответа

Это вопрос с несколькими возможными ответами в зависимости от ваших обстоятельств и точных требований. Я предполагаю, что вы просите XMLGregorianCalendar потому что вы собираетесь использовать его в документе XML, где его toXMLFormat Метод производит синтаксис, который вам нужен.

Попробуйте, если LocalDate работает

    LocalDate ld = LocalDate.of(2018, Month.SEPTEMBER, 27);
    System.out.println(ld);

Это выводит:

2018-09-27

Если то, что вам нужно поместить в ваш XML-документ, это дата, а не дата и время и смещение UTC, это было бы логичным решением. Выше приведен правильный формат даты в XML (проверьте ссылки внизу). Приемник вашего XML-документа принимает его, я не могу сказать. Я бы узнал, если бы это был я.

Метод в вашем вопросе принимает Date аргумент. Date Класс давно устарел и имеет проблемы с дизайном, поэтому избегайте его, если можете. Если вы не можете избежать этого, конвертируйте его в LocalDate как это:

    ZoneId zone = ZoneId.of("Europe/Rome");
    LocalDate ld = date.toInstant().atZone(zone).toLocalDate();

Пожалуйста, используйте желаемый часовой пояс, в который я поместил Европу / Рим, поскольку во всех часовых поясах никогда не бывает одинаковых дат Правильный часовой пояс - то, что контролирует, получите ли вы 26 или 27 сентября.

Использовать OffsetDateTime

    ZoneId zone = ZoneId.of("Europe/Rome");
    OffsetDateTime odt = LocalDate.of(2018, Month.SEPTEMBER, 27)
                            .atStartOfDay(zone)
                            .toOffsetDateTime();
    System.out.println(odt);

2018-09-27T00: 00 + 02: 00

Это почти синтаксис, который вы также получаете от XMLGregorianCalendar (XMLGregorianCalendar мог бы это тоже произвести, если бы захотел). Секунды и миллисекунды не включены. Опять же, проверьте, все ли в порядке. Если это не так, отформатируйте OffsetDateTime в String для вашего XML:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSSxxx");
    String dateTimeString = odt.format(formatter);
    System.out.println(dateTimeString);

2018-09-27T00: 00: 00,000+02:00

Это соответствует синтаксису, который вы получили от XMLGregorianCalendar в вашем вопросе точно, только дата и время не были изменены. Опять же, если вы не можете избежать принятия старомодного Date, перерабатывать:

    OffsetDateTime odt = date.toInstant().atZone(zone).toOffsetDateTime();

Если вам нужен XMLGregorianCalendar

    ZoneId zone = ZoneId.of("Europe/Rome");
    ZonedDateTime zdt = date.toInstant().atZone(zone);
    GregorianCalendar cal = GregorianCalendar.from(zdt);
    XMLGregorianCalendar xmlgcal = DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
    System.out.println(xmlgcal);

2018-09-27T00: 00: 00,000+02:00

Спецификация часового пояса контролирует смещение и, следовательно, также дату и время производства.

связи

Это та же дата и время.

Ваша первая дата находится в часовом поясе CEST, что эквивалентно UTC+2. Ваша вторая временная метка отображается в часовом поясе Z, что эквивалентно UTC+0.

Таким образом, оба означают один и тот же момент времени, но просто отображают по-разному.

В GregorianCalendar есть метод для изменения часового пояса календарей. Если вы хотите выводить дату и время CEST, то я предлагаю вам изменить часовой пояс календаря на этот. См. GregorianCalendar.setTimeZone для справки по API.

Это также зависит от того, как вы извлекаете дату из этого календаря. Если вы просто планируете использовать .getTime() метод, который возвращает простой объект Java Date, затем вы можете отправить его через DateTimeFormatter, чтобы вывести дату в любом часовом поясе.

Если вы заботитесь только о фактической части даты "date" и не хотите адаптировать ее к различным часовым поясам, обратите внимание на LocalDate.

Другие вопросы по тегам