Reputation: 383
I am trying to figure out why Jackson (2.9.5) formats dates from Java 8 incorrectly.
data class Test(
val zonedDateTim: ZonedDateTime = ZonedDateTime.now(),
val offsetDateTim: OffsetDateTime = OffsetDateTime.now(),
val date: Date = Date(),
val localDateTime: LocalDateTime = LocalDateTime.now()
)
val mapper = ObjectMapper().apply {
registerModule(KotlinModule())
registerModule(JavaTimeModule())
dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
enable(SerializationFeature.INDENT_OUTPUT)
}
println(mapper.writeValueAsString(Test()))
From the date format I provided I would expect to get dates formatted without milliseconds but instead the result looks like this:
{
"zonedDateTim" : "2018-07-27T13:18:26.452+02:00",
"offsetDateTim" : "2018-07-27T13:18:26.452+02:00",
"date" : "2018-07-27T13:18:26",
"localDateTime" : "2018-07-27T13:18:26.452"
}
Why are milliseconds being included in the formatted dates?
Upvotes: 5
Views: 5650
Reputation: 328608
dateFormat
only applies to Date
objects - the 3 other objects are handled by the JavaTimeModule
, which uses ISO formatting by default.
If you want a different format, you can use:
val format = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
val javaTimeModule = JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, LocalDateTimeSerializer(format));
javaTimeModule.addSerializer(ZonedDateTime.class, ZonedDateTimeSerializer(format));
mapper.registerModule(javaTimeModule);
You may also need to add mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
but I'm not 100% sure that it's necessary.
Also note that with that format, you will lose time zone and offset information. So you may want a different format for Offset/Zoned-DateTimes.
Upvotes: 10
Reputation: 338564
The Answer by assylias is correct. Here are some further thoughts.
If you really do not want the fractional second at all, truncate to whole seconds.
Instant instant = Instant.now().truncatedTo( ChronoUnit.SECONDS ) ;
OffsetDateTime odt = OffsetDateTime.now().truncatedTo( ChronoUnit.SECONDS ) ;
ZonedDateTime zdt = ZonedDateTime.now().truncatedTo( ChronoUnit.SECONDS ) ;
The formatters used by the various toString
methods by default omit any text representing the fractional second if the value is zero.
So the value of:
2018-07-27T13:18:26.452+02:00
…becomes:
2018-07-27T13:18:26.000+02:00
…and its String
representation will be generated as seconds without a fraction:
2018-07-27T13:18:26+02:00
Try it.
OffsetDateTime odt = OffsetDateTime.parse( "2018-07-27T13:18:26.452+02:00" ) ;
OffsetDateTime odtTrunc = odt.truncatedTo( ChronoUnit.SECONDS ) ;
System.out.println( "odt.toString(): " + odt ) ;
System.out.println( "odtTrunc.toString(): " + odtTrunc ) ;
Try that code live at IdeOne.com.
odt.toString(): 2018-07-27T13:18:26.452+02:00
odtTrunc.toString(): 2018-07-27T13:18:26+02:00
The code in your Question confuses me. Do not mix the troublesome old legacy date-time classes such as Date
& SimpleDateFormat
with the modern java.time classes. The legacy classes are entirely supplanted by the modern ones.
Be clear that LocalDateTime
serves a very different purpose than Instant
, OffsetDateTime
, and ZonedDateTime
. A LocalDateTime
object purposely lacks any concept of time zone or offset-from-UTC. So it cannot represent a moment, is not a point on the timeline.
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
Upvotes: 3