DATAES-792 - Add java.util.Date to the supported types for Field annotation date times.

Original PR: #432
This commit is contained in:
Peter-Josef Meisch 2020-04-19 22:58:02 +02:00 committed by GitHub
parent f6a37f4601
commit e49f140233
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 104 additions and 20 deletions

View File

@ -17,7 +17,9 @@ package org.springframework.data.elasticsearch.core.convert;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Instant;
import java.time.temporal.TemporalAccessor;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import org.elasticsearch.common.time.DateFormatter;
@ -73,9 +75,25 @@ final public class ElasticsearchDateConverter {
* @return the formatted object
*/
public String format(TemporalAccessor accessor) {
Assert.notNull(accessor, "accessor must not be null");
return dateFormatter.format(accessor);
}
/**
* Formats the given {@link TemporalAccessor} int a String
*
* @param date must not be {@literal null}
* @return the formatted object
*/
public String format(Date date) {
Assert.notNull(date, "accessor must not be null");
return dateFormatter.format(Instant.ofEpochMilli(date.getTime()));
}
/**
* Parses a String into an object
*
@ -96,4 +114,14 @@ final public class ElasticsearchDateConverter {
throw new ConversionException("could not create object of class " + type.getName(), e);
}
}
/**
* Parses a String into a Date.
*
* @param input the String to parse, must not be {@literal null}.
* @return the new created object
*/
public Date parse(String input) {
return new Date(Instant.from(dateFormatter.parse(input)).toEpochMilli());
}
}

View File

