You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2022/02/22 16:43:25 UTC
[cxf] branch 3.5.x-fixes updated: CXF-8659: Can't filter when attribute type is LocalDate or LocalDateTime (#911)
This is an automated email from the ASF dual-hosted git repository.
reta pushed a commit to branch 3.5.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/3.5.x-fixes by this push:
new 9f413c0 CXF-8659: Can't filter when attribute type is LocalDate or LocalDateTime (#911)
9f413c0 is described below
commit 9f413c0ef37c798b9cf69a899e63d5cae0788573
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Tue Feb 22 10:09:42 2022 -0500
CXF-8659: Can't filter when attribute type is LocalDate or LocalDateTime (#911)
(cherry picked from commit e0df5b52626680967c05a65ac3a8305270e99891)
---
.../ext/search/AbstractSearchConditionParser.java | 77 +++++-
.../apache/cxf/jaxrs/ext/search/SearchUtils.java | 14 +-
.../cxf/jaxrs/ext/search/fiql/FiqlParserTest.java | 262 +++++++++++++++++++++
3 files changed, 350 insertions(+), 3 deletions(-)
diff --git a/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionParser.java b/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionParser.java
index d69a24d..08c4aba 100644
--- a/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionParser.java
+++ b/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/AbstractSearchConditionParser.java
@@ -25,11 +25,22 @@ import java.sql.Time;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.time.temporal.Temporal;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
import java.util.Set;
+import java.util.function.BiFunction;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
@@ -111,6 +122,7 @@ public abstract class AbstractSearchConditionParser<T> implements SearchConditio
return setter;
}
+ @SuppressWarnings("unchecked")
protected Object parseType(String originalPropName,
Object ownerBean,
Object lastCastedValue,
@@ -126,6 +138,8 @@ public abstract class AbstractSearchConditionParser<T> implements SearchConditio
Object castedValue = value;
if (Date.class.isAssignableFrom(valueType)) {
castedValue = convertToDate(valueType, value);
+ } else if (Temporal.class.isAssignableFrom(valueType)) {
+ castedValue = convertToTemporal((Class<? extends Temporal>)valueType, value);
} else {
boolean isPrimitive = InjectionUtils.isPrimitive(valueType);
boolean isPrimitiveOrEnum = isPrimitive || valueType.isEnum();
@@ -309,6 +323,47 @@ public abstract class AbstractSearchConditionParser<T> implements SearchConditio
}
}
}
+
+ private Temporal convertToTemporal(Class<? extends Temporal> valueType, String value) throws SearchParseException {
+
+ Message m = JAXRSUtils.getCurrentMessage();
+ Temporal obj = InjectionUtils.createFromParameterHandler(value, valueType, valueType,
+ new Annotation[]{}, m);
+ if (obj != null) {
+ return obj;
+ }
+
+ try {
+ if (LocalTime.class.isAssignableFrom(valueType)) {
+ return LocalTime.parse(value);
+ } else if (LocalDate.class.isAssignableFrom(valueType)) {
+ return LocalDate.from(convertToDefaultDate(value).toInstant().atZone(ZoneId.systemDefault()));
+ } else if (LocalDateTime.class.isAssignableFrom(valueType)) {
+ return convertTo(value, SearchUtils.DEFAULT_DATETIME_FORMAT, Boolean.FALSE, LocalDateTime::parse);
+ } else if (OffsetTime.class.isAssignableFrom(valueType)) {
+ return OffsetTime.parse(value);
+ } else if (OffsetDateTime.class.isAssignableFrom(valueType)) {
+ return convertTo(value, SearchUtils.DEFAULT_OFFSET_DATETIME_FORMAT,
+ Boolean.TRUE, OffsetDateTime::parse);
+ } else if (ZonedDateTime.class.isAssignableFrom(valueType)) {
+ return convertTo(value, SearchUtils.DEFAULT_ZONE_DATETIME_FORMAT,
+ Boolean.TRUE, ZonedDateTime::parse);
+ } else {
+ return convertToDefaultDate(value).toInstant();
+ }
+ } catch (ParseException | DateTimeParseException e) {
+ // is that duration?
+ try {
+ Date now = new Date();
+ DatatypeFactory.newInstance().newDuration(value).addTo(now);
+ return LocalDateTime.from(now.toInstant().atZone(ZoneId.systemDefault()));
+ } catch (DatatypeConfigurationException e1) {
+ throw new SearchParseException(e1);
+ } catch (IllegalArgumentException e1) {
+ throw new SearchParseException("Can parse " + value + " neither as date nor duration", e);
+ }
+ }
+ }
private Timestamp convertToTimestamp(String value) throws ParseException {
Date date = convertToDefaultDate(value);
@@ -322,15 +377,33 @@ public abstract class AbstractSearchConditionParser<T> implements SearchConditio
private Date convertToDefaultDate(String value) throws ParseException {
DateFormat df = SearchUtils.getDateFormat(contextProperties);
+ String dateValue = normalizeTimeZone(value);
+ return df.parse(dateValue);
+ }
+
+ private <S extends Temporal> S convertTo(String value, String pattern, Boolean timezoneSupported,
+ BiFunction<String, DateTimeFormatter, S> parser) throws ParseException {
+ final DateTimeFormatter df = DateTimeFormatter.ofPattern(SearchUtils
+ .getDateFormatOrDefault(contextProperties, pattern)
+ .toPattern());
+ final String dateValue = normalizeTimeZone(value, timezoneSupported);
+ return parser.apply(dateValue, df);
+ }
+
+ private String normalizeTimeZone(String value) {
+ return normalizeTimeZone(value, Boolean.FALSE);
+ }
+
+ private String normalizeTimeZone(String value, Boolean timezoneSupported) {
String dateValue = value;
- if (SearchUtils.isTimeZoneSupported(contextProperties, Boolean.FALSE)) {
+ if (SearchUtils.isTimeZoneSupported(contextProperties, timezoneSupported)) {
// zone in XML is "+01:00" in Java is "+0100"; stripping semicolon
int idx = value.lastIndexOf(':');
if (idx != -1) {
dateValue = value.substring(0, idx) + value.substring(idx + 1);
}
}
- return df.parse(dateValue);
+ return dateValue;
}
private static String getMethodNameSuffix(String name) {
diff --git a/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java b/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
index ba73c57..2110ab1 100644
--- a/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
+++ b/rt/rs/extensions/search/src/main/java/org/apache/cxf/jaxrs/ext/search/SearchUtils.java
@@ -36,6 +36,9 @@ public final class SearchUtils {
public static final String TIMESTAMP_NO_TIMEZONE = "yyyy-MM-dd'T'HH:mm:ss";
public static final String TIMESTAMP_WITH_TIMEZONE_Z = "yyyy-MM-dd'T'HH:mm:ssZ";
public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
+ public static final String DEFAULT_DATETIME_FORMAT = TIMESTAMP_NO_TIMEZONE;
+ public static final String DEFAULT_OFFSET_DATETIME_FORMAT = TIMESTAMP_WITH_TIMEZONE_Z;
+ public static final String DEFAULT_ZONE_DATETIME_FORMAT = TIMESTAMP_WITH_TIMEZONE_Z + "'['z']'";
public static final String DATE_FORMAT_PROPERTY = "search.date-format";
public static final String TIMEZONE_SUPPORT_PROPERTY = "search.timezone.support";
public static final String LAX_PROPERTY_MATCH = "search.lax.property.match";
@@ -85,11 +88,20 @@ public final class SearchUtils {
return dateFromStringWithDefaultFormats(value);
}
+ public static SimpleDateFormat getDateFormatOrDefault(Map<String, String> properties, String pattern) {
+ return getDateFormatOrDefault(properties.get(DATE_FORMAT_PROPERTY), pattern);
+ }
+
public static SimpleDateFormat getDateFormat(Map<String, String> properties) {
return getDateFormat(properties.get(DATE_FORMAT_PROPERTY));
}
+
+ public static SimpleDateFormat getDateFormatOrDefault(String dfProperty, String pattern) {
+ return new SimpleDateFormat(dfProperty == null ? pattern : dfProperty);
+ }
+
public static SimpleDateFormat getDateFormat(String dfProperty) {
- return new SimpleDateFormat(dfProperty == null ? DEFAULT_DATE_FORMAT : dfProperty);
+ return getDateFormatOrDefault(dfProperty, DEFAULT_DATE_FORMAT);
}
public static boolean isTimeZoneSupported(Map<String, String> properties, Boolean defaultValue) {
diff --git a/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java b/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java
index c3b88ef..7778b48 100644
--- a/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java
+++ b/rt/rs/extensions/search/src/test/java/org/apache/cxf/jaxrs/ext/search/fiql/FiqlParserTest.java
@@ -21,6 +21,14 @@ package org.apache.cxf.jaxrs.ext.search.fiql;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
@@ -207,6 +215,151 @@ public class FiqlParserTest {
}
@Test
+ public void testParseLocalDateWithDefaultFormat() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("localDate=le=2010-03-11");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern(SearchUtils.DEFAULT_DATE_FORMAT);
+ assertTrue(filter.isMet(new Condition("whatever", 15, null, LocalDate.parse("2010-03-11", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null, LocalDate.parse("2010-03-10", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null, LocalDate.parse("2010-03-12", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null, LocalDate.parse("2010-03-12", df))));
+ }
+
+ @Test
+ public void testParseInstantWithDefaultFormat() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("instant=le=2010-03-11");
+ DateFormat df = new SimpleDateFormat(SearchUtils.DEFAULT_DATE_FORMAT);
+ assertTrue(filter.isMet(new Condition("whatever", 15, null, df.parse("2010-03-11").toInstant())));
+ assertTrue(filter.isMet(new Condition(null, null, null, df.parse("2010-03-10").toInstant())));
+ assertFalse(filter.isMet(new Condition("blah", null, null, df.parse("2010-03-12").toInstant())));
+ assertFalse(filter.isMet(new Condition(null, 123, null, df.parse("2010-03-12").toInstant())));
+ }
+
+ @Test
+ public void testParseInstantDuration() throws Exception {
+ SearchCondition<Condition> filter = parser.parse("localDateTime=gt=-PT1M");
+ LocalDateTime now = LocalDateTime.now();
+ LocalDateTime tenMinutesAgo = now.minusMinutes(10);
+ assertTrue(filter.isMet(new Condition(null, null, null, now)));
+ assertFalse(filter.isMet(new Condition(null, null, null, tenMinutesAgo)));
+ }
+
+ @Test
+ public void testParseLocalTime() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("localTime=le=03:11:22");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null, LocalTime.parse("03:11:22"))));
+ assertTrue(filter.isMet(new Condition(null, null, null, LocalTime.parse("03:11:21"))));
+ assertFalse(filter.isMet(new Condition("blah", null, null, LocalTime.parse("03:12:21"))));
+ assertFalse(filter.isMet(new Condition(null, 123, null, LocalTime.parse("03:12:21"))));
+ }
+
+ @Test
+ public void testParseOffsetTime() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("offsetTime=le=03:11:22+01:00");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null, OffsetTime.parse("03:11:22+01:00"))));
+ assertTrue(filter.isMet(new Condition(null, null, null, OffsetTime.parse("03:11:21+01:00"))));
+ assertFalse(filter.isMet(new Condition("blah", null, null, OffsetTime.parse("03:12:21+01:00"))));
+ assertFalse(filter.isMet(new Condition(null, 123, null, OffsetTime.parse("03:12:21+01:00"))));
+ }
+
+ @Test
+ public void testParseLocalDateTimeWithDefaultFormat() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("localDateTime=le=2010-03-11T18:00:00");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ LocalDateTime.parse("2010-03-11T18:00:00", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ LocalDateTime.parse("2010-03-10T22:22:00", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ LocalDateTime.parse("2010-03-12T00:00:00", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null,
+ LocalDateTime.parse("2010-03-12T00:00:00", df))));
+ }
+
+ @Test
+ public void testParseLocalDateTimeWithCustomFormat() throws SearchParseException, ParseException {
+ Map<String, String> props = new HashMap<>();
+ props.put(SearchUtils.DATE_FORMAT_PROPERTY, "yyyy-MM-dd'T'HH:mm:ss");
+ props.put(SearchUtils.TIMEZONE_SUPPORT_PROPERTY, "false");
+ parser = new FiqlParser<>(Condition.class, props);
+
+ SearchCondition<Condition> filter = parser.parse("localDateTime=le=2010-03-11T18:00:00");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ LocalDateTime.parse("2010-03-11T18:00:00", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ LocalDateTime.parse("2010-03-10T22:22:00", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ LocalDateTime.parse("2010-03-12T00:00:00", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null,
+ LocalDateTime.parse("2010-03-12T00:00:00", df))));
+ }
+
+ @Test
+ public void testParseOffsetDateTimeWithDefaultFormat() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("offsetDateTime=le=2010-03-11T18:00:00+01:00");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ OffsetDateTime.parse("2010-03-11T18:00:00+0100", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ OffsetDateTime.parse("2010-03-10T22:22:00+0100", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ OffsetDateTime.parse("2010-03-12T00:00:00+0100", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null,
+ OffsetDateTime.parse("2010-03-12T00:00:00+0100", df))));
+ }
+
+ @Test
+ public void testParseOffsetDateTimeWithCustomFormat() throws SearchParseException, ParseException {
+ Map<String, String> props = new HashMap<>();
+ props.put(SearchUtils.DATE_FORMAT_PROPERTY, "yyyy-MM-dd'T'HH:mm:ssZ");
+ props.put(SearchUtils.TIMEZONE_SUPPORT_PROPERTY, "true");
+ parser = new FiqlParser<>(Condition.class, props);
+
+ SearchCondition<Condition> filter = parser.parse("offsetDateTime=le=2010-03-11T18:00:00+01:00");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ OffsetDateTime.parse("2010-03-11T18:00:00+0100", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ OffsetDateTime.parse("2010-03-10T22:22:00+0100", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ OffsetDateTime.parse("2010-03-12T00:00:00+0100", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null, OffsetDateTime.parse("2010-03-12T00:00:00+0100", df))));
+ }
+
+ @Test
+ public void testParseZonedDateTimeWithCustomFormat() throws SearchParseException, ParseException {
+ Map<String, String> props = new HashMap<>();
+ props.put(SearchUtils.DATE_FORMAT_PROPERTY, "yyyy-MM-dd'T'HH:mm:ss '['z']'");
+ props.put(SearchUtils.TIMEZONE_SUPPORT_PROPERTY, "false");
+ parser = new FiqlParser<>(Condition.class, props);
+
+ SearchCondition<Condition> filter = parser.parse("zonedDateTime=le=2010-03-11T18:00:00 [Europe/Paris]");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss' ['z']'");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ ZonedDateTime.parse("2010-03-11T18:00:00 [Europe/Paris]", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ ZonedDateTime.parse("2010-03-10T22:22:00 [Europe/Paris]", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ ZonedDateTime.parse("2010-03-12T00:00:00 [Europe/Paris]", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null,
+ ZonedDateTime.parse("2010-03-12T00:00:00 [Europe/Paris]", df))));
+ }
+
+ @Test
+ public void testParseZonedDateTimeWithDefaultFormat() throws SearchParseException, ParseException {
+ SearchCondition<Condition> filter = parser.parse("zonedDateTime=le=2010-03-11T18:00:00+01:00[Europe/Paris]");
+ DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ'['z']'");
+ assertTrue(filter.isMet(new Condition("whatever", 15, null,
+ ZonedDateTime.parse("2010-03-11T18:00:00+0100[Europe/Paris]", df))));
+ assertTrue(filter.isMet(new Condition(null, null, null,
+ ZonedDateTime.parse("2010-03-10T22:22:00+0100[Europe/Paris]", df))));
+ assertFalse(filter.isMet(new Condition("blah", null, null,
+ ZonedDateTime.parse("2010-03-12T00:00:00+0100[Europe/Paris]", df))));
+ assertFalse(filter.isMet(new Condition(null, 123, null,
+ ZonedDateTime.parse("2010-03-12T00:00:00+0100[Europe/Paris]", df))));
+ }
+
+ @Test
public void testParseComplex1() throws SearchParseException {
SearchCondition<Condition> filter = parser.parse("name==ami*;level=gt=10");
assertEquals(ConditionType.AND, filter.getConditionType());
@@ -334,14 +487,68 @@ public class FiqlParserTest {
private String name2;
private Integer level;
private Date time;
+ private LocalDate localDate;
+ private LocalTime localTime;
+ private LocalDateTime localDateTime;
+ private OffsetTime offsetTime;
+ private OffsetDateTime offsetDateTime;
+ private ZonedDateTime zonedDateTime;
+ private Instant instant;
public Condition() {
}
public Condition(String name, Integer level, Date time) {
+ this(name, level, time, (LocalDate)null);
+ }
+
+ public Condition(String name, Integer level, Date time, ZonedDateTime zonedDateTime) {
this.name = name;
this.level = level;
this.time = time;
+ this.zonedDateTime = zonedDateTime;
+ }
+
+ public Condition(String name, Integer level, Date time, OffsetDateTime offsetDateTime) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.offsetDateTime = offsetDateTime;
+ }
+
+ public Condition(String name, Integer level, Date time, OffsetTime offsetTime) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.offsetTime = offsetTime;
+ }
+
+ public Condition(String name, Integer level, Date time, LocalDateTime localDateTime) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.localDateTime = localDateTime;
+ }
+
+ public Condition(String name, Integer level, Date time, LocalDate localDate) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.localDate = localDate;
+ }
+
+ public Condition(String name, Integer level, Date time, LocalTime localTime) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.localTime = localTime;
+ }
+
+ public Condition(String name, Integer level, Date time, Instant instant) {
+ this.name = name;
+ this.level = level;
+ this.time = time;
+ this.instant = instant;
}
public Condition(String name, Integer level, Date time, String name2) {
@@ -384,6 +591,61 @@ public class FiqlParserTest {
return name2;
}
+ public LocalDate getLocalDate() {
+ return localDate;
+ }
+
+ public void setLocalDate(LocalDate localDate) {
+ this.localDate = localDate;
+ }
+
+ public LocalTime getLocalTime() {
+ return localTime;
+ }
+
+ public void setLocalTime(LocalTime localTime) {
+ this.localTime = localTime;
+ }
+
+ public void setLocalDateTime(LocalDateTime localDateTime) {
+ this.localDateTime = localDateTime;
+ }
+
+ public LocalDateTime getLocalDateTime() {
+ return localDateTime;
+ }
+
+ public void setOffsetTime(OffsetTime offsetTime) {
+ this.offsetTime = offsetTime;
+ }
+
+ public OffsetTime getOffsetTime() {
+ return offsetTime;
+ }
+
+ public void setOffsetDateTime(OffsetDateTime offsetDateTime) {
+ this.offsetDateTime = offsetDateTime;
+ }
+
+ public OffsetDateTime getOffsetDateTime() {
+ return offsetDateTime;
+ }
+
+ public void setZonedDateTime(ZonedDateTime zonedDateTime) {
+ this.zonedDateTime = zonedDateTime;
+ }
+
+ public ZonedDateTime getZonedDateTime() {
+ return zonedDateTime;
+ }
+
+ public Instant getInstant() {
+ return instant;
+ }
+
+ public void setInstant(Instant instant) {
+ this.instant = instant;
+ }
}