This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 605344850159ef0b1ae3aa4633f1f664cc8110f8
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Fri Dec 2 14:20:35 2022 +0100

    Replace `java.util.Date` (from Java 1) by `java.time.temporal.Temporal` 
(from Java 8)
    in two properties that were introduced by the ISO 19157 upgrade (JIRA issue 
SIS-394).
    This change should be done on all properties, but this commit starts with 
properties
    that did not existed before SIS 1.3 release for making the transition 
smother.
    
    https://github.com/opengeospatial/geoapi/issues/79
---
 .../apache/sis/internal/jaxb/gco/GO_DateTime.java  |   7 +-
 .../gco/{GO_DateTime.java => GO_Temporal.java}     |  61 +++++----
 .../internal/metadata/legacy/DateToTemporal.java   |  87 +++++++++++++
 .../internal/metadata/legacy/TemporalToDate.java   |  94 ++++++++++++++
 .../org/apache/sis/internal/xml/XmlUtilities.java  | 143 ++++++++++++++++++++-
 .../org/apache/sis/internal/xml/package-info.java  |   2 +-
 .../sis/metadata/iso/quality/AbstractElement.java  |  27 ++--
 .../sis/metadata/iso/quality/AbstractResult.java   |  28 ++--
 .../iso/quality/DefaultEvaluationMethod.java       |  78 +++++------
 .../sis/metadata/iso/quality/package-info.java     |   1 +
 .../apache/sis/internal/xml/XmlUtilitiesTest.java  |  67 +++++++++-
 .../metadata/iso/quality/AbstractElementTest.java  |  96 +++-----------
 ...tTest.java => DefaultEvaluationMethodTest.java} |  24 ++--
 .../apache/sis/test/suite/MetadataTestSuite.java   |   1 +
 14 files changed, 526 insertions(+), 190 deletions(-)

diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
index b31340c401..af53fa8b7c 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
@@ -56,8 +56,11 @@ import org.apache.sis.internal.xml.XmlUtilities;
  *
  * @since 0.3
  * @module
+ *
+ * @todo This adapter may be deleted in favor of {@link GO_Temporal} after all 
usages
+ *       of {@link Date} have been replaced by {@link 
java.time.temporal.Temporal}.
  */
