从日期格式中排除毫秒(杰克逊+ Java 8日期)

时间:2018-07-27 11:27:40

标签: java date kotlin jackson objectmapper

我试图弄清楚为什么杰克逊(2.9.5)格式错误地来自Java 8。

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()))

从我提供的日期格式中,我希望得到的日期格式不带毫秒,但结果看起来像这样:

{
  "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"
}

我们非常感谢您的帮助。

最好, 丹尼尔

2 个答案:

答案 0 :(得分:4)

dateFormat仅适用于Date对象-其他3个对象由JavaTimeModule处理,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); 默认使用ISO格式。

如果要使用其他格式,可以使用:

mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

您可能还需要添加filterContext.RequestContext.HttpContext.Request.IsAuthenticated ,但我不确定100%是否有必要。

还请注意,使用该格式,您将丢失时区和偏移信息。因此,您可能需要Offset / Zoned-DateTimes的其他格式。

答案 1 :(得分:1)

Answer by assylias是正确的。这是一些进一步的想法。

截断

如果您真的根本不想得到小数秒,请截短至整秒。

Instant instant = Instant.now().truncatedTo( ChronoUnit.SECONDS ) ;
OffsetDateTime odt = OffsetDateTime.now().truncatedTo( ChronoUnit.SECONDS ) ;
ZonedDateTime zdt = ZonedDateTime.now().truncatedTo( ChronoUnit.SECONDS ) ;

默认情况下,各种toString方法使用的格式化程序会省略任何表示小数秒的文本(如果该值为零)。

因此,值:

  

2018-07-27T13:18:26.452 + 02:00

…成为:

  

2018-07-27T13:18:26.000 + 02:00

…及其String表示形式将以秒的形式生成,且不带分数:

  

2018-07-27T13:18:26 + 02:00

尝试一下。

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 ) ;

尝试code live at IdeOne.com

  

odt.toString():2018-07-27T13:18:26.452 + 02:00

     

odtTrunc.toString():2018-07-27T13:18:26 + 02:00

避免使用旧类

您问题中的代码使我感到困惑。请勿将麻烦的旧式旧日期时间类(例如DateSimpleDateFormat)与现代的 java.time 类混合使用。传统类完全被现代类所取代。

时间轴

请注意,LocalDateTime的用途与InstantOffsetDateTimeZonedDateTime截然不同。 LocalDateTime对象故意缺少任何时区或从UTC偏移的概念。因此它不能表示一个时刻,不是时间线上的一个点。


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore