SLING-8558 - ValueMapDecorator should allow getting ZonedDateTime values
diff --git a/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java b/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
index 8062149..060647a 100644
--- a/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
+++ b/src/main/java/org/apache/sling/api/wrappers/impl/ObjectConverter.java
@@ -19,10 +19,13 @@
package org.apache.sling.api.wrappers.impl;
import java.time.Instant;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
-import java.util.GregorianCalendar;
+import java.util.TimeZone;
+import org.apache.jackrabbit.util.ISO8601;
import org.osgi.util.converter.ConversionException;
import org.osgi.util.converter.Converter;
import org.osgi.util.converter.Converters;
@@ -45,16 +48,19 @@
synchronized (ObjectConverter.class) {
if (converter == null) {
converter = Converters.newConverterBuilder()
- .rule(new TypeRule<String, GregorianCalendar>(String.class, GregorianCalendar.class,
+ .rule(new TypeRule<String, Calendar>(String.class, Calendar.class,
ObjectConverter::toCalendar))
- .rule(new TypeRule<Date, GregorianCalendar>(Date.class, GregorianCalendar.class,
+ .rule(new TypeRule<Date, Calendar>(Date.class, Calendar.class,
ObjectConverter::toCalendar))
.rule(new TypeRule<String, Date>(String.class, Date.class, ObjectConverter::toDate))
.rule(new TypeRule<Calendar, String>(Calendar.class, String.class,
ObjectConverter::toString))
.rule(new TypeRule<Date, String>(Date.class, String.class, ObjectConverter::toString))
- .rule(new TypeRule<GregorianCalendar, Date>(GregorianCalendar.class, Date.class,
+ .rule(new TypeRule<Calendar, Date>(Calendar.class, Date.class,
ObjectConverter::toDate))
+ .rule(new TypeRule<>(Calendar.class, ZonedDateTime.class, ObjectConverter::toZonedDateTime))
+ .rule(new TypeRule<ZonedDateTime, Calendar>(ZonedDateTime.class, Calendar.class, ObjectConverter::toCalendar))
+ .rule(new TypeRule<ZonedDateTime, String>(ZonedDateTime.class, String.class, ObjectConverter::toString))
.build();
}
}
@@ -62,6 +68,20 @@
return converter;
}
+ private static String toString(ZonedDateTime zonedDateTime) {
+ return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(zonedDateTime);
+ }
+
+ private static Calendar toCalendar(ZonedDateTime zonedDateTime) {
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getOffset()));
+ calendar.setTimeInMillis(zonedDateTime.toInstant().toEpochMilli());
+ return calendar;
+ }
+
+ private static ZonedDateTime toZonedDateTime(Calendar calendar) {
+ return ZonedDateTime.ofInstant(calendar.toInstant(), calendar.getTimeZone().toZoneId().normalized());
+ }
+
private static String toString(Calendar cal) {
return cal.toInstant().toString();
}
@@ -70,16 +90,15 @@
return cal.toInstant().toString();
}
- private static GregorianCalendar toCalendar(String date) {
- Calendar response = Calendar.getInstance();
- response.setTime(Date.from(Instant.parse(date)));
- return (GregorianCalendar) response;
+ private static Calendar toCalendar(String date) {
+ ZonedDateTime zonedDateTime = ZonedDateTime.parse(date, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ return toCalendar(zonedDateTime);
}
- private static GregorianCalendar toCalendar(Date date) {
+ private static Calendar toCalendar(Date date) {
Calendar response = Calendar.getInstance();
response.setTime(date);
- return (GregorianCalendar) response;
+ return response;
}
private static Date toDate(String date) {
diff --git a/src/test/java/org/apache/sling/api/wrappers/ValueMapDecoratorTest.java b/src/test/java/org/apache/sling/api/wrappers/ValueMapDecoratorTest.java
index c573849..185f497 100644
--- a/src/test/java/org/apache/sling/api/wrappers/ValueMapDecoratorTest.java
+++ b/src/test/java/org/apache/sling/api/wrappers/ValueMapDecoratorTest.java
@@ -18,14 +18,20 @@
*/
package org.apache.sling.api.wrappers;
+import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;
+import java.util.TimeZone;
import org.apache.sling.api.resource.ValueMap;
+import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
@@ -166,5 +172,28 @@
decorated.get("prop1", "defValue");
verify(original, times(1)).get("prop1", "defValue");
}
+
+ @Test
+ public void testGettingZonedDateTime() {
+ String dateAsIso8601 = "2019-07-04T14:05:37.123+02:00";
+ ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateAsIso8601, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
+ Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone(zonedDateTime.getOffset()));
+ calendar.setTimeInMillis(zonedDateTime.toInstant().toEpochMilli());
+
+ map.put("dateAsIso8601", dateAsIso8601);
+ map.put("dateAsCalendar", calendar);
+ map.put("dateAsZonedDateTime", zonedDateTime);
+
+ assertThat("Conversion from \"dateAsIso8601\" to ZonedDateTime",
+ valueMap.get("dateAsIso8601", ZonedDateTime.class), Matchers.is(zonedDateTime));
+ assertThat("Conversion from \"dateAsCalendar\" to ZonedDateTime",
+ valueMap.get("dateAsCalendar", ZonedDateTime.class), Matchers.is(zonedDateTime));
+ assertThat("Conversion from \"dateAsZonedDateTime\" to ZonedDateTime",
+ valueMap.get("dateAsZonedDateTime", ZonedDateTime.class), Matchers.is(zonedDateTime));
+ assertThat("Conversion from \"dateAsZonedDateTime\" to Calendar",
+ valueMap.get("dateAsZonedDateTime", Calendar.class), Matchers.is(calendar));
+ assertThat("Conversion from \"dateAsZonedDateTime\" to String",
+ valueMap.get("dateAsZonedDateTime", String.class), Matchers.is(dateAsIso8601));
+ }
}