From 9bc4bee86fa5727102b94bdb912cce4d21ed5938 Mon Sep 17 00:00:00 2001 From: Peter-Josef Meisch Date: Thu, 15 Oct 2020 23:08:10 +0200 Subject: [PATCH] DATAES-953 - DateTimeException on converting Instant or Date to custom format. Original PR: #538 --- .../convert/ElasticsearchDateConverter.java | 9 +++-- .../ElasticsearchDateConverterTests.java | 33 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverter.java b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverter.java index 6f2a0630d..0a1b07682 100644 --- a/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverter.java +++ b/src/main/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverter.java @@ -18,11 +18,13 @@ package org.springframework.data.elasticsearch.core.convert; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.time.Instant; +import java.time.ZonedDateTime; import java.time.temporal.TemporalAccessor; import java.util.Date; import java.util.concurrent.ConcurrentHashMap; import org.elasticsearch.common.time.DateFormatter; +import org.elasticsearch.common.time.DateFormatters; import org.springframework.data.elasticsearch.annotations.DateFormat; import org.springframework.util.Assert; @@ -103,10 +105,10 @@ final public class ElasticsearchDateConverter { * @return the new created object */ public T parse(String input, Class type) { - TemporalAccessor accessor = dateFormatter.parse(input); + ZonedDateTime zonedDateTime = DateFormatters.from(dateFormatter.parse(input)); try { Method method = type.getMethod("from", TemporalAccessor.class); - Object o = method.invoke(null, accessor); + Object o = method.invoke(null, zonedDateTime); return type.cast(o); } catch (NoSuchMethodException e) { throw new ConversionException("no 'from' factory method found in class " + type.getName()); @@ -122,6 +124,7 @@ final public class ElasticsearchDateConverter { * @return the new created object */ public Date parse(String input) { - return new Date(Instant.from(dateFormatter.parse(input)).toEpochMilli()); + ZonedDateTime zonedDateTime = DateFormatters.from(dateFormatter.parse(input)); + return new Date(Instant.from(zonedDateTime).toEpochMilli()); } } diff --git a/src/test/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverterTests.java b/src/test/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverterTests.java index b2e991395..95ce82c08 100644 --- a/src/test/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverterTests.java +++ b/src/test/java/org/springframework/data/elasticsearch/core/convert/ElasticsearchDateConverterTests.java @@ -10,6 +10,7 @@ import java.time.ZonedDateTime; import java.util.Date; import java.util.GregorianCalendar; +import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.EnumSource; @@ -98,4 +99,36 @@ class ElasticsearchDateConverterTests { assertThat(formatted).isEqualTo("1234568901234"); } + + @Test // DATAES-953 + @DisplayName("should write and read Date with custom format") + void shouldWriteAndReadDateWithCustomFormat() { + + // only seconds as the format string does not store millis + long currentTimeSeconds = System.currentTimeMillis() / 1_000; + Date date = new Date(currentTimeSeconds * 1_000); + + ElasticsearchDateConverter converter = ElasticsearchDateConverter.of("uuuu-MM-dd HH:mm:ss"); + + String formatted = converter.format(date); + Date parsed = converter.parse(formatted); + + assertThat(parsed).isEqualTo(date); + } + + @Test // DATAES-953 + @DisplayName("should write and read Instant with custom format") + void shouldWriteAndReadInstantWithCustomFormat() { + + // only seconds as the format string does not store millis + long currentTimeSeconds = System.currentTimeMillis() / 1_000; + Instant instant = Instant.ofEpochSecond(currentTimeSeconds); + + ElasticsearchDateConverter converter = ElasticsearchDateConverter.of("uuuu-MM-dd HH:mm:ss"); + + String formatted = converter.format(instant); + Instant parsed = converter.parse(formatted, Instant.class); + + assertThat(parsed).isEqualTo(instant); + } }