Java - Ошибка при сериализации / десериализации даты - PullRequest
0 голосов
/ 28 февраля 2019

У меня проблемы с выяснением, что это за формат даты: 2019-02-28T12:17:46.279+0000.Я пробовал разные форматы даты, чтобы получить этот результат, но ничего не получалось.Ближайший шаблон был: yyyy-MM-dd'T'HH:mm:ss.SSSZ Но с этим шаблоном вывод был таким: 2019-02-28T12:17:46.279-0000 (- через несколько секунд вместо +)

Я получаю это исключение:

Caused by: java.lang.IllegalArgumentException: 2019-02-28T12:17:46.279+0000
    at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl$Parser.skip(XMLGregorianCalendarImpl.java:2932)
    at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl$Parser.parse(XMLGregorianCalendarImpl.java:2898)
    at org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl.<init>(XMLGregorianCalendarImpl.java:478)
    at org.apache.xerces.jaxp.datatype.DatatypeFactoryImpl.newXMLGregorianCalendar(DatatypeFactoryImpl.java:230)
    at __redirected.__DatatypeFactory.newXMLGregorianCalendar(__DatatypeFactory.java:132)
    at javax.xml.bind.DatatypeConverterImpl.parseDate(DatatypeConverterImpl.java:519)
    at javax.xml.bind.DatatypeConverter.parseDate(DatatypeConverter.java:431)
    at eu.europa.ec.my.custom.package.model.mapper.XsdDateTimeConverter.unmarshal(XsdDateTimeConverter.java:23)

Мой XsdDateTimeConverter класс выглядит следующим образом:

public class XsdDateTimeConverter {

    public static Date unmarshal(String dateTime) {
        return DatatypeConverter.parseDate(dateTime).getTime();
    }

    public static String marshalDate(Date date) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return DatatypeConverter.printDate(calendar);
    }

    public static String marshalDateTime(Date dateTime) {
        final Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTime);
        return DatatypeConverter.printDateTime(calendar);
    }
}

И проанализированная дата в моей базе данных postgres выглядит следующим образом:

move_timestamp timestamp(6) with time zone

2019-02-28 12:17:46.279+00

В моем методе отдыха я использую ObjectMapper какэто.

MyCustomResponseDto responseDto = customService.getCustomResponseDto(query);
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
String strValue = mapper.writeValueAsString(responseDto);
return Response.ok(strValue).build();

Я думаю, что я действительно хотел, это то, что правильный шаблон для этой даты.Я могу зайти на эту страницу: http://www.sdfonlinetester.info/ и ввести мой шаблон (например, yyyy-MM-dd'T'HH:mm:ss.SSSZ), и он даст вам фактическую дату выхода для этого шаблона.Мне нужно наоборот.Я хочу ввести свою дату, и она даст мне правильный шаблон для нее.

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Спасите себя от неприятностей и сохраните эпоху в миллис.Разбирать и отображать даты только в пользовательском интерфейсе.Очень немногие случаи составления расписаний для людей требуют, чтобы компьютер знал часы, день, неделю, месяц, год ... Но сохранение мгновенного времени - это просто "долго".

0 голосов
/ 28 февраля 2019

tl; dr

OffsetDateTime.parse( 
    "2019-02-28T12:17:46.279+0000" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT )
)

java.time

Вы используете ужасный класс Calendar, который был вытеснен несколько лет назад классами java.time .

ISO 8601

Ваша входная строка имеет стандартный формат ISO 8601 , предназначенный для машиночитаемых текстовых представлений значений времени и даты.Это хорошая вещь.

Классы java.time по умолчанию используют форматы ISO 8601 при разборе / генерации строк.

OffsetDateTime

Вы должны можно просто анализировать с OffsetDateTime.

OffsetDateTime.parse( "2019-02-28T12:17:46.279+0000" )

… но, к сожалению, необязательный символ COLON, опускаемый из смещения (+00:00), является проблемой.Класс OffsetDateTime имеет небольшую ошибку, когда он отказывается анализировать без этого символа.Ошибка обсуждается здесь и здесь .

Стандарт ISO 8601 разрешает отсутствие двоеточия, но практически всегда следует включать его.OffsetDateTime класс не одинок;Я видел другие библиотеки, которые ломаются, когда отсутствуют двоеточия или дополняющие нули.Я предлагаю попросить издателя ваших данных использовать полный формат ISO 8601, включая двоеточие.

Обходной путь для ошибки OffsetDateTime заключается в явном определении DateTimeFormatter.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT ) ;

Затем выполните синтаксический анализ.

String input = "2019-02-28T12:17:46.279+0000" ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;

Чтобы сгенерировать текст в полном стандартном формате ISO 8601, просто позвоните toString.

String output = odt.toString() ;

См. Этот код, запущенный в режиме реального времени на IdeOne.com.

вывод: 2019-02-28T12: 17: 46.279Z

Z на конце означает UTC, то есть +0000 или+00:00.Произносится «Зулу».Очень часто используется, более читабельно, чем числовое смещение.

Если вы хотите использовать тот же формат вывода, что и для ввода, используйте тот же DateTimeFormatter.

String output = odt.format( f ) ;
0 голосов
/ 28 февраля 2019

Вы можете попробовать код ниже

SimpleDateFormat format = new SimpleDateFormat ("гггг-ММ-дд'ТХЧ: мм: сс.СССЗ", Locale.ENGLISH);Строка lastmod = format.format (new Date ());

...