javaspringspring-dataspring-data-elasticsearchopensearch

Spring Data OpenSearch Unable to Convert Value of @Timestamp to Java Instant


Hi I have field in my opensearch index of @timestamp which looks like this JSON in the document: “@timestamp”: “2024-06-03T20:31:06.40402165Z”,. I tried to retrive the value with the following field in my spring data opensearch document record:

@Field(name = "@timestamp" type = FieldType.Date) Instant atTimestamp,

but I am getting the following error:

2024-06-14 14:13:47 org.springframework.data.elasticsearch.core.convert.ConversionException: Unable to convert value '2024-06-03T20:30:17.058647704Z' to java.time.Instant for property 'atTimestamp'

To fix this I tried adding a pattern to field like this: pattern = "YYYY-MM-DDThh:mm:ss.sssssssssZ but his gives the following error: Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'auditLogRepository' defined in com.my.java.project defined in @EnableElasticsearchRepositories declared on OpenSearchConfig: Too many pattern letters: s

So I then tried to add a format with DateFormat:

format = {
   DateFormat.date_time_no_millis,
   DateFormat.strict_date_optional_time_nanos,
   DateFormat.date_optional_time,
   DateFormat.epoch_millis
 })

but this just gave the original error. Now I am just throwing patterns at the wall and hopping something sticks but nothing seem to work. Here is what I tried so far:

  @Field(
             name = "@timestamp",
             type = FieldType.Date,
             pattern = {
               "uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXX]",
               "uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXXZ]",
               "uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXXZD]",
               "uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXX]Z",
               "YYYY-MM-DD'T'HH:mm:ss.SSSSSSXXXZ",
               "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXXZ",
               "yyyy-MM-dd'T'HH:mm:ss.SSSXXX",
               "yyyy-MM-dd'T'HH:mm:ss.SSSXXXZ",
               "yyyy-MM-dd'T'HH:mm:ss.SSSXXXZD",
               "YYYY-MM-DD'T'hh:mm:ss,s'T'ZD",
               "YYYY-MM-DD['T'hh:mm:ss.SSSSSSXXXZ]",
               "YYYY-MM-DD['T'hh:mm:ss.SSSSSSXXXZD]",
               "YYYY-MM-DD['T'hh:mm:ss.SSSSSSXXX]Z",
               "YYYY-MM-DD['T'hh:mm:ss.SSSSSSXXX]ZD",
               "uuuu-MM-dd['T'HH:mm:ss.SSSSSSXXX]ZD"
             })
         Instant atTimestamp,

Does anyone know how I am supposed to properly convert this? Thanks for any help in advance


Solution

  • I think the format you want is uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSX.

    Here is a test which passes:

        @Test
        @DisplayName("should convert nanos")
        void shouldConvertNanos() {
            ElasticsearchDateConverter converter = ElasticsearchDateConverter.of("uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSX");
            LocalDateTime parsed = converter.parse("2024-06-03T20:30:17.058647704Z", LocalDateTime.class);
    
            assertThat(parsed).isEqualTo(LocalDateTime.of(2024, 6, 3, 20,30, 17, 58647704));
        }
    

    It would also work to truncate your dates at six decimal places: this test also passes:

        @Test
        @DisplayName("should convert millis")
        void shouldConvertMillis() {
            ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.strict_date_optional_time_nanos);
            LocalDateTime parsed = converter.parse("2024-06-03T20:30:17.058647Z", LocalDateTime.class);
    
            assertThat(parsed).isEqualTo(LocalDateTime.of(2024, 6, 3, 20,30, 17, 58647000));
        }