From 196da883f6f5dea2411f0dd4b6ec9402371c5e97 Mon Sep 17 00:00:00 2001 From: codingconquerors <100064563+codingconquerors@users.noreply.github.com> Date: Mon, 20 Feb 2023 15:33:31 -0500 Subject: [PATCH] feature: adds OffsetDateTime converters for Hashes (#195) * OffsetDateTime converters for Hashes * Adding Test Cases - OffsetDateTime converters for Hashes --------- Co-authored-by: khushwinder --- .../BytesToOffsetDateTimeConverter.java | 22 ++++++++++++++++ .../OffsetDateTimeToBytesConverter.java | 26 +++++++++++++++++++ .../OffsetDateTimeToStringConverter.java | 20 ++++++++++++++ .../convert/RedisOMCustomConversions.java | 4 +++ .../hash/fixtures/KitchenSink.java | 4 +++ .../hash/serialization/SerializationTest.java | 19 +++++++++++--- 6 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 redis-om-spring/src/main/java/com/redis/om/spring/convert/BytesToOffsetDateTimeConverter.java create mode 100644 redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToBytesConverter.java create mode 100644 redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToStringConverter.java diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/convert/BytesToOffsetDateTimeConverter.java b/redis-om-spring/src/main/java/com/redis/om/spring/convert/BytesToOffsetDateTimeConverter.java new file mode 100644 index 00000000..82a6d3f8 --- /dev/null +++ b/redis-om-spring/src/main/java/com/redis/om/spring/convert/BytesToOffsetDateTimeConverter.java @@ -0,0 +1,22 @@ +package com.redis.om.spring.convert; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.ReadingConverter; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; + +@ReadingConverter +public class BytesToOffsetDateTimeConverter implements Converter { + + @Override + public OffsetDateTime convert(byte[] source) { + return OffsetDateTime.ofInstant(Instant.ofEpochMilli(Long.parseLong(toString(source))), ZoneId.systemDefault()); + } + String toString(byte[] source) { + return new String(source, StandardCharsets.UTF_8); + } + +} diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToBytesConverter.java b/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToBytesConverter.java new file mode 100644 index 00000000..47212718 --- /dev/null +++ b/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToBytesConverter.java @@ -0,0 +1,26 @@ +package com.redis.om.spring.convert; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.WritingConverter; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; + +@Component +@WritingConverter +public class OffsetDateTimeToBytesConverter implements Converter { + byte[] fromString(String source) { + return source.getBytes(StandardCharsets.UTF_8); + } + + @Override + public byte[] convert(OffsetDateTime source) { + Instant instant = source.atZoneSameInstant(ZoneId.systemDefault()).toInstant(); + long timeInMillis = instant.toEpochMilli(); + + return fromString(Long.toString(timeInMillis)); + } +} diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToStringConverter.java b/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToStringConverter.java new file mode 100644 index 00000000..5546fd4d --- /dev/null +++ b/redis-om-spring/src/main/java/com/redis/om/spring/convert/OffsetDateTimeToStringConverter.java @@ -0,0 +1,20 @@ +package com.redis.om.spring.convert; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.convert.WritingConverter; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.time.OffsetDateTime; +import java.time.ZoneId; + +@Component +@WritingConverter +public class OffsetDateTimeToStringConverter implements Converter { + @Override + public String convert(OffsetDateTime source) { + Instant instant = source.atZoneSameInstant(ZoneId.systemDefault()).toInstant(); + long unixTime = instant.getEpochSecond(); + return Long.toString(unixTime); + } +} diff --git a/redis-om-spring/src/main/java/com/redis/om/spring/convert/RedisOMCustomConversions.java b/redis-om-spring/src/main/java/com/redis/om/spring/convert/RedisOMCustomConversions.java index 33e24021..9308a523 100644 --- a/redis-om-spring/src/main/java/com/redis/om/spring/convert/RedisOMCustomConversions.java +++ b/redis-om-spring/src/main/java/com/redis/om/spring/convert/RedisOMCustomConversions.java @@ -20,6 +20,10 @@ public class RedisOMCustomConversions extends RedisCustomConversions { omConverters.add(new LocalDateToBytesConverter()); omConverters.add(new BytesToLocalDateConverter()); omConverters.add(new LocalDateToStringConverter()); + // OffsetDateTime + omConverters.add(new OffsetDateTimeToBytesConverter()); + omConverters.add(new BytesToOffsetDateTimeConverter()); + omConverters.add(new OffsetDateTimeToStringConverter()); // LocalDateTime omConverters.add(new LocalDateTimeToBytesConverter()); omConverters.add(new BytesToLocalDateTimeConverter()); diff --git a/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/fixtures/KitchenSink.java b/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/fixtures/KitchenSink.java index 1ba5dc2d..f377c57c 100644 --- a/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/fixtures/KitchenSink.java +++ b/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/fixtures/KitchenSink.java @@ -9,6 +9,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.OffsetDateTime; import java.util.Date; import java.util.List; import java.util.Set; @@ -33,6 +34,9 @@ public class KitchenSink { private LocalDateTime localDateTime; @NonNull @Indexed + private OffsetDateTime localOffsetDateTime; + @NonNull + @Indexed private Date date; @NonNull @Indexed diff --git a/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/serialization/SerializationTest.java b/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/serialization/SerializationTest.java index dd1cb144..acd648b9 100644 --- a/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/serialization/SerializationTest.java +++ b/redis-om-spring/src/test/java/com/redis/om/spring/annotations/hash/serialization/SerializationTest.java @@ -11,10 +11,7 @@ import org.springframework.data.geo.Point; import org.springframework.data.redis.core.StringRedisTemplate; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; +import java.time.*; import java.time.temporal.ChronoUnit; import java.util.*; @@ -35,6 +32,7 @@ private LocalDate localDate; private LocalDateTime localDateTime; + private OffsetDateTime localOffsetDateTime; private Date date; private Point point; private Ulid ulid; @@ -50,6 +48,7 @@ public void cleanUp() { localDate = LocalDate.now(); localDateTime = LocalDateTime.now(); + localOffsetDateTime = OffsetDateTime.now(); date = new Date(); point = new Point(-111.83592170193586,33.62826024782707); ulid = UlidCreator.getMonotonicUlid(); @@ -67,6 +66,7 @@ public void cleanUp() { ks = KitchenSink.builder() // .localDate(localDate) // .localDateTime(localDateTime) // + .localOffsetDateTime(localOffsetDateTime) // .date(date) // .point(point) // .ulid(ulid) // @@ -77,6 +77,7 @@ public void cleanUp() { ks1 = KitchenSink.builder() // .localDate(localDate) // .localDateTime(localDateTime) // + .localOffsetDateTime(localOffsetDateTime) // .date(date) // .point(point) // .ulid(ulid) // @@ -87,6 +88,7 @@ public void cleanUp() { ks2 = KitchenSink.builder() // .localDate(localDate) // .localDateTime(localDateTime) // + .localOffsetDateTime(localOffsetDateTime) // .date(date) // .point(point) // .ulid(ulid) // @@ -98,6 +100,7 @@ public void cleanUp() { ks3 = KitchenSink.builder() // .localDate(localDate) // .localDateTime(localDateTime) // + .localOffsetDateTime(localOffsetDateTime) // .date(date) // .point(point) // .ulid(ulid) // @@ -109,6 +112,7 @@ public void cleanUp() { ks4 = KitchenSink.builder() // .localDate(localDate) // .localDateTime(localDateTime) // + .localOffsetDateTime(localOffsetDateTime) // .date(date) // .point(point) // .ulid(ulid) // @@ -134,6 +138,11 @@ void testHashSerialization() { long localDateTimeInMillis = localDateTimeInstant.toEpochMilli(); long rawLocalDateTime = Long.parseLong(Objects.requireNonNull(template.opsForHash().get(key, "localDateTime")).toString()); + // OffsetDateTime + Instant localOffsetDateTimeInstant = localOffsetDateTime.atZoneSameInstant(ZoneId.systemDefault()).toInstant(); + long localOffsetDateTimeInMillis = localOffsetDateTimeInstant.toEpochMilli(); + long rawlocalOffsetDateTime = Long.parseLong(Objects.requireNonNull(template.opsForHash().get(key, "localOffsetDateTime")).toString()); + // Date long dateInMillis = date.getTime(); long rawDate = Long.parseLong(Objects.requireNonNull(template.opsForHash().get(key, "date")).toString()); @@ -150,6 +159,7 @@ void testHashSerialization() { assertThat(rawLocalDate).isEqualTo(localDateAsUnixTS); assertThat(rawLocalDateTime).isEqualTo(localDateTimeInMillis); + assertThat(rawlocalOffsetDateTime).isEqualTo(localOffsetDateTimeInMillis); assertThat(rawDate).isEqualTo(dateInMillis); assertThat(rawPoint).isEqualTo(redisGeo); assertThat(rawUlid).isEqualTo(ulid.toString()); @@ -168,6 +178,7 @@ void testHashDeserialization() { // NOTE: We lose nanosecond precision in order to store LocalDateTime as long in // order to allow for RediSearch range queries assertThat(fromDb.get().getLocalDateTime()).isEqualToIgnoringNanos(localDateTime); + assertThat(fromDb.get().getLocalOffsetDateTime()).isEqualToIgnoringNanos(localOffsetDateTime); assertThat(fromDb.get().getSetThings()).isEqualTo(setThings); assertThat(fromDb.get().getListThings()).isEqualTo(listThings); }