@ -17,6 +17,7 @@ package org.springframework.data.elasticsearch.core.mapping;
import java.time.temporal.TemporalAccessor;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.springframework.data.elasticsearch.annotations.DateFormat;
@ -95,11 +96,14 @@ public class SimpleElasticsearchPersistentProperty extends
/**
* Initializes an {@link ElasticsearchPersistentPropertyConverter} if this property is annotated as a Field with type
* {@link FieldType#Date}, has a {@link DateFormat} set and if the type of the property is one of the Java8 temporal
* classes.
* classes or java.util.Date.
*/
private void initDateConverter() {
Field field = findAnnotation(Field.class);
if (field != null && field.type() == FieldType.Date && TemporalAccessor.class.isAssignableFrom(getType())) {
boolean isTemporalAccessor = TemporalAccessor.class.isAssignableFrom(getType());
boolean isDate = Date.class.isAssignableFrom(getType());
if (field != null && field.type() == FieldType.Date && (isTemporalAccessor || isDate)) {
DateFormat dateFormat = field.format();
ElasticsearchDateConverter converter = null;
@ -119,13 +123,21 @@ public class SimpleElasticsearchPersistentProperty extends
propertyConverter = new ElasticsearchPersistentPropertyConverter() {
@Override
public String write(Object property) {
return dateConverter.format((TemporalAccessor) property);
if (isTemporalAccessor) {
return dateConverter.format((TemporalAccessor) property);
} else { // must be Date
return dateConverter.format((Date) property);
}
}
@SuppressWarnings("unchecked")
@Override
public Object read(String s) {
return dateConverter.parse(s, (Class<? extends TemporalAccessor>) getType());
if (isTemporalAccessor) {
return dateConverter.parse(s, (Class<? extends TemporalAccessor>) getType());
} else { // must be date
return dateConverter.parse(s);
}
}
};
}

View File

@ -3,6 +3,8 @@ package org.springframework.data.elasticsearch.core.convert;
import static org.assertj.core.api.Assertions.*;
import java.time.LocalDate;
import java.util.Date;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
@ -14,7 +16,7 @@ import org.springframework.data.elasticsearch.annotations.DateFormat;
*/
class ElasticsearchDateConverterTests {
@ParameterizedTest
@ParameterizedTest // DATAES-716
@EnumSource(DateFormat.class)
void shouldCreateConvertersForAllKnownFormats(DateFormat dateFormat) {
@ -28,8 +30,8 @@ class ElasticsearchDateConverterTests {
assertThat(converter).isNotNull();
}
@Test
void shouldConvertToString() {
@Test // DATAES-716
void shouldConvertTemporalAccessorToString() {
LocalDate localDate = LocalDate.of(2019, 12, 27);
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date);
@ -38,8 +40,8 @@ class ElasticsearchDateConverterTests {
assertThat(formatted).isEqualTo("20191227");
}
@Test
void shouldParseFromString() {
@Test // DATAES-716
void shouldParseTemporalAccessorFromString() {
LocalDate localDate = LocalDate.of(2019, 12, 27);
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date);
@ -47,4 +49,24 @@ class ElasticsearchDateConverterTests {
assertThat(parsed).isEqualTo(localDate);
}
@Test // DATAES-792
void shouldConvertLegacyDateToString() {
Date date = new GregorianCalendar(2020, 3, 19, 21, 44).getTime();
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date_time);
String formatted = converter.format(date);
assertThat(formatted).isEqualTo("20200419T194400.000Z");
}
@Test // DATAES-792
void shouldParseLegacyDateFromString() {
Date date = new GregorianCalendar(2020, 3, 19, 21, 44).getTime();
ElasticsearchDateConverter converter = ElasticsearchDateConverter.of(DateFormat.basic_date_time);
Date parsed = converter.parse("20200419T194400.000Z");
assertThat(parsed).isEqualTo(date);
}
}

View File

@ -20,6 +20,7 @@ import static org.assertj.core.api.Assertions.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.GregorianCalendar;
import org.junit.jupiter.api.Test;
import org.springframework.data.elasticsearch.annotations.DateFormat;
@ -69,25 +70,25 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
assertThat(persistentProperty.getFieldName()).isEqualTo("by-value");
}
@Test
// DATAES-716
@Test // DATAES-716, DATAES-792
void shouldSetPropertyConverters() {
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("date");
assertThat(persistentProperty.hasPropertyConverter()).isFalse();
persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate");
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate");
assertThat(persistentProperty.hasPropertyConverter()).isTrue();
assertThat(persistentProperty.getPropertyConverter()).isNotNull();
persistentProperty = persistentEntity.getRequiredPersistentProperty("localDateTime");
assertThat(persistentProperty.hasPropertyConverter()).isTrue();
assertThat(persistentProperty.getPropertyConverter()).isNotNull();
persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate");
assertThat(persistentProperty.hasPropertyConverter()).isTrue();
assertThat(persistentProperty.getPropertyConverter()).isNotNull();
}
@Test
// DATAES-716
@Test // DATAES-716
void shouldConvertFromLocalDate() {
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate");
@ -98,8 +99,7 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
assertThat(converted).isEqualTo("27.12.2019");
}
@Test
// DATAES-716
@Test // DATAES-716
void shouldConvertToLocalDate() {
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("localDate");
@ -110,6 +110,28 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
assertThat(converted).isEqualTo(LocalDate.of(2019, 12, 27));
}
@Test // DATAES_792
void shouldConvertFromLegacyDate() {
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate");
Date legacyDate = new GregorianCalendar(2020, 3, 19, 21, 44).getTime();
String converted = persistentProperty.getPropertyConverter().write(legacyDate);
assertThat(converted).isEqualTo("20200419T194400.000Z");
}
@Test // DATES-792
void shouldConvertToLegacyDate() {
SimpleElasticsearchPersistentEntity<?> persistentEntity = context.getRequiredPersistentEntity(DatesProperty.class);
ElasticsearchPersistentProperty persistentProperty = persistentEntity.getRequiredPersistentProperty("legacyDate");
Object converted = persistentProperty.getPropertyConverter().read("20200419T194400.000Z");
assertThat(converted).isInstanceOf(Date.class);
assertThat(converted).isEqualTo(new GregorianCalendar(2020, 3, 19, 21, 44).getTime());
}
static class InvalidScoreProperty {
@Nullable @Score String scoreProperty;
}
@ -123,8 +145,8 @@ public class SimpleElasticsearchPersistentPropertyUnitTests {
}
static class DatesProperty {
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date) Date date;
@Nullable @Field(type = FieldType.Date, format = DateFormat.custom, pattern = "dd.MM.uuuu") LocalDate localDate;
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) LocalDateTime localDateTime;
@Nullable @Field(type = FieldType.Date, format = DateFormat.basic_date_time) Date legacyDate;
}
}