What converters should be used for LastModifiedDate, as it throws UnsupportedTemporalTypeException error

Viewed 473
@Builder.Default
@LastModifiedDate
@Field(type = FieldType.Date, name = "mdt", format = DateFormat.basic_date_time)
private LocalDateTime modifiedDate = LocalDateTime.now();

21-06-08T19:10:25,367 TRACE [http-nio-5555-exec-1] c.p.m.e.GlobalExceptionHandler: Found generic exception
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
        at java.base/java.time.LocalDate.get0(LocalDate.java:709)
        at java.base/java.time.LocalDate.getLong(LocalDate.java:688)
        at java.base/java.time.LocalDateTime.getLong(LocalDateTime.java:721)
        at java.base/java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:308)
        at java.base/java.time.format.DateTimeFormatterBuilder$OffsetIdPrinterParser.format(DateTimeFormatterBuilder.java:3569)
        at java.base/java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2343)
        at java.base/java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1847)
        at java.base/java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1821)
        at org.springframework.data.elasticsearch.core.convert.ElasticsearchDateConverter$PatternDateFormatter.format(ElasticsearchDateConverter.java:261)
2 Answers

Not directly related to the answer: Is this the @LastModifiedDate annotation from the org.springframework.data.annotation package? And are you using Spring Data Elasticsearch Auditing (see the docs)? The you do not need to set the value of the field by yourself. If you do not use auditing you can remove the annotation.

To your question: The format DateFormat.basic_date_time is a date with time and time-zone. But a LocalDateTime does not have a time-zone. You have two alternatives:

  1. Use a Java datatype that supports the timezone, for an auditing field I would choose Instant.
  2. Use an Elasticsearch date format that does not expect a timezone, for example DateFormat.date_hour_minute_second_millis. You need to recreate your index with the mapping if you change that.

Personally I would choose the first.

Finally, I find the answer for this, As @p-j-meisch mentioned the LocalDateTime does not support zone, which it will cause a format issue.

I tried multiple solutions but I didn't find the root cause till I create a sample method to find out what happens in LocalDateTime and what is the right format to be used, as you see in below logs and code the right formatter when you are interesting to date with time, the best formatter either date_hour_minute_second_millis or date_hour_minute_second_fraction depends on you.

fun main(args: Array<String>) {
    DateFormat.values().map {
        try {
            val elasticsearchDateConverter = ElasticsearchDateConverter.of(it)
            val format = elasticsearchDateConverter.format(LocalDateTime.now())
            val parsedValue = elasticsearchDateConverter.parse(format, LocalDateTime::class.java)
            Pair(true, " $it  Working fine --> [formatter: $format ] [parser: $parsedValue]")
        } catch (e: Exception) {
            Pair(false, " $it Not-Supported [error = ${e.message}]")
        }
    }.filter { it.first }
     .forEach {
        println(it.second)
     }
}

the result of above code:

 date_hour  Working fine --> [formatter: 2021-06-13T22 ] [parser: 2021-06-13T22:00]
 date_hour_minute  Working fine --> [formatter: 2021-06-13T22:51 ] [parser: 2021-06-13T22:51]
 date_hour_minute_second  Working fine --> [formatter: 2021-06-13T22:51:47 ] [parser: 2021-06-13T22:51:47]
 date_hour_minute_second_fraction  Working fine --> [formatter: 2021-06-13T22:51:47.644 ] [parser: 2021-06-13T22:51:47.644]
 date_hour_minute_second_millis  Working fine --> [formatter: 2021-06-13T22:51:47.645 ] [parser: 2021-06-13T22:51:47.645]

Related