I'm having trouble to figure out what is this date format: 2019-02-28T12:17:46.279+0000
. I have tried different date formats to get this result but nothing worked. Closest pattern was: yyyy-MM-dd'T'HH:mm:ss.SSSZ
But with this pattern output was like this: 2019-02-28T12:17:46.279-0000
(-
is after seconds instead of +
)
I get this exception:
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)
My XsdDateTimeConverter
class looks like this:
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);
}
}
And parsed date in my postgres db looks like this:
move_timestamp timestamp(6) with time zone
2019-02-28 12:17:46.279+00
In my rest method I use ObjectMapper
like this.
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();
I guess what I really wanted is what is the right pattern for this date. I can go in this page: http://www.sdfonlinetester.info/ and enter my pattern (e.g. yyyy-MM-dd'T'HH:mm:ss.SSSZ
) and it gives you an actual date output for that pattern. I need the other way around. I want to enter my date and it will give me the right pattern for it.
OffsetDateTime.parse(
"2019-02-28T12:17:46.279+0000" ,
DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT )
)
You are using terrible Calendar
class that was supplanted years ago by the java.time classes.
Your input string is in standard ISO 8601 format, designed for human-readable machine-parseable textual representations of date-time values. That is a good thing.
The java.time classes use ISO 8601 formats by default when parsing/generating strings.
OffsetDateTime
You should be able to simply parse with OffsetDateTime
.
OffsetDateTime.parse( "2019-02-28T12:17:46.279+0000" )
…but unfortunately the optional COLON character being omitted from the offset (+00:00
) is a problem. The OffsetDateTime
class has a minor bug where it refuses to parse without that character. The bug is discussed here and here.
The ISO 8601 standard permits the colon’s absence, but practically you should always include it. The OffsetDateTime
class is not alone; I have seen other libraries that break when the colon or padding zeros are absent. I suggest asking the publisher of your data to use the full ISO 8601 format including the colon.
The workaround for the OffsetDateTime
bug is to define a DateTimeFormatter
explicitly.
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ss.SSSX" , Locale.ROOT ) ;
Then parse.
String input = "2019-02-28T12:17:46.279+0000" ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
To generate text in full standard ISO 8601 format, simply call toString
.
String output = odt.toString() ;
See this code run live at IdeOne.com.
output: 2019-02-28T12:17:46.279Z
The Z
on the end means UTC, that is +0000
or +00:00
. Pronounced “Zulu”. Very commonly used, more immediately readable than the numeric offset.
If you want same output format as your input, use the same DateTimeFormatter
.
String output = odt.format( f ) ;