-@XmlType(name = "Date_PropertyType")
+@XmlType(name = "DateTime_PropertyType")
 public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> {
     /**
      * The date and time value using the {@code code "DateTime"} name.
@@ -111,7 +114,7 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, 
Date> {
      * Returns the current date, or {@code null} if none. If both fields are 
defined,
      * then {@link #dateTime} has precedence since it is assumed more accurate.
      */
-    final Date getDate() {
+    private Date getDate() {
         return XmlUtilities.toDate(Context.current(), dateTime != null ? 
dateTime : date);
     }
 
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java
similarity index 76%
copy from 
core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
copy to 
core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java
index b31340c401..bf50053b6c 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_DateTime.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/jaxb/gco/GO_Temporal.java
@@ -16,7 +16,8 @@
  */
 package org.apache.sis.internal.jaxb.gco;
 
-import java.util.Date;
+import java.time.temporal.Temporal;
+import java.time.temporal.ChronoField;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlSchemaType;
@@ -32,8 +33,8 @@ import org.apache.sis.internal.xml.XmlUtilities;
 /**
  * JAXB adapter wrapping the date value in a {@code <gco:Date>} or {@code 
<gco:DateTime>} element,
  * for ISO 19115-3 compliance. Only one of {@code Date} or {@code DateTime} 
field shall be non-null.
- * At marshalling time, the choice is performed depending on whatever the 
given date contains
- * hour, minute or seconds information different than zero.
+ * At marshalling time, the choice is performed depending on whatever the 
given date contains hour,
+ * minute or seconds fields.
  *
  * <h2>Difference between ISO 19139:2007 and ISO 19115-3:2016</h2>
  * The ISO {@code baseTypes.xsd} files define two kinds of date property:
@@ -54,11 +55,11 @@ import org.apache.sis.internal.xml.XmlUtilities;
  * @see org.apache.sis.internal.jaxb.gml.DateAdapter
  * @see org.apache.sis.internal.jaxb.gml.UniversalTimeAdapter
  *
- * @since 0.3
+ * @since 1.3
  * @module
  */
 @XmlType(name = "Date_PropertyType")
-public class GO_DateTime extends XmlAdapter<GO_DateTime, Date> {
+public class GO_Temporal extends XmlAdapter<GO_Temporal, Temporal> {
     /**
      * The date and time value using the {@code code "DateTime"} name.
      * Only one of {@code date} and {@link #dateTime} shall be non-null.
@@ -78,30 +79,28 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, 
Date> {
     /**
      * Empty constructor for JAXB.
      */
-    public GO_DateTime() {
+    public GO_Temporal() {
     }
 
     /**
-     * Builds a wrapper for the given {@link Date}.
+     * Builds a wrapper for the given temporal object.
      *
-     * @param date  the date to marshal. Cannot be {@code null}.
+     * @param time  the date and time to marshal. Cannot be {@code null}.
      */
-    private GO_DateTime(final Date date) {
+    private GO_Temporal(final Temporal time) {
         final Context context = Context.current();
         try {
-            final XMLGregorianCalendar gc = XmlUtilities.toXML(context, date);
+            final XMLGregorianCalendar gc = XmlUtilities.toXML(context, time);
+            if (gc.getMillisecond() == 0) {
+                gc.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
+            }
             if (Context.isFlagSet(context, Context.LEGACY_METADATA)) {
-                if (XmlUtilities.trimTime(gc, false)) {
-                    this.date = gc;
-                } else {
-                    dateTime = gc;
-                }
-            } else {
-                if (gc.getMillisecond() == 0) {
-                    gc.setMillisecond(DatatypeConstants.FIELD_UNDEFINED);
+                if (!time.isSupported(ChronoField.HOUR_OF_DAY)) {
+                    date = gc;
+                    return;
                 }
-                dateTime = gc;
             }
+            dateTime = gc;
         } catch (DatatypeConfigurationException e) {
             Context.warningOccured(context, XmlAdapter.class, "marshal", e, 
true);
         }
@@ -111,40 +110,40 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, 
Date> {
      * Returns the current date, or {@code null} if none. If both fields are 
defined,
      * then {@link #dateTime} has precedence since it is assumed more accurate.
      */
-    final Date getDate() {
-        return XmlUtilities.toDate(Context.current(), dateTime != null ? 
dateTime : date);
+    private Temporal getDate() {
+        return XmlUtilities.toTemporal(Context.current(), dateTime != null ? 
dateTime : date);
     }
 
     /**
-     * Converts a date read from a XML stream to the object which will contain
-     * the value. JAXB calls automatically this method at unmarshalling time.
+     * Converts a date read from a XML stream to the object which will contain 
the value.
+     * JAXB calls automatically this method at unmarshalling time.
      *
      * @param  value  the adapter for this metadata value.
-     * @return a {@linkplain Date date} which represents the metadata value.
+     * @return a temporal object which represents the metadata value.
      */
     @Override
-    public final Date unmarshal(final GO_DateTime value) {
+    public final Temporal unmarshal(final GO_Temporal value) {
         return (value != null) ? value.getDate() : null;
     }
 
     /**
-     * Converts the {@linkplain Date date} to the object to be marshalled in a 
XML
-     * file or stream. JAXB calls automatically this method at marshalling 
time.
+     * Converts the temporal object to the object to be marshalled in a XML 
file or stream.
+     * JAXB calls automatically this method at marshalling time.
      * The use of {@code <gco:Date>} or {@code <gco:DateTime>} is determined 
automatically.
      *
      * @param  value  the date value.
      * @return the adapter for this date.
      */
     @Override
-    public GO_DateTime marshal(final Date value) {
-        return (value != null) ? new GO_DateTime(value) : null;
+    public GO_Temporal marshal(final Temporal value) {
+        return (value != null) ? new GO_Temporal(value) : null;
     }
 
     /**
      * Wraps the value only if marshalling ISO 19115-3 element.
      * Otherwise (i.e. if marshalling a legacy ISO 19139:2007 document), omit 
the element.
      */
-    public static final class Since2014 extends GO_DateTime {
+    public static final class Since2014 extends GO_Temporal {
         /** Empty constructor used only by JAXB. */
         public Since2014() {
         }
@@ -154,7 +153,7 @@ public class GO_DateTime extends XmlAdapter<GO_DateTime, 
Date> {
          *
          * @return a non-null value only if marshalling ISO 19115-3 or newer.
          */
-        @Override public GO_DateTime marshal(final Date value) {
+        @Override public GO_Temporal marshal(final Temporal value) {
             return FilterByVersion.CURRENT_METADATA.accept() ? 
super.marshal(value) : null;
         }
     }
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java
new file mode 100644
index 0000000000..5fe78a10e6
--- /dev/null
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/DateToTemporal.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.metadata.legacy;
+
+import java.time.temporal.Temporal;
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+
+
+/**
+ * A collection where conversion from {@link Date} to {@link Temporal} objects 
are performed on-the-fly.
+ * This is used for handling legacy metadata, before the move to {@link 
java.time}.
+ * This adapter may be deleted after deprecated metadata methods have been 
removed from Apache SIS.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+public final class DateToTemporal extends AbstractCollection<Temporal> {
+    /**
+     * The collection of dates.
+     */
+    private final Collection<? extends Date> source;
+
+    /**
+     * Creates a new view over the given collection.
+     *
+     * @param source the collection of dates to wrap.
+     */
+    public DateToTemporal(final Collection<? extends Date> source) {
+        this.source = source;
+    }
+
+    /**
+     * Returns the number of dates in this collection.
+     *
+     * @return number of dates.
+     */
+    @Override
+    public int size() {
+        return source.size();
+    }
+
+    /**
+     * Returns an iterator over the dates in this collection.
+     *
+     * @return an iterator over the dates.
+     */
+    @Override
+    public Iterator<Temporal> iterator() {
+        final Iterator<? extends Date> dates = source.iterator();
+        return new Iterator<Temporal>() {
+            /** Tests whether there is more dates to return. */
+            @Override public boolean hasNext() {
+                return dates.hasNext();
+            }
+
+            /** Returns the next date, converted to a temporal object. */
+            @Override public Temporal next() {
+                final Date t = dates.next();
+                return (t != null) ? t.toInstant() : null;
+            }
+
+            /** Remove the last date returned by the iterator. */
+            @Override public void remove() {
+                dates.remove();
+            }
+        };
+    }
+}
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java
new file mode 100644
index 0000000000..02e1fad93c
--- /dev/null
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/metadata/legacy/TemporalToDate.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.internal.metadata.legacy;
+
+import java.time.Instant;
+import java.time.temporal.ChronoField;
+import java.time.temporal.Temporal;
+import java.util.AbstractCollection;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+
+
+/**
+ * A collection where conversion from {@link Temporal} to {@link Date} objects 
are performed on-the-fly.
+ * This is used for handling legacy metadata, before the move to {@link 
java.time}.
+ * This adapter may be deleted after deprecated metadata methods have been 
removed from Apache SIS.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 1.3
+ * @since   1.3
+ * @module
+ */
+public final class TemporalToDate extends AbstractCollection<Date> {
+    /**
+     * The collection of dates.
+     */
+    private final Collection<? extends Temporal> source;
+
+    /**
+     * Creates a new view over the given collection.
+     *
+     * @param source the collection of dates to wrap.
+     */
+    public TemporalToDate(final Collection<? extends Temporal> source) {
+        this.source = source;
+    }
+
+    /**
+     * Returns the number of dates in this collection.
+     *
+     * @return number of dates.
+     */
+    @Override
+    public int size() {
+        return source.size();
+    }
+
+    /**
+     * Returns an iterator over the dates in this collection.
+     *
+     * @return an iterator over the dates.
+     */
+    @Override
+    public Iterator<Date> iterator() {
+        final Iterator<? extends Temporal> dates = source.iterator();
+        return new Iterator<Date>() {
+            /** Tests whether there is more dates to return. */
+            @Override public boolean hasNext() {
+                return dates.hasNext();
+            }
+
+            /** Returns the next temporal object, converted to a date. */
+            @Override public Date next() {
+                final Temporal t = dates.next();
+                if (t == null) return null;
+                if (t instanceof Instant) {
+                    return Date.from((Instant) t);
+                }
+                // Following may throw `DateTimeException` if the temporal 
does not support the field.
+                return new 
Date(Math.multiplyExact(t.getLong(ChronoField.INSTANT_SECONDS), 1000));
+            }
+
+            /** Remove the last date returned by the iterator. */
+            @Override public void remove() {
+                dates.remove();
+            }
+        };
+    }
+}
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java
index 4ce01ccc94..76be5ca57f 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/XmlUtilities.java
@@ -16,10 +16,25 @@
  */
 package org.apache.sis.internal.xml;
 
+import java.math.BigDecimal;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.OffsetTime;
+import java.time.YearMonth;
+import java.time.Year;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.temporal.Temporal;
+import java.time.temporal.ChronoField;
 import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 import java.util.GregorianCalendar;
+import java.util.function.ObjIntConsumer;
 import javax.xml.datatype.XMLGregorianCalendar;
 import javax.xml.datatype.DatatypeFactory;
 import javax.xml.datatype.DatatypeConfigurationException;
@@ -34,7 +49,7 @@ import static 
javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED;
  * Utilities methods related to XML.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 1.3
  * @since   0.3
  * @module
  */
@@ -131,9 +146,78 @@ public final class XmlUtilities extends SystemListener {
         return false;
     }
 
+    /**
+     * Temporal fields that may be copied into {@link XMLGregorianCalendar}.
+     */
+    private static final ChronoField[] FIELDS = {
+        /*[0]*/ ChronoField.YEAR,
+        /*[1]*/ ChronoField.MONTH_OF_YEAR,
+        /*[2]*/ ChronoField.DAY_OF_MONTH,
+        /*[3]*/ ChronoField.HOUR_OF_DAY,
+        /*[4]*/ ChronoField.MINUTE_OF_HOUR,
+        /*[5]*/ ChronoField.SECOND_OF_MINUTE,
+        /*[6]*/ ChronoField.MILLI_OF_SECOND,
+        /*[7]*/ ChronoField.OFFSET_SECONDS
+    };
+
+    /**
+     * Setter methods to invoke for setting the value of a temporal field on a 
{@link XMLGregorianCalendar}.
+     * Indices in this array must correspond to indices in the {@link #FIELDS} 
array.
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})        // Generic array 
creation.
+    private static final ObjIntConsumer<XMLGregorianCalendar>[] SETTERS = new 
ObjIntConsumer[FIELDS.length];
+    static {
+        SETTERS[0] = XMLGregorianCalendar::setYear;
+        SETTERS[1] = XMLGregorianCalendar::setMonth;
+        SETTERS[2] = XMLGregorianCalendar::setDay;
+        SETTERS[3] = XMLGregorianCalendar::setHour;
+        SETTERS[4] = XMLGregorianCalendar::setMinute;
+        SETTERS[5] = XMLGregorianCalendar::setSecond;
+        SETTERS[6] = XMLGregorianCalendar::setMillisecond;
+        SETTERS[7] = (calendar, seconds) -> calendar.setTimezone(seconds / 
60);     // Convert seconds to minutes.
+    }
+
+    /**
+     * Converts the given temporal object to a XML Gregorian calendar.
+     * The returned calendar may have undefined fields (including undefined 
time zone)
+     * if the corresponding information was not provided in the given temporal 
object.
+     *
+     * <p>If the returned date has a time, then it usually has millisecond 
accuracy.
+     * Caller may want to clear the millisecond field if it is equal to 
zero.</p>
+     *
+     * @param  context  the current (un)marshalling context, or {@code null} 
if none.
+     * @param  date     the date to convert to a XML calendar, or {@code null}.
+     * @return the XML calendar, or {@code null} if {@code date} was null.
+     * @throws DatatypeConfigurationException if the factory cannot be created.
+     */
+    public static XMLGregorianCalendar toXML(final Context context, final 
Temporal date) throws DatatypeConfigurationException {
+        if (date == null) {
+            return null;
+        }
+        final XMLGregorianCalendar xml = 
getDatatypeFactory().newXMLGregorianCalendar();
+        if (date instanceof Instant) {
+            final TimeZone zone = (context != null) ? context.getTimeZone() : 
null;
+            final ZoneId zid = (zone != null) ? zone.toZoneId() : 
ZoneId.systemDefault();
+            final ZonedDateTime t = ZonedDateTime.ofInstant((Instant) date, 
zid);
+            for (int i=0; i<FIELDS.length; i++) {
+                SETTERS[i].accept(xml, t.get(FIELDS[i]));
+            }
+        } else {
+            for (int i=0; i<FIELDS.length; i++) {
+                final ChronoField field = FIELDS[i];
+                if (date.isSupported(field)) {
+                    SETTERS[i].accept(xml, date.get(field));
+                }
+            }
+        }
+        return xml;
+    }
+
     /**
      * Converts the given date to a XML Gregorian calendar using the locale 
and timezone
      * from the current {@linkplain Context marshalling context}.
+     * The returned date has millisecond accuracy.
+     * Caller may want to clear the millisecond field if it is equal to zero.
      *
      * @param  context  the current (un)marshalling context, or {@code null} 
if none.
      * @param  date     the date to convert to a XML calendar, or {@code null}.
@@ -175,6 +259,61 @@ public final class XmlUtilities extends SystemListener {
         return new GregorianCalendar();
     }
 
+    /**
+     * Replaces undefined value by zero. Used for optional time fields.
+     */
+    private static int zeroIfUndef(final int value) {
+        return (value != FIELD_UNDEFINED) ? value : 0;
+    }
+
+    /**
+     * Converts the given XML Gregorian calendar to a temporal object.
+     * The temporal object may be {@link LocalDate}, {@link LocalTime},
+     * {@link LocalDateTime}, {@link OffsetDateTime}, {@link Year} or {@link 
YearMonth}
+     * depending on which fields are defined in the given calendar.
+     *
+     * @param  context  the current (un)marshalling context, or {@code null} 
if none.
+     * @param  xml      the XML calendar to convert to a temporal object, or 
{@code null}.
+     * @return the temporal object, or {@code null} if {@code xml} is null or 
has too many undefined fields.
+     */
+    public static Temporal toTemporal(final Context context, final 
XMLGregorianCalendar xml) {
+        if (xml == null) {
+            return null;
+        }
+        final int year  = xml.getYear();
+        final int month = xml.getMonth();
+        final int day   = xml.getDay();
+        final int hour  = xml.getHour();
+        final int min   = zeroIfUndef(xml.getMinute());
+        final int sec   = zeroIfUndef(xml.getSecond());
+        final int nano;
+        final boolean hasYear =            (year  != FIELD_UNDEFINED);
+        final boolean hasYM   = hasYear && (month != FIELD_UNDEFINED);
+        final boolean hasDate = hasYM   && (day   != FIELD_UNDEFINED);
+        if (hour == FIELD_UNDEFINED) {
+            return hasDate ? LocalDate.of(year, month, day) :
+                   hasYM   ? YearMonth.of(year, month) :
+                   hasYear ? Year     .of(year) : null;
+        } else {
+            final BigDecimal f = xml.getFractionalSecond();
+            nano = (f != null) ? f.movePointRight(9).intValue() : 0;
+        }
+        final int offset = xml.getTimezone();
+        if (offset == FIELD_UNDEFINED) {
+            if (hasDate) {
+                return LocalDateTime.of(year, month, day, hour, min, sec, 
nano);
+            } else {
+                return LocalTime.of(hour, min, sec, nano);
+            }
+        }
+        final ZoneOffset zone = ZoneOffset.ofTotalSeconds(offset * 60);
+        if (hasDate) {
+            return OffsetDateTime.of(year, month, day, hour, min, sec, nano, 
zone);
+        } else {
+            return OffsetTime.of(hour, min, sec, nano, zone);
+        }
+    }
+
     /**
      * Converts the given XML Gregorian calendar to a date.
      *
@@ -184,7 +323,7 @@ public final class XmlUtilities extends SystemListener {
      */
     public static Date toDate(final Context context, final 
XMLGregorianCalendar xml) {
         if (xml != null) {
-            final GregorianCalendar calendar =  xml.toGregorianCalendar();
+            final GregorianCalendar calendar = xml.toGregorianCalendar();
             if (context != null && xml.getTimezone() == FIELD_UNDEFINED) {
                 final TimeZone timezone = context.getTimeZone();
                 if (timezone != null) {
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java
index 4017656bd7..fc62947465 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/internal/xml/package-info.java
@@ -30,7 +30,7 @@
  * @author  Cédric Briançon (Geomatys)
  * @author  Cullen Rombach (Image Matters)
  * @author  Martin Desruisseaux (Geomatys)
- * @version 1.1
+ * @version 1.3
  * @since   1.0
  * @module
  */
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
index db46e76277..8a04d3dbb7 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractElement.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.function.Function;
 import java.util.function.BiConsumer;
+import java.time.temporal.Temporal;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -43,6 +44,8 @@ import org.opengis.metadata.quality.Metaquality;
 import org.opengis.util.InternationalString;
 import org.apache.sis.internal.jaxb.FilterByVersion;
 import org.apache.sis.internal.jaxb.gco.InternationalStringAdapter;
+import org.apache.sis.internal.metadata.legacy.DateToTemporal;
+import org.apache.sis.internal.metadata.legacy.TemporalToDate;
 import org.apache.sis.internal.metadata.Dependencies;
 import org.apache.sis.internal.xml.LegacyNamespaces;
 
@@ -547,20 +550,18 @@ public class AbstractElement extends ISOMetadata 
implements Element {
     @Dependencies("getEvaluationMethod")
     @XmlElement(name = "dateTime", namespace = LegacyNamespaces.GMD)
     public Collection<Date> getDates() {
-        if (!FilterByVersion.LEGACY_METADATA.accept()) {
-            return null;
-        }
-        EvaluationMethod m = getEvaluationMethod();
-        if (m == null) {
-            if (state() == State.FINAL) {
-                return Collections.emptyList();
+        if (FilterByVersion.LEGACY_METADATA.accept()) {
+            EvaluationMethod m = getEvaluationMethod();
+            if (m == null) {
+                if (state() == State.FINAL) {
+                    return Collections.emptyList();
+                }
+                setEvaluationMethod(m = new DefaultEvaluationMethod());
             }
-            setEvaluationMethod(m = new DefaultEvaluationMethod());
-        }
-        if (m instanceof DefaultEvaluationMethod) {
-            return ((DefaultEvaluationMethod) m).getDates();
+            Collection<? extends Temporal> dates = m.getDates();
+            if (dates != null) return new TemporalToDate(dates);
         }
-        return Collections.unmodifiableCollection(m.getDates());
+        return null;
     }
 
     /**
@@ -574,7 +575,7 @@ public class AbstractElement extends ISOMetadata implements 
Element {
     @Deprecated
     public void setDates(final Collection<? extends Date> newValues) {
         if (!isNullOrEmpty(newValues)) {
-            setEvaluationMethodProperty(DefaultEvaluationMethod::setDates, 
newValues);
+            setEvaluationMethodProperty(DefaultEvaluationMethod::setDates, new 
DateToTemporal(newValues));
         }
     }
 
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java
index d733b85ef2..ab6c9894e0 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/AbstractResult.java
@@ -16,7 +16,7 @@
  */
 package org.apache.sis.metadata.iso.quality;
 
-import java.util.Date;
+import java.time.temporal.Temporal;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlSeeAlso;
@@ -28,8 +28,7 @@ import org.opengis.metadata.quality.ConformanceResult;
 import org.opengis.metadata.quality.QuantitativeResult;
 import org.opengis.metadata.quality.DescriptiveResult;
 import org.apache.sis.internal.jaxb.metadata.MD_Scope;
-import org.apache.sis.internal.jaxb.gco.GO_DateTime;
-import org.apache.sis.internal.metadata.ImplementationHelper;
+import org.apache.sis.internal.jaxb.gco.GO_Temporal;
 
 // Branch-dependent imports
 import org.opengis.metadata.maintenance.Scope;
@@ -78,15 +77,15 @@ public class AbstractResult extends ISOMetadata implements 
Result {
     private Scope resultScope;
 
     /**
-     * Date when the result was generated, or {@link Long#MIN_VALUE} if none.
+     * Date when the result was generated, or {@code null} if none.
      */
-    private long dateTime;
+    @SuppressWarnings("serial")
+    private Temporal dateTime;
 
     /**
      * Constructs an initially empty result.
      */
     public AbstractResult() {
-        dateTime = Long.MIN_VALUE;
     }
 
     /**
@@ -102,9 +101,7 @@ public class AbstractResult extends ISOMetadata implements 
Result {
         super(object);
         if (object != null) {
             resultScope = object.getResultScope();
-            dateTime    = 
ImplementationHelper.toMilliseconds(object.getDateTime());
-        } else {
-            dateTime = Long.MIN_VALUE;
+            dateTime    = object.getDateTime();
         }
     }
 
@@ -178,6 +175,9 @@ public class AbstractResult extends ISOMetadata implements 
Result {
 
     /**
      * Returns the date when the result was generated.
+     * This is typically a {@link java.time.LocalDate}, {@link 
java.time.LocalDateTime}
+     * or {@link java.time.ZonedDateTime} depending on whether the hour of the 
day and
+     * the time zone are provided.
      *
      * @return date of the result, or {@code null} if none.
      *
@@ -185,9 +185,9 @@ public class AbstractResult extends ISOMetadata implements 
Result {
      */
     @Override
     @XmlElement(name = "dateTime")
-    @XmlJavaTypeAdapter(GO_DateTime.Since2014.class)
-    public Date getDateTime() {
-        return ImplementationHelper.toDate(dateTime);
+    @XmlJavaTypeAdapter(GO_Temporal.Since2014.class)
+    public Temporal getDateTime() {
+        return dateTime;
     }
 
     /**
@@ -197,7 +197,7 @@ public class AbstractResult extends ISOMetadata implements 
Result {
      *
      * @since 1.3
      */
-    public void setDateTime(final Date newValue) {
-        dateTime = ImplementationHelper.toMilliseconds(newValue);
+    public void setDateTime(final Temporal newValue) {
+        dateTime = newValue;
     }
 }
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java
index 51764ef798..d204673ae5 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethod.java
@@ -16,11 +16,11 @@
  */
 package org.apache.sis.metadata.iso.quality;
 
-import java.util.Date;
 import java.util.Iterator;
 import java.util.Collection;
 import java.util.AbstractList;
 import java.io.Serializable;
+import java.time.temporal.Temporal;
 import javax.xml.bind.annotation.XmlType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -34,6 +34,7 @@ import org.opengis.metadata.quality.AggregationDerivation;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.util.collection.CheckedContainer;
 import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.ArgumentChecks;
 
 import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
 import static 
org.apache.sis.internal.metadata.ImplementationHelper.valueIfDefined;
@@ -107,8 +108,8 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
     /**
      * The start and end times as a list of O, 1 or 2 elements.
      */
-    private static final class Dates extends AbstractList<Date>
-            implements CheckedContainer<Date>, Cloneable, Serializable
+    private static final class Dates extends AbstractList<Temporal>
+            implements CheckedContainer<Temporal>, Cloneable, Serializable
     {
         /**
          * For cross-version compatibility.
@@ -116,10 +117,11 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
         private static final long serialVersionUID = 1210175223467194009L;
 
         /**
-         * Start time ({@code date1}) and end time ({@code date2}) on which a 
data quality measure
-         * was applied. Value is {@link Long#MIN_VALUE} if this information is 
not available.
+         * Start time ({@code date1}) and end time ({@code date2}) on which a 
data quality measure was applied.
+         * Value is {@code null} if this information is not available.
          */
-        private long date1, date2;
+        @SuppressWarnings("serial")
+        private Temporal date1, date2;
 
         /**
          * Creates a new list initialized with no dates.
@@ -132,8 +134,8 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          * Returns the type of elements in this list.
          */
         @Override
-        public Class<Date> getElementType() {
-            return Date.class;
+        public Class<Temporal> getElementType() {
+            return Temporal.class;
         }
 
         /**
@@ -141,8 +143,8 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          */
         @Override
         public void clear() {
-            date1 = Long.MIN_VALUE;
-            date2 = Long.MIN_VALUE;
+            date1 = null;
+            date2 = null;
         }
 
         /**
@@ -150,8 +152,8 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          */
         @Override
         public int size() {
-            if (date2 != Long.MIN_VALUE) return 2;
-            if (date1 != Long.MIN_VALUE) return 1;
+            if (date2 != null) return 2;
+            if (date1 != null) return 1;
             return 0;
         }
 
@@ -159,14 +161,17 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          * Returns the value at the given index.
          */
         @Override
-        @SuppressWarnings("fallthrough")
-        public Date get(final int index) {
-            long date = date1;
+        public Temporal get(final int index) {
+            Temporal date;
             switch (index) {
-                case 1:  date = date2;                                         
 // Fall through
-                case 0:  if (date != Long.MIN_VALUE) return new Date(date);    
 // else fallthrough.
-                default: throw new 
IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index));
+                case 0:  date = date1; break;
+                case 1:  date = date2; break;
+                default: date = null;  break;
+            }
+            if (date == null) {
+                throw new 
IndexOutOfBoundsException(Errors.format(Errors.Keys.IndexOutOfBounds_1, index));
             }
+            return date;
         }
 
         /**
@@ -174,9 +179,9 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          * Null values are not allowed.
          */
         @Override
-        public Date set(final int index, final Date value) {
-            final long date = value.getTime();
-            final Date previous = get(index);
+        public Temporal set(final int index, final Temporal date) {
+            ArgumentChecks.ensureNonNull("date", date);
+            final Temporal previous = get(index);
             switch (index) {
                 case 0: date1 = date; break;
                 case 1: date2 = date; break;
@@ -190,11 +195,11 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          */
         @Override
         @SuppressWarnings("fallthrough")
-        public Date remove(final int index) {
-            final Date previous = get(index);
+        public Temporal remove(final int index) {
+            final Temporal previous = get(index);
             switch (index) {
-                case 0: date1 = date2;                      // Fallthrough
-                case 1: date2 = Long.MIN_VALUE; break;
+                case 0: date1 = date2;  // Fallthrough
+                case 1: date2 = null; break;
             }
             modCount++;
             return previous;
@@ -205,9 +210,8 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          * Null values are not allowed.
          */
         @Override
-        public void add(final int index, final Date value) {
-            final long date = value.getTime();
-            if (date2 == Long.MIN_VALUE) {
+        public void add(final int index, final Temporal date) {
+            if (date2 == null) {
                 switch (index) {
                     case 0: {
                         date2 = date1;
@@ -216,7 +220,7 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
                         return;
                     }
                     case 1: {
-                        if (date1 == Long.MIN_VALUE) break;     // Exception 
will be thrown below.
+                        if (date1 == null) break;   // Exception will be 
thrown below.
                         date2 = date;
                         modCount++;
                         return;
@@ -231,16 +235,16 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
          */
         @Override
         @SuppressWarnings("fallthrough")
-        public boolean addAll(final Collection<? extends Date> dates) {
+        public boolean addAll(final Collection<? extends Temporal> dates) {
             final int c = modCount;
             if (dates != null) {
-                final Iterator<? extends Date> it = dates.iterator();
-                switch (size()) { // Fallthrough everywhere.
+                final Iterator<? extends Temporal> it = dates.iterator();
+                switch (size()) {               // Fallthrough everywhere.
                     case 0:  if (!it.hasNext()) break;
-                             date1 = it.next().getTime();
+                             date1 = it.next();
                              modCount++;
                     case 1:  if (!it.hasNext()) break;
-                             date2 = it.next().getTime();
+                             date2 = it.next();
                              modCount++;
                     default: if (!it.hasNext()) break;
                              throw new IllegalArgumentException(Errors.format(
@@ -418,7 +422,7 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
     @Override
     @XmlElement(name = "dateTime")
     @SuppressWarnings("ReturnOfCollectionOrArrayField")
-    public Collection<Date> getDates() {
+    public Collection<Temporal> getDates() {
         if (Semaphores.query(Semaphores.NULL_COLLECTION)) {
             return isNullOrEmpty(dates) ? null : dates;
         }
@@ -434,7 +438,7 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
      *
      * @param  newValues  the new dates, or {@code null}.
      */
-    public void setDates(final Collection<? extends Date> newValues) {
+    public void setDates(final Collection<? extends Temporal> newValues) {
         if (newValues != dates) {               // Mandatory check for 
avoiding the call to 'dates.clear()'.
             checkWritePermission(valueIfDefined(dates));
             writeDates(newValues);
@@ -444,7 +448,7 @@ public class DefaultEvaluationMethod extends ISOMetadata 
implements EvaluationMe
     /**
      * Implementation of {@link #setDates(Collection)}.
      */
-    private void writeDates(final Collection<? extends Date> newValues) {
+    private void writeDates(final Collection<? extends Temporal> newValues) {
         if (isNullOrEmpty(newValues)) {
             dates = null;
         } else {
diff --git 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java
 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java
index f5bf8095e8..12ec71efde 100644
--- 
a/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java
+++ 
b/core/sis-metadata/src/main/java/org/apache/sis/metadata/iso/quality/package-info.java
@@ -70,6 +70,7 @@
     @XmlJavaTypeAdapter(DQM_SourceReference.class),
     @XmlJavaTypeAdapter(DQM_ValueStructure.class),
     @XmlJavaTypeAdapter(GO_Boolean.class),
+    @XmlJavaTypeAdapter(GO_Temporal.class),
     @XmlJavaTypeAdapter(GO_DateTime.class),
     @XmlJavaTypeAdapter(GO_GenericName.class),
     @XmlJavaTypeAdapter(GO_Record.class),
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java
index b2217b9f52..8c90d2d4cf 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/internal/xml/XmlUtilitiesTest.java
@@ -16,10 +16,19 @@
  */
 package org.apache.sis.internal.xml;
 
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.YearMonth;
+import java.time.Year;
+import java.time.temporal.Temporal;
 import java.util.Date;
 import java.util.Locale;
 import javax.xml.datatype.XMLGregorianCalendar;
 import javax.xml.datatype.DatatypeConfigurationException;
+import org.apache.sis.internal.jaxb.Context;
 import org.apache.sis.test.xml.TestCase;
 import org.junit.Test;
 
@@ -31,24 +40,74 @@ import static 
javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED;
  * Test {@link XmlUtilities}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 1.3
  * @since   0.3
  * @module
  */
 public final strictfp class XmlUtilitiesTest extends TestCase {
     /**
-     * Tests the {@link XmlUtilities#toXML} method.
+     * Tests the {@link XmlUtilities#toXML(Context, Date)} method.
      * This test arbitrarily uses the CET timezone.
+     * The reverse operation is also tested.
      *
      * @throws DatatypeConfigurationException if the XML factory cannot be 
created.
      */
     @Test
-    public void testToXML() throws DatatypeConfigurationException {
+    public void testDateToXML() throws DatatypeConfigurationException {
         createContext(false, Locale.FRANCE, "CET");
-        final XMLGregorianCalendar calendar = XmlUtilities.toXML(context, new 
Date(1230786000000L));
+        final Date date = new Date(1230786000000L);
+        final XMLGregorianCalendar calendar = XmlUtilities.toXML(context, 
date);
         assertEquals("2009-01-01T06:00:00.000+01:00", calendar.toString());
+        assertEquals(date, XmlUtilities.toDate(context, calendar));
 
         calendar.setMillisecond(FIELD_UNDEFINED);
         assertEquals("2009-01-01T06:00:00+01:00", calendar.toString());
     }
+
+    /**
+     * Tests the {@link XmlUtilities#toXML(Context, Temporal)} method.
+     * This test arbitrarily uses the JST timezone.
+     *
+     * @throws DatatypeConfigurationException if the XML factory cannot be 
created.
+     */
+    @Test
+    public void testTemporalToXML() throws DatatypeConfigurationException {
+        createContext(false, Locale.JAPAN, "JST");
+        XMLGregorianCalendar calendar;
+        Temporal t;
+
+        t = Instant.ofEpochMilli(1230786000000L);
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2009-01-01T14:00:00.000+09:00", calendar.toString());
+
+        t = OffsetDateTime.parse("2009-01-01T06:00:00+01:00");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2009-01-01T06:00:00.000+01:00", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+
+        t = LocalDateTime.parse("2009-08-12T06:20:10");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2009-08-12T06:20:10.000", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+
+        t = LocalTime.parse("06:10:45");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("06:10:45.000", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+
+        t = LocalDate.parse("2009-05-08");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2009-05-08", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+
+        t = YearMonth.parse("2009-05");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2009-05", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+
+        t = Year.parse("2012");
+        calendar = XmlUtilities.toXML(context, t);
+        assertEquals("2012", calendar.toString());
+        assertEquals(t, XmlUtilities.toTemporal(context, calendar));
+    }
 }
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
index 02392b2c2b..f06163f89c 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
@@ -16,98 +16,44 @@
  */
 package org.apache.sis.metadata.iso.quality;
 
+import java.time.Instant;
 import java.util.Date;
-import java.util.List;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Collection;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
-import static org.apache.sis.test.Assert.*;
+import static org.junit.Assert.*;
 
 
 /**
  * Tests {@link AbstractElement}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
+ * @version 1.3
  * @since   0.3
  * @module
  */
 public final strictfp class AbstractElementTest extends TestCase {
     /**
-     * Tests the {@link AbstractElement#getDates()} list, which is backed by a 
custom implementation.
+     * Tests {@link Element#getDates()}.
      */
     @Test
-    public void testDates() {
-        final Date now   = new Date();
-        final Date later = new Date(now.getTime() + 60000);
-        final List<Date> dates = (List<Date>) new AbstractElement().getDates();
-        /*
-         * dates = []
-         */
-        assertTrue("isEmpty()", dates.isEmpty());
-        assertCanNotGet(dates, 2);
-        assertCanNotGet(dates, 1);
-        assertCanNotGet(dates, 0);
-        /*
-         * dates = [now]
-         */
-        assertCanNotAdd(dates, 2, now);
-        assertCanNotAdd(dates, 1, now);
-        dates.add(0, now);
-        assertEquals("size()", 1, dates.size());
-        assertCanNotGet(dates, 2);
-        assertCanNotGet(dates, 1);
-        assertEquals(now, dates.get(0));
-        /*
-         * dates = [now, later]
-         */
-        assertCanNotAdd(dates, 2, later);
-        dates.add(1, later);
-        assertEquals("size()", 2, dates.size());
-        assertCanNotGet(dates, 2);
-        assertEquals(later, dates.get(1));
-        assertEquals(now,   dates.get(0));
-        /*
-         * dates = [later]
-         */
-        assertEquals(now, dates.remove(0));
-        assertEquals("size()", 1, dates.size());
-        assertCanNotGet(dates, 2);
-        assertCanNotGet(dates, 1);
-        assertEquals(later, dates.get(0));
-        /*
-         * dates = [now, later]
-         */
-        dates.add(0, now);
-        assertEquals("size()", 2, dates.size());
-        assertCanNotGet(dates, 2);
-        assertEquals(later, dates.get(1));
-        assertEquals(now,   dates.get(0));
+    public void testGetDates() {
+        final Instant   startTime = Instant.parse("2009-05-08T14:10:00Z");
+        final Instant     endTime = Instant.parse("2009-05-12T21:45:00Z");
+        final DefaultEvaluationMethod method = new DefaultEvaluationMethod();
+        method.setDates(Arrays.asList(startTime, endTime));
+        final AbstractElement element = new AbstractElement();
+        element.setEvaluationMethod(method);
 
-        assertSerializedEquals(dates);
-    }
-
-    /**
-     * Asserts that we cannot get a date at the given index in the given list.
-     */
-    private static void assertCanNotGet(final List<Date> dates, final int 
index) {
-        try {
-            dates.get(index);
-            fail("Should not be allowed to get an element at index " + index);
-        } catch (IndexOutOfBoundsException e) {
-            // This is the expected exception.
-        }
-    }
-
-    /**
-     * Asserts that we cannot get add a date at the given index in the given 
list.
-     */
-    private static void assertCanNotAdd(final List<Date> dates, final int 
index, final Date date) {
-        try {
-            dates.add(index, date);
-            fail("Should not be allowed to add an element at index " + index);
-        } catch (IndexOutOfBoundsException e) {
-            // This is the expected exception.
-        }
+        @SuppressWarnings("deprecation")
+        final Collection<? extends Date> dates = element.getDates();
+        assertEquals(2, dates.size());
+        final Iterator<? extends Date> it = dates.iterator();
+        assertEquals(startTime, it.next().toInstant());
+        assertEquals(endTime,   it.next().toInstant());
+        assertFalse (it.hasNext());
     }
 }
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java
similarity index 80%
copy from 
core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
copy to 
core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java
index 02392b2c2b..f475257fb7 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/AbstractElementTest.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/metadata/iso/quality/DefaultEvaluationMethodTest.java
@@ -16,8 +16,9 @@
  */
 package org.apache.sis.metadata.iso.quality;
 
-import java.util.Date;
 import java.util.List;
+import java.time.Instant;
+import java.time.temporal.Temporal;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -25,22 +26,23 @@ import static org.apache.sis.test.Assert.*;
 
 
 /**
- * Tests {@link AbstractElement}.
+ * Tests {@link DefaultEvaluationMethod}.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.3
- * @since   0.3
+ * @version 1.3
+ * @since   1.3
  * @module
  */
-public final strictfp class AbstractElementTest extends TestCase {
+public final strictfp class DefaultEvaluationMethodTest extends TestCase {
     /**
-     * Tests the {@link AbstractElement#getDates()} list, which is backed by a 
custom implementation.
+     * Tests the {@link DefaultEvaluationMethod#getDates()} list,
+     * which is backed by a custom implementation.
      */
     @Test
     public void testDates() {
-        final Date now   = new Date();
-        final Date later = new Date(now.getTime() + 60000);
-        final List<Date> dates = (List<Date>) new AbstractElement().getDates();
+        final Instant now   = Instant.now();
+        final Instant later = Instant.ofEpochSecond(now.getEpochSecond()+ 60);
+        final List<Temporal> dates = (List<Temporal>) new 
DefaultEvaluationMethod().getDates();
         /*
          * dates = []
          */
@@ -90,7 +92,7 @@ public final strictfp class AbstractElementTest extends 
TestCase {
     /**
      * Asserts that we cannot get a date at the given index in the given list.
      */
-    private static void assertCanNotGet(final List<Date> dates, final int 
index) {
+    private static void assertCanNotGet(final List<Temporal> dates, final int 
index) {
         try {
             dates.get(index);
             fail("Should not be allowed to get an element at index " + index);
@@ -102,7 +104,7 @@ public final strictfp class AbstractElementTest extends 
TestCase {
     /**
      * Asserts that we cannot get add a date at the given index in the given 
list.
      */
-    private static void assertCanNotAdd(final List<Date> dates, final int 
index, final Date date) {
+    private static void assertCanNotAdd(final List<Temporal> dates, final int 
index, final Temporal date) {
         try {
             dates.add(index, date);
             fail("Should not be allowed to add an element at index " + index);
diff --git 
a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
 
b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
index 7a16422d54..f815db9985 100644
--- 
a/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
+++ 
b/core/sis-metadata/src/test/java/org/apache/sis/test/suite/MetadataTestSuite.java
@@ -119,6 +119,7 @@ import org.junit.BeforeClass;
     org.apache.sis.internal.jaxb.metadata.replace.QualityParameterTest.class,
     
org.apache.sis.metadata.iso.identification.DefaultCoupledResourceTest.class,
     
org.apache.sis.metadata.iso.identification.DefaultServiceIdentificationTest.class,
+    org.apache.sis.metadata.iso.quality.DefaultEvaluationMethodTest.class,
     org.apache.sis.metadata.iso.quality.AbstractElementTest.class,
     org.apache.sis.metadata.iso.quality.AbstractPositionalAccuracyTest.class,
     org.apache.sis.metadata.iso.quality.DefaultDomainConsistencyTest.class,

Reply via email to