This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new f2faacb692 Reintroduce `org.opengis.temporal.Instant` from ISO 19108,
because this is not the same thing as `java.time.Instant` despite the name.
Regroup all temporal objects in an `org.apache.sis.temporal` package, not
exported for now.
f2faacb692 is described below
commit f2faacb6926784fed19ef087d983ec9790ab23ea
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Jun 12 11:20:46 2024 +0200
Reintroduce `org.opengis.temporal.Instant` from ISO 19108, because this is
not the same thing as `java.time.Instant` despite the name.
Regroup all temporal objects in an `org.apache.sis.temporal` package, not
exported for now.
---
.../org/apache/sis/filter/TemporalOperation.java | 118 +++++---
.../test/org/apache/sis/filter/PeriodLiteral.java | 44 +--
.../org.apache.sis.metadata/main/module-info.java | 9 +
.../apache/sis/metadata/iso/DefaultMetadata.java | 2 +-
.../sis/metadata/iso/acquisition/DefaultEvent.java | 2 +-
.../iso/acquisition/DefaultRequestedDate.java | 2 +-
.../iso/acquisition/DefaultRequirement.java | 2 +-
.../sis/metadata/iso/citation/DefaultCitation.java | 2 +-
.../metadata/iso/citation/DefaultCitationDate.java | 4 +-
.../distribution/DefaultStandardOrderProcess.java | 2 +-
.../metadata/iso/extent/DefaultTemporalExtent.java | 8 +-
.../apache/sis/metadata/iso/extent/Extents.java | 21 +-
.../metadata/iso/identification/DefaultUsage.java | 6 +-
.../sis/metadata/iso/legacy/TemporalToDate.java | 2 +-
.../metadata/iso/lineage/DefaultProcessStep.java | 2 +-
.../apache/sis/pending/temporal/DefaultPeriod.java | 78 -----
.../org/apache/sis/pending/temporal/Primitive.java | 69 -----
.../sis/pending/temporal/TemporalUtilities.java | 127 --------
.../org/apache/sis/temporal/DefaultInstant.java | 180 ++++++++++++
.../org/apache/sis/temporal/DefaultPeriod.java | 107 +++++++
.../org/apache/sis/temporal/GeneralDuration.java | 325 +++++++++++++++++++++
.../apache/sis/temporal}/StandardDateFormat.java | 3 +-
.../org/apache/sis/temporal}/TemporalDate.java | 38 +--
.../org/apache/sis/temporal/TemporalUtilities.java | 102 +++++++
.../sis/{pending => }/temporal/package-info.java | 9 +-
.../org/apache/sis/xml/bind/gml/TM_Primitive.java | 8 +-
.../apache/sis/xml/bind/gml/TimePeriodBound.java | 19 +-
.../org/apache/sis/xml/privy/XmlUtilities.java | 2 +-
.../iso/citation/DefaultCitationDateTest.java | 8 +-
.../apache/sis/temporal/DefaultInstantTest.java | 79 +++++
.../org/apache/sis/temporal/DefaultPeriodTest.java | 79 +++++
.../sis/temporal}/StandardDateFormatTest.java | 2 +-
.../apache/sis/xml/bind/gml/TimePeriodTest.java | 17 +-
.../org/apache/sis/geometry/CoordinateFormat.java | 2 +-
.../main/org/apache/sis/io/wkt/AbstractParser.java | 2 +-
.../main/org/apache/sis/io/wkt/Formatter.java | 4 +-
.../main/org/apache/sis/io/wkt/WKTFormat.java | 4 +-
.../sis/referencing/datum/AbstractDatum.java | 2 +-
.../referencing/factory/sql/EPSGDataAccess.java | 2 +-
.../sis/referencing/privy/ExtentSelector.java | 2 +-
.../sis/test/integration/MetadataVerticalTest.java | 2 +-
.../sis/storage/geotiff/reader/XMLMetadata.java | 2 +-
.../storage/geotiff/reader/XMLMetadataTest.java | 4 +-
.../sis/storage/netcdf/classic/ChannelDecoder.java | 4 +-
.../sis/storage/netcdf/classic/VariableInfo.java | 2 +-
.../apache/sis/storage/netcdf/base/TestCase.java | 2 +-
.../sis/storage/xml/stream/StaxStreamReader.java | 2 +-
.../main/org/apache/sis/storage/csv/Store.java | 2 +-
.../org/apache/sis/storage/csv/TimeEncoding.java | 4 +-
.../main/org/apache/sis/measure/RangeFormat.java | 44 ++-
.../main/org/apache/sis/pending/jdk/JDK18.java | 11 +
.../main/org/apache/sis/util/resources/Errors.java | 5 +
.../apache/sis/util/resources/Errors.properties | 1 +
.../apache/sis/util/resources/Errors_fr.properties | 1 +
geoapi/snapshot | 2 +-
.../main/org/apache/sis/cql/CQL.java | 2 +-
.../org/apache/sis/cql/FilterToCQLVisitor.java | 2 +-
57 files changed, 1131 insertions(+), 457 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
index d826f84485..7918cc3f82 100644
---
a/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
+++
b/endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/TemporalOperation.java
@@ -163,6 +163,32 @@ abstract class TemporalOperation<T> implements
Serializable {
*/
protected abstract boolean evaluate(Period self, Period other);
+ /**
+ * Returns the beginning of the given period, or {@code null} if
indeterminate.
+ *
+ * @param p the period from which to get the beginning.
+ * @return beginning of the given period, or {@code null} if indeterminate.
+ *
+ * @todo Handle "before" and "after" indeterminate values.
+ */
+ static Temporal getBeginning(final Period p) {
+ final var t = p.getBeginning();
+ return (t != null) ? t.getPosition() : null;
+ }
+
+ /**
+ * Returns the ending of the given period, or {@code null} if
indeterminate.
+ *
+ * @param p the period from which to get the ending.
+ * @return ending of the given period, or {@code null} if indeterminate.
+ *
+ * @todo Handle "before" and "after" indeterminate values.
+ */
+ static Temporal getEnding(final Period p) {
+ final var t = p.getEnding();
+ return (t != null) ? t.getPosition() : null;
+ }
+
/**
* Returns {@code true} if {@code other} is non-null and the specified
comparison evaluates to {@code true}.
* This is a helper function for {@code evaluate(…)} methods
implementations.
@@ -247,20 +273,20 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(T self, Period other) {
- return compare(EQUAL, self, other.getBeginning()) &&
- compare(EQUAL, self, other.getEnding());
+ return compare(EQUAL, self, getBeginning(other)) &&
+ compare(EQUAL, self, getEnding(other));
}
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(Period self, T other) {
- return compare(EQUAL, other, self.getBeginning()) &&
- compare(EQUAL, other, self.getEnding());
+ return compare(EQUAL, other, getBeginning(self)) &&
+ compare(EQUAL, other, getEnding(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, Period other) {
- return compare(EQUAL, self.getBeginning(), other.getBeginning()) &&
- compare(EQUAL, self.getEnding(), other.getEnding());
+ return compare(EQUAL, getBeginning(self), getBeginning(other)) &&
+ compare(EQUAL, getEnding(self), getEnding(other));
}
}
@@ -301,17 +327,17 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Relationship not defined by ISO 19108:2006. */
@Override public boolean evaluate(T self, Period other) {
- return compare(BEFORE, self, other.getBeginning());
+ return compare(BEFORE, self, getBeginning(other));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, T other) {
- return compare(AFTER, other, self.getEnding());
+ return compare(AFTER, other, getEnding(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, Period other) {
- return compare(BEFORE, self.getEnding(), other.getBeginning());
+ return compare(BEFORE, getEnding(self), getBeginning(other));
}
}
@@ -352,17 +378,17 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Relationship not defined by ISO 19108:2006. */
@Override public boolean evaluate(T self, Period other) {
- return compare(AFTER, self, other.getEnding());
+ return compare(AFTER, self, getEnding(other));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, T other) {
- return compare(BEFORE, other, self.getBeginning());
+ return compare(BEFORE, other, getBeginning(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, Period other) {
- return compare(AFTER, self.getBeginning(), other.getEnding());
+ return compare(AFTER, getBeginning(self), getEnding(other));
}
}
@@ -391,8 +417,8 @@ abstract class TemporalOperation<T> implements Serializable
{
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getBeginning(), other.getBeginning())
&&
- compare(BEFORE, self.getEnding(), other.getEnding());
+ return compare(EQUAL, getBeginning(self), getBeginning(other)) &&
+ compare(BEFORE, getEnding(self), getEnding(other));
}
}
@@ -421,8 +447,8 @@ abstract class TemporalOperation<T> implements Serializable
{
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getEnding(), other.getEnding()) &&
- compare(AFTER, self.getBeginning(), other.getBeginning());
+ return compare(EQUAL, getEnding(self), getEnding(other)) &&
+ compare(AFTER, getBeginning(self), getBeginning(other));
}
}
@@ -452,13 +478,13 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(Period self, T other) {
- return compare(EQUAL, other, self.getBeginning());
+ return compare(EQUAL, other, getBeginning(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getBeginning(), other.getBeginning()) &&
- compare(AFTER, self.getEnding(), other.getEnding());
+ return compare(EQUAL, getBeginning(self), getBeginning(other)) &&
+ compare(AFTER, getEnding(self), getEnding(other));
}
}
@@ -488,13 +514,13 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final T other) {
- return compare(EQUAL, other, self.getEnding());
+ return compare(EQUAL, other, getEnding(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getEnding(), other.getEnding()) &&
- compare(BEFORE, self.getBeginning(), other.getBeginning());
+ return compare(EQUAL, getEnding(self), getEnding(other)) &&
+ compare(BEFORE, getBeginning(self), getBeginning(other));
}
}
@@ -528,17 +554,17 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(final T self, final Period other) {
- return compare(EQUAL, self, other.getBeginning());
+ return compare(EQUAL, self, getBeginning(other));
}
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(final Period self, final T other) {
- return compare(EQUAL, other, self.getEnding());
+ return compare(EQUAL, other, getEnding(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getEnding(), other.getBeginning());
+ return compare(EQUAL, getEnding(self), getBeginning(other));
}
}
@@ -572,17 +598,17 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(final T self, final Period other) {
- return compare(EQUAL, self, other.getEnding());
+ return compare(EQUAL, self, getEnding(other));
}
/** Extension to ISO 19108: handle instant as a tiny period. */
@Override public boolean evaluate(final Period self, final T other) {
- return compare(EQUAL, other, self.getBeginning());
+ return compare(EQUAL, other, getBeginning(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(EQUAL, self.getBeginning(), other.getEnding());
+ return compare(EQUAL, getBeginning(self), getEnding(other));
}
}
@@ -616,8 +642,8 @@ abstract class TemporalOperation<T> implements Serializable
{
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(AFTER, self.getBeginning(), other.getBeginning())
&&
- compare(BEFORE, self.getEnding(), other.getEnding());
+ return compare(AFTER, getBeginning(self), getBeginning(other)) &&
+ compare(BEFORE, getEnding(self), getEnding(other));
}
}
@@ -652,14 +678,14 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final T other) {
- return compare(AFTER, other, self.getBeginning()) &&
- compare(BEFORE, other, self.getEnding());
+ return compare(AFTER, other, getBeginning(self)) &&
+ compare(BEFORE, other, getEnding(self));
}
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
- return compare(BEFORE, self.getBeginning(), other.getBeginning())
&&
- compare(AFTER, self.getEnding(), other.getEnding());
+ return compare(BEFORE, getBeginning(self), getBeginning(other)) &&
+ compare(AFTER, getEnding(self), getEnding(other));
}
}
@@ -689,10 +715,10 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
- return ((otherBegin = other.getBeginning()) != null) &&
- ((selfBegin = self .getBeginning()) != null) &&
compare(BEFORE, selfBegin, otherBegin) &&
- ((selfEnd = self .getEnding()) != null) &&
compare(AFTER, selfEnd, otherBegin) &&
- ((otherEnd = other.getEnding()) != null) &&
compare(BEFORE, selfEnd, otherEnd);
+ return ((otherBegin = getBeginning(other)) != null) &&
+ ((selfBegin = getBeginning(self)) != null) &&
compare(BEFORE, selfBegin, otherBegin) &&
+ ((selfEnd = getEnding (self)) != null) &&
compare(AFTER, selfEnd, otherBegin) &&
+ ((otherEnd = getEnding (other)) != null) &&
compare(BEFORE, selfEnd, otherEnd);
}
}
@@ -722,10 +748,10 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by ISO 19108:2006 (corrigendum) §5.2.3.5. */
@Override public boolean evaluate(final Period self, final Period
other) {
final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
- return ((selfBegin = self .getBeginning()) != null) &&
- ((otherBegin = other.getBeginning()) != null) &&
compare(AFTER, selfBegin, otherBegin) &&
- ((otherEnd = other.getEnding()) != null) &&
compare(BEFORE, selfBegin, otherEnd) &&
- ((selfEnd = self .getEnding()) != null) &&
compare(AFTER, selfEnd, otherEnd);
+ return ((selfBegin = getBeginning(self)) != null) &&
+ ((otherBegin = getBeginning(other)) != null) &&
compare(AFTER, selfBegin, otherBegin) &&
+ ((otherEnd = getEnding (other)) != null) &&
compare(BEFORE, selfBegin, otherEnd) &&
+ ((selfEnd = getEnding (self)) != null) &&
compare(AFTER, selfEnd, otherEnd);
}
}
@@ -753,10 +779,10 @@ abstract class TemporalOperation<T> implements
Serializable {
/** Condition defined by OGC filter specification. */
@Override public boolean evaluate(final Period self, final Period
other) {
final Temporal selfBegin, selfEnd, otherBegin, otherEnd;
- return ((selfBegin = self .getBeginning()) != null) &&
- ((otherEnd = other.getEnding()) != null) &&
compare(BEFORE, selfBegin, otherEnd) &&
- ((selfEnd = self .getEnding()) != null) &&
- ((otherBegin = other.getBeginning()) != null) &&
compare(AFTER, selfEnd, otherBegin);
+ return ((selfBegin = getBeginning(self)) != null) &&
+ ((otherEnd = getEnding (other)) != null) &&
compare(BEFORE, selfBegin, otherEnd) &&
+ ((selfEnd = getEnding (self)) != null) &&
+ ((otherBegin = getBeginning(other)) != null) &&
compare(AFTER, selfEnd, otherBegin);
}
}
}
diff --git
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/PeriodLiteral.java
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/PeriodLiteral.java
index 4318272100..beaa0746a2 100644
---
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/PeriodLiteral.java
+++
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/PeriodLiteral.java
@@ -18,19 +18,13 @@ package org.apache.sis.filter;
import java.time.Instant;
import java.io.Serializable;
+import org.apache.sis.temporal.TemporalUtilities;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import java.time.temporal.TemporalAmount;
import org.opengis.feature.Feature;
import org.opengis.filter.Expression;
import org.opengis.filter.Literal;
import org.opengis.temporal.Period;
-import org.opengis.temporal.RelativePosition;
-import org.opengis.temporal.TemporalPrimitive;
-import org.opengis.temporal.TemporalGeometricPrimitive;
-
-// Specific to the geoapi-4.0 branch:
-import org.opengis.metadata.Identifier;
/**
@@ -55,18 +49,34 @@ final class PeriodLiteral implements Period,
Literal<Feature,Period>, Serializab
/**
* Returns the constant value held by this object.
*/
- @Override public Period getValue() {return this;}
+ @Override
+ public Period getValue() {
+ return this;
+ }
+
+ /**
+ * Returns the beginning of this period.
+ */
+ @Override
+ public org.opengis.temporal.Instant getBeginning() {
+ return TemporalUtilities.createInstant(Instant.ofEpochMilli(begin));
+ }
- /** Returns a bound of this period. */
- @Override public Instant getBeginning() {return
Instant.ofEpochMilli(begin);}
- @Override public Instant getEnding() {return Instant.ofEpochMilli(end);}
+ /**
+ * Returns the ending of this period.
+ */
+ @Override
+ public org.opengis.temporal.Instant getEnding() {
+ return TemporalUtilities.createInstant(Instant.ofEpochMilli(end));
+ }
- /** Not needed for the tests. */
- @Override public Identifier getName()
{throw new UnsupportedOperationException();}
- @Override public RelativePosition relativePosition(TemporalPrimitive o)
{throw new UnsupportedOperationException();}
- @Override public TemporalAmount distance(TemporalGeometricPrimitive o)
{throw new UnsupportedOperationException();}
- @Override public TemporalAmount length()
{throw new UnsupportedOperationException();}
- @Override public <N> Expression<Feature,N> toValueType(Class<N> target)
{throw new UnsupportedOperationException();}
+ /**
+ * Not needed for the tests.
+ */
+ @Override
+ public <N> Expression<Feature,N> toValueType(Class<N> target) {
+ throw new UnsupportedOperationException();
+ }
/**
* Hash code value. Used by the tests for checking the results of
deserialization.
diff --git a/endorsed/src/org.apache.sis.metadata/main/module-info.java
b/endorsed/src/org.apache.sis.metadata/main/module-info.java
index 4aacf66825..2f35b34abf 100644
--- a/endorsed/src/org.apache.sis.metadata/main/module-info.java
+++ b/endorsed/src/org.apache.sis.metadata/main/module-info.java
@@ -76,6 +76,15 @@ module org.apache.sis.metadata {
/*
* Internal API open only to other Apache SIS modules.
*/
+ exports org.apache.sis.temporal to
+ org.apache.sis.referencing,
+ org.apache.sis.feature,
+ org.apache.sis.storage,
+ org.apache.sis.storage.xml,
+ org.apache.sis.storage.netcdf,
+ org.apache.sis.storage.geotiff,
+ org.apache.sis.cql; // In the "incubator"
sub-project.
+
exports org.apache.sis.metadata.privy to
org.apache.sis.referencing,
org.apache.sis.feature,
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadata.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadata.java
index d9265feb93..5ba20d67fb 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadata.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/DefaultMetadata.java
@@ -62,7 +62,7 @@ import org.apache.sis.util.Emptiable;
import org.apache.sis.util.ObjectConverter;
import org.apache.sis.util.collection.Containers;
import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.metadata.MetadataCopier;
import org.apache.sis.metadata.MetadataStandard;
import org.apache.sis.metadata.iso.citation.DefaultCitation;
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
index 3f61f355ef..732bc85b94 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultEvent.java
@@ -31,7 +31,7 @@ import org.opengis.metadata.acquisition.PlatformPass;
import org.opengis.metadata.acquisition.Sequence;
import org.opengis.metadata.acquisition.Trigger;
import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
index 15f26db867..f1a9226e80 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequestedDate.java
@@ -23,7 +23,7 @@ import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import org.opengis.metadata.acquisition.RequestedDate;
import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
index 357b1ebb35..355c09c9b7 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/acquisition/DefaultRequirement.java
@@ -29,7 +29,7 @@ import org.opengis.metadata.acquisition.RequestedDate;
import org.opengis.metadata.acquisition.Requirement;
import org.opengis.metadata.citation.Citation;
import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
// Specific to the geoapi-4.0 branch:
import org.opengis.metadata.citation.Responsibility;
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
index d911b0cba3..dfbfcfd24c 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitation.java
@@ -36,7 +36,7 @@ import org.apache.sis.xml.IdentifierMap;
import org.apache.sis.xml.bind.FilterByVersion;
import org.apache.sis.xml.bind.NonMarshalledAuthority;
import org.apache.sis.xml.privy.LegacyNamespaces;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.metadata.TitleProperty;
import org.apache.sis.metadata.iso.ISOMetadata;
import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
index 2db4683608..8f75d6a434 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/citation/DefaultCitationDate.java
@@ -25,7 +25,7 @@ import org.opengis.metadata.citation.CitationDate;
import org.opengis.metadata.citation.DateType;
import org.apache.sis.metadata.TitleProperty;
import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
@@ -50,7 +50,7 @@ import org.apache.sis.util.privy.TemporalDate;
* @version 1.5
* @since 0.3
*/
-@TitleProperty(name = "date")
+@TitleProperty(name = "referenceDate")
@XmlType(name = "CI_Date_Type", propOrder = {
"referenceDate",
"dateType"
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
index 985cfdb18e..207f5ce244 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/distribution/DefaultStandardOrderProcess.java
@@ -30,7 +30,7 @@ import org.opengis.metadata.distribution.StandardOrderProcess;
import org.apache.sis.xml.bind.gco.GO_RecordType;
import org.apache.sis.xml.bind.gco.GO_Record;
import org.apache.sis.metadata.iso.ISOMetadata;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
index dea4892eba..4539bf5493 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/DefaultTemporalExtent.java
@@ -31,8 +31,8 @@ import org.opengis.metadata.extent.SpatialTemporalExtent;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.metadata.iso.ISOMetadata;
import org.apache.sis.metadata.privy.ReferencingServices;
-import org.apache.sis.pending.temporal.TemporalUtilities;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalUtilities;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.xml.NilObject;
import org.apache.sis.xml.NilReason;
@@ -175,7 +175,7 @@ public class DefaultTemporalExtent extends ISOMetadata
implements TemporalExtent
}
/**
- * Infers a value from the extent as a {@code Instant} object.
+ * Infers a value from the extent as an {@code Instant} object.
*
* @param begin {@code true} for the start time, or {@code false} for
the end time.
* @return the requested time as an instant, or {@code null} if none.
@@ -183,7 +183,7 @@ public class DefaultTemporalExtent extends ISOMetadata
implements TemporalExtent
static Temporal getBound(final TemporalPrimitive extent, final boolean
begin) {
if (extent instanceof Period) {
final var p = (Period) extent;
- return begin ? p.getBeginning() : p.getEnding();
+ return (begin ? p.getBeginning() : p.getEnding()).getPosition();
}
return null;
}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
index 4fa65934dd..704c490bcc 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/extent/Extents.java
@@ -62,7 +62,6 @@ import org.apache.sis.measure.Longitude;
import org.apache.sis.measure.MeasurementRange;
import org.apache.sis.measure.Range;
import org.apache.sis.pending.jdk.JDK23;
-import org.apache.sis.pending.temporal.DefaultPeriod;
import org.apache.sis.util.OptionalCandidate;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ComparisonMode;
@@ -71,7 +70,7 @@ import org.apache.sis.util.Static;
import org.apache.sis.util.iso.Types;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
import static org.apache.sis.util.privy.CollectionsExt.nonNull;
import static org.apache.sis.util.collection.Containers.isNullOrEmpty;
import static
org.apache.sis.metadata.privy.ReferencingServices.AUTHALIC_RADIUS;
@@ -492,9 +491,9 @@ public final class Extents extends Static {
*/
@OptionalCandidate
public static Range<Date> getTimeRange(final Extent extent) {
- final DefaultPeriod period = getPeriod(extent);
- final Date min = TemporalDate.toDate(period.getBeginning());
- final Date max = TemporalDate.toDate(period.getEnding());
+ final Temporal[] period = getPeriod(extent);
+ final Date min = TemporalDate.toDate(period[0]);
+ final Date max = TemporalDate.toDate(period[1]);
if (min == null && max == null) {
return null;
}
@@ -561,9 +560,9 @@ public final class Extents extends Static {
*/
public static Optional<Instant> getInstant(final Extent extent, final
ZoneId zone, final double location) {
ArgumentChecks.ensureFinite("location", location);
- final DefaultPeriod period = getPeriod(extent);
- Instant min = TemporalDate.toInstant(period.getBeginning(), zone);
- Instant max = TemporalDate.toInstant(period.getEnding(), zone);
+ final Temporal[] period = getPeriod(extent);
+ Instant min = TemporalDate.toInstant(period[0], zone);
+ Instant max = TemporalDate.toInstant(period[1], zone);
if (min == null || location == 1) {
return Optional.ofNullable(max);
}
@@ -576,11 +575,11 @@ public final class Extents extends Static {
/**
* Returns the minimum and maximum temporal values in an array of length 2.
*
- * @param extent the extent on which to apply a function, or {@code
null}.
+ * @param extent the extent on which to apply a function, or {@code
null}.
* @return the minimum and maximum values. Never null, but may contain
null elements.
* @throws DateTimeException if there is more than one temporal extent,
and some temporal values are not comparable.
*/
- private static DefaultPeriod getPeriod(final Extent extent) {
+ private static Temporal[] getPeriod(final Extent extent) {
Temporal min = null;
Temporal max = null;
if (extent != null) {
@@ -600,7 +599,7 @@ public final class Extents extends Static {
if ( endTime != null && (max == null || TemporalDate.compare(
endTime, max) > 0)) max = endTime;
}
}
- return new DefaultPeriod(min, max);
+ return new Temporal[] {min, max};
}
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
index cf6f3f105a..e3a0d20692 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/identification/DefaultUsage.java
@@ -34,9 +34,9 @@ import org.apache.sis.xml.privy.LegacyNamespaces;
import org.apache.sis.metadata.TitleProperty;
import org.apache.sis.metadata.iso.ISOMetadata;
import org.apache.sis.metadata.internal.Dependencies;
-import org.apache.sis.pending.temporal.TemporalUtilities;
+import org.apache.sis.temporal.TemporalUtilities;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.util.iso.Types;
-import org.apache.sis.util.privy.TemporalDate;
// Specific to the geoapi-4.0 branch:
import org.opengis.metadata.citation.Responsibility;
@@ -239,7 +239,7 @@ public class DefaultUsage extends ISOMetadata implements
Usage {
final Collection<TemporalPrimitive> usageDates = getUsageDates();
if (usageDates != null) {
for (TemporalPrimitive t : usageDates) {
- Date p = TemporalDate.toDate(t.position().orElse(null));
+ Date p =
TemporalDate.toDate(TemporalUtilities.getInstant(t));
if (p != null) {
return p;
}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/legacy/TemporalToDate.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/legacy/TemporalToDate.java
index 2249cde9ff..ab7183702a 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/legacy/TemporalToDate.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/legacy/TemporalToDate.java
@@ -21,7 +21,7 @@ import java.util.AbstractCollection;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
index 05df948518..030509cdfe 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/iso/lineage/DefaultProcessStep.java
@@ -37,7 +37,7 @@ import org.apache.sis.xml.bind.FilterByVersion;
import org.apache.sis.xml.bind.gml.TM_Primitive;
import org.apache.sis.xml.bind.metadata.MD_Scope;
import org.apache.sis.xml.privy.LegacyNamespaces;
-import org.apache.sis.pending.temporal.TemporalUtilities;
+import org.apache.sis.temporal.TemporalUtilities;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
import org.opengis.metadata.maintenance.Scope;
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
deleted file mode 100644
index 6f4cff5259..0000000000
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/DefaultPeriod.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.pending.temporal;
-
-import java.util.Objects;
-import java.time.temporal.Temporal;
-
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import java.time.Duration;
-import java.time.temporal.TemporalAmount;
-import org.opengis.temporal.Period;
-
-
-/**
- * Default implementation of GeoAPI period. This is a temporary class;
- * GeoAPI temporal interfaces are expected to change a lot in a future
revision.
- *
- * @author Martin Desruisseaux (Geomatys)
- */
-public final class DefaultPeriod extends Primitive implements Period {
- /** Bounds making this period. */
- private final Temporal beginning, ending;
-
- /** Creates a new period with the given bounds. */
- public DefaultPeriod(final Temporal beginning, final Temporal ending) {
- this.beginning = beginning;
- this.ending = ending;
- }
-
- /** The beginning instant at which this period starts. */
- @Override public Temporal getBeginning() {
- return beginning;
- }
-
- /** The ending instant at which this period ends. */
- @Override public Temporal getEnding() {
- return ending;
- }
-
- /** Duration of this temporal geometric primitive. */
- @Override public TemporalAmount length() {
- return (beginning != null && ending != null) ?
Duration.between(beginning, ending) : null;
- }
-
- /** String representation. */
- @Override public String toString() {
- return "[" + beginning + " … " + ending + ']';
- }
-
- /** Hash code value of the time position. */
- @Override public int hashCode() {
- return Objects.hash(beginning, ending);
- }
-
- /** Compares with given object for equality. */
- @Override public boolean equals(final Object obj) {
- if (obj instanceof DefaultPeriod) {
- DefaultPeriod other = (DefaultPeriod) obj;
- return Objects.equals(other.beginning, beginning) &&
- Objects.equals(other.ending, ending);
- }
- return false;
- }
-}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/Primitive.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/Primitive.java
deleted file mode 100644
index 0a8220d48c..0000000000
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/Primitive.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.pending.temporal;
-
-import java.time.temporal.TemporalAmount;
-import org.opengis.temporal.RelativePosition;
-import org.opengis.temporal.TemporalGeometricPrimitive;
-import org.opengis.temporal.TemporalPrimitive;
-
-// Specific to the geoapi-4.0 branch:
-import org.opengis.metadata.Identifier;
-
-
-/**
- * Base implementation of GeoAPI temporal primitives. This is a temporary
class;
- * GeoAPI temporal interfaces are expected to change a lot in a future
revision.
- *
- * @author Martin Desruisseaux (Geomatys)
- */
-abstract class Primitive implements TemporalGeometricPrimitive, Identifier {
- /**
- * For sub-class constructors.
- */
- Primitive() {
- }
-
- /**
- * The primary name by which this object is identified.
- * This field is inherited from ISO 19111 {@code IdentifiedObject} and is
in principle mandatory.
- */
- @Override
- public final Identifier getName() {
- return this;
- }
-
- /**
- * Returns the string representation as the code for this object. This is
not a correct identifier code,
- * but we use that as a trick for forcing {@link
org.apache.sis.util.collection.TreeTableFormat} to show
- * the temporal value, because the formatter handles {@link
org.opengis.referencing.IdentifiedObject} in
- * a special way.
- */
- @Override public final String getCode() {
- return toString();
- }
-
- /** Position of this primitive relative to another primitive. */
- @Override public final RelativePosition relativePosition(TemporalPrimitive
other) {
- throw new UnsupportedOperationException();
- }
-
- /** Absolute value of the difference between temporal positions. */
- @Override public final TemporalAmount distance(TemporalGeometricPrimitive
other) {
- throw new UnsupportedOperationException();
- }
-}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/TemporalUtilities.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/TemporalUtilities.java
deleted file mode 100644
index a8800060f8..0000000000
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/TemporalUtilities.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.pending.temporal;
-
-import java.util.Date;
-import java.time.temporal.Temporal;
-import org.opengis.temporal.TemporalPrimitive;
-import org.apache.sis.util.privy.TemporalDate;
-
-// Specific to the geoapi-3.1 and geoapi-4.0 branches:
-import org.opengis.temporal.Period;
-
-
-/**
- * Utilities related to ISO 19108 objects.
- *
- * @author Martin Desruisseaux (Geomatys)
- * @author Guilhem Legal (Geomatys)
- */
-public final class TemporalUtilities {
- /**
- * Do not allow instantiation of this class.
- */
- private TemporalUtilities() {
- }
-
- /**
- * Creates an instant for the given Java temporal instant.
- *
- * @param time the date for which to create instant, or {@code null}.
- * @return the instant, or {@code null} if the given time was null.
- */
- public static TemporalPrimitive createInstant(final Temporal time) {
- return (time == null) ? null : new DefaultPeriod(time, time);
- }
-
- /**
- * Creates a period for the given begin and end instant.
- *
- * @param beginning the begin instant (inclusive), or {@code null}.
- * @param ending the end instant (inclusive), or {@code null}.
- * @return the period, or {@code null} if both arguments are null.
- *
- * @todo Needs to avoid assuming UTC timezone.
- */
- public static TemporalPrimitive createPeriod(final Temporal beginning,
final Temporal ending) {
- return (beginning == null && ending == null) ? null : new
DefaultPeriod(beginning, ending);
- }
-
- /**
- * Returns the given value as a period if it is not a single point in
time, or {@code null} otherwise.
- * This method is mutually exclusive with {@link
#getInstant(TemporalPrimitive)}: if one method returns
- * a non-null value, then the other method shall return a null value.
- *
- * @param time the instant or period for which to get a time range, or
{@code null}.
- * @return the period, or {@code null} if none.
- */
- public static Period getPeriod(final TemporalPrimitive time) {
- if (time instanceof Period) {
- var p = (Period) time;
- final Temporal begin = p.getBeginning();
- if (begin != null) {
- final Temporal end = p.getEnding();
- if (end != null && !begin.equals(end)) {
- return p;
- }
- }
- }
- return null;
- }
-
- /**
- * Returns the given value as an ISO 19108 instant (a temporal in Java API)
- * if the period is a single point in time, or {@code null} otherwise.
- * This method is mutually exclusive with {@link
#getPeriod(TemporalPrimitive)}:
- * if one method returns a non-null value, then the other method shall
return a null value.
- *
- * @param time the instant or period for which to get a date, or {@code
null}.
- * @return the ISO 19108 instant, or {@code null} if none.
- */
- public static Temporal getInstant(final TemporalPrimitive time) {
- if (time instanceof Period) {
- var p = (Period) time;
- final Temporal begin = p.getBeginning();
- final Temporal end = p.getEnding();
- if (end == null) {
- return begin;
- }
- if (begin == null || begin.equals(end)) {
- return end;
- }
- }
- return null;
- }
-
- /**
- * Infers a value from the extent as a {@link Date} object.
- * This method is used for compatibility with legacy API and may disappear
in future SIS version.
- *
- * @param time the instant or period for which to get a date, or {@code
null}.
- * @return the requested time as a Java date, or {@code null} if none.
- */
- public static Date getAnyDate(final TemporalPrimitive time) {
- if (time instanceof Period) {
- var p = (Period) time;
- Temporal instant;
- if ((instant = p.getEnding()) != null || (instant =
p.getBeginning()) != null) {
- return TemporalDate.toDate(instant);
- }
- }
- return null;
- }
-}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java
new file mode 100644
index 0000000000..f8c0a5af14
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultInstant.java
@@ -0,0 +1,180 @@
+/*
+ * 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.temporal;
+
+import java.util.Objects;
+import java.util.Optional;
+import java.io.Serializable;
+import java.time.Duration;
+import java.time.DateTimeException;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAmount;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.resources.Errors;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.Period;
+import org.opengis.temporal.Instant;
+import org.opengis.temporal.TemporalPrimitive;
+import org.opengis.temporal.IndeterminateValue;
+import org.opengis.filter.TemporalOperatorName;
+
+
+/**
+ * Default implementation of an instant as defined by ISO 19108.
+ * This is not the same as {@link java.time.Instant}, because the
+ * instant can actually be a date, or may be indeterminate.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+final class DefaultInstant implements Instant, Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 3898772638524283287L;
+
+ /**
+ * The temporal position as a date, time or date/time.
+ * May be {@code null} if {@link #indeterminate} is non-null and not
"before" or "after".
+ */
+ @SuppressWarnings("serial") // Standard implementations are
serializable.
+ private final Temporal position;
+
+ /**
+ * The indeterminate value, or {@code null} if none.
+ */
+ private final IndeterminateValue indeterminate;
+
+ /**
+ * Creates a new instant.
+ *
+ * @param position the temporal position, or {@code null} if
unknown or now.
+ * @param indeterminate the indeterminate value, or {@code null} if none.
+ */
+ DefaultInstant(final Temporal position, final IndeterminateValue
indeterminate) {
+ this.position = position;
+ this.indeterminate = indeterminate;
+ }
+
+ /**
+ * Returns the date, time or position on the time-scale represented by
this primitive.
+ * Should not be null, unless the value is {@linkplain
IndeterminateValue#UNKNOWN unknown}.
+ *
+ * @return the date, time or position on the time-scale represented by
this primitive.
+ */
+ @Override
+ public Temporal getPosition() {
+ if (indeterminate != IndeterminateValue.NOW) {
+ return position;
+ }
+ return java.time.Instant.now();
+ }
+
+ /**
+ * Returns the reason why the temporal position is missing or inaccurate.
+ *
+ * @return the reason why the temporal position is missing or inaccurate.
+ */
+ @Override
+ public Optional<IndeterminateValue> getIndeterminatePosition() {
+ return Optional.ofNullable(indeterminate);
+ }
+
+ /**
+ * Returns the distance from this instant to another instant or period.
+ *
+ * @param other the other object from which to measure the distance.
+ * @return the distance from this instant to another instant or period.
+ * @throws DateTimeException if the duration cannot be computed.
+ * @throws ArithmeticException if the calculation exceeds the integer
capacity.
+ */
+ @Override
+ public TemporalAmount distance(final TemporalPrimitive other) {
+ ArgumentChecks.ensureNonNull("other", other);
+ if (other instanceof Instant) {
+ return GeneralDuration.distance(this, (Instant) other, false,
true);
+ } else if (other instanceof Period) {
+ final var p = (Period) other;
+ TemporalAmount t = GeneralDuration.distance(this,
p.getBeginning(), false, false);
+ if (t == null) {
+ t = GeneralDuration.distance(this, p.getEnding(), true, false);
+ if (t == null) {
+ return Duration.ZERO;
+ }
+ }
+ return t;
+ } else {
+ throw new
DateTimeException(Errors.format(Errors.Keys.UnsupportedType_1,
other.getClass()));
+ }
+ }
+
+ /**
+ * Determines the position of this primitive relative to another temporal
primitive.
+ * The relative position is identified by an operator which evaluates to
{@code true}
+ * when the two operands are {@code this} and {@code other}.
+ *
+ * @param other the other primitive for which to determine the relative
position.
+ * @return a temporal operator which is true when evaluated between this
primitive and the other primitive.
+ * @throws DateTimeException if the temporal objects cannot be compared.
+ */
+ @Override
+ public TemporalOperatorName findRelativePosition(final TemporalPrimitive
other) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Compares this instant with the given object for equality.
+ */
+ @Override
+ public boolean equals(final Object object) {
+ if (object == this) {
+ return true;
+ }
+ if (object instanceof DefaultInstant) {
+ final var that = (DefaultInstant) object;
+ return Objects.equals(position, that.position) && indeterminate ==
that.indeterminate;
+ }
+ return false;
+ }
+
+ /**
+ * Computes a hash code value for this instant.
+ */
+ @Override
+ public int hashCode() {
+ return Objects.hash(position, indeterminate);
+ }
+
+ /**
+ * Returns a string representation of this instant.
+ * This is either the date, the indeterminate position (e.g., "now"),
+ * or a combination of both (e.g., "after 2000-01-01").
+ */
+ @Override
+ public String toString() {
+ final var s = new StringBuilder();
+ if (indeterminate != null) {
+ s.append(indeterminate.identifier());
+ if (position != null) {
+ s.append(' ').append(position);
+ }
+ } else {
+ s.append(position); // Should never be null.
+ }
+ return s.toString();
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultPeriod.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultPeriod.java
new file mode 100644
index 0000000000..eb5dd82f5c
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/DefaultPeriod.java
@@ -0,0 +1,107 @@
+/*
+ * 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.temporal;
+
+import java.io.Serializable;
+import java.time.temporal.TemporalAmount;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.Instant;
+import org.opengis.temporal.Period;
+
+
+/**
+ * Default implementation of GeoAPI period.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+final class DefaultPeriod implements Period, Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = 3870895998810224339L;
+
+ /**
+ * Bounds making this period.
+ */
+ @SuppressWarnings("serial") // Default implementations are
serializable.
+ private final Instant beginning, ending;
+
+ /**
+ * Creates a new period with the given bounds.
+ */
+ DefaultPeriod(final Instant beginning, final Instant ending) {
+ this.beginning = beginning;
+ this.ending = ending;
+ }
+
+ /**
+ * Returns the beginning instant at which this period starts.
+ */
+ @Override
+ public Instant getBeginning() {
+ return beginning;
+ }
+
+ /**
+ * Returns the ending instant at which this period ends.
+ */
+ @Override
+ public Instant getEnding() {
+ return ending;
+ }
+
+ /**
+ * Returns the duration of this period.
+ */
+ @Override
+ public TemporalAmount length() {
+ return GeneralDuration.distance(beginning, ending, false, false);
+ }
+
+ /**
+ * Returns a string representation in ISO 8601 format.
+ * The format is {@code <start>/<end>}.
+ */
+ @Override
+ public String toString() {
+ return beginning + "/" + ending;
+ }
+
+ /**
+ * Hash code value of the time position.
+ */
+ @Override
+ public int hashCode() {
+ return beginning.hashCode() + 37 * ending.hashCode();
+ }
+
+ /**
+ * Compares with given object for equality.
+ */
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof DefaultPeriod) {
+ final var other = (DefaultPeriod) obj;
+ return beginning.equals(other.beginning) &&
ending.equals(other.ending);
+ }
+ return false;
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/GeneralDuration.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/GeneralDuration.java
new file mode 100644
index 0000000000..6b9b49ccf7
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/GeneralDuration.java
@@ -0,0 +1,325 @@
+/*
+ * 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.temporal;
+
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.io.Serializable;
+import java.time.Period;
+import java.time.Duration;
+import java.time.LocalTime;
+import java.time.LocalDateTime;
+import java.time.ZonedDateTime;
+import java.time.DateTimeException;
+import java.time.chrono.ChronoLocalDate;
+import java.time.chrono.ChronoPeriod;
+import java.time.temporal.ChronoField;
+import java.time.temporal.ChronoUnit;
+import java.time.temporal.Temporal;
+import java.time.temporal.TemporalAmount;
+import java.time.temporal.TemporalUnit;
+import java.time.temporal.UnsupportedTemporalTypeException;
+import org.apache.sis.pending.jdk.JDK18;
+import org.apache.sis.util.privy.UnmodifiableArrayList;
+import org.apache.sis.util.resources.Errors;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.Instant;
+import org.opengis.temporal.IndeterminateValue;
+import org.opengis.temporal.IndeterminatePositionException;
+
+
+/**
+ * A data type to be used for describing length or distance in the temporal
dimension.
+ * This implementation combine {@link java.time.Period} with {@link
java.time.Duration}
+ * for situation where both of them are needed together (which is not
recommended).
+ *
+ * This class also contains a {@code distance(…)} method for computing the
distance between two ISO 19108 instants.
+ * This is defined here for reducing class loading in the common case where
{@code distance(…)} is not invoked.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ */
+final class GeneralDuration implements TemporalAmount, Serializable {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -521478824158640275L;
+
+ /**
+ * The period in numbers of years, months and days.
+ * Shall be non-null and non-zero.
+ */
+ private final Period period;
+
+ /**
+ * The time part of the period in numbers of hours, minutes and seconds.
+ * Shall be non-null, non-zero and less than one day.
+ */
+ private final Duration time;
+
+ /**
+ * Creates a new instance with the given parts.
+ * The two parts must be non-null and non-zero.
+ *
+ * @param period the period in numbers of years, months and days.
+ * @param time the time part of the period in numbers of hours,
minutes and seconds.
+ */
+ private GeneralDuration(final Period period, final Duration time) {
+ this.period = period;
+ this.time = time;
+ }
+
+ /**
+ * Returns the temporal position of the given instant if that position is
determinate or is "now".
+ * Otherwise, throws an exception. If the position is "now", then this
method returns {@code null}
+ * instead of fetching the current time in order to avoid mismatch when
comparing two "now" values
+ * that are a few nanoseconds apart.
+ *
+ * @param t the instant for which to get the temporal position, or
{@code null}.
+ * @return temporal position of the given instant, or {@code null} for
"now".
+ * @throws DateTimeException if the given instant is null or its position
is indeterminate.
+ */
+ private static Temporal getDeterminatePosition(final Instant t) {
+ if (t != null) {
+ final Optional<IndeterminateValue> p =
t.getIndeterminatePosition();
+ if (p.isEmpty()) {
+ return t.getPosition();
+ }
+ if (p.get() == IndeterminateValue.NOW) {
+ return null; // Avoid fetching the current time now.
+ }
+ }
+ throw new
IndeterminatePositionException(Errors.format(Errors.Keys.IndeterminatePosition));
+ }
+
+ /**
+ * Returns the distance between the two given ISO 19108 instants.
+ * If the result is negative, then the return value depends on the {@code
absolute} argument:
+ * If {@code true}, this method returns the absolute value. Otherwise, it
returns {@code null}.
+ *
+ * <p>If everything else is equal, methods such as {@link
ChronoLocalDate#until(ChronoLocalDate)}
+ * will be invoked on the {@code self} instance. It makes a difference in
the type of the result.
+ * For computing a duration with arguments in the reverse order, the
{@code negate} parameter can
+ * be set to {@code true}.</p>
+ *
+ * @param self the first instant from which to measure the distance.
+ * @param other the second instant from which to measure the distance.
+ * @param negate whether to negate the result. True for duration from
{@code other} to {@code self}.
+ * @param absolute whether to return absolute value. If false, negative
result is replaced by null.
+ * @return the distance, or {@code null} if the result is negative and
{@code absolute} is false.
+ * @throws DateTimeException if the duration cannot be computed.
+ * @throws ArithmeticException if the calculation exceeds the integer
capacity.
+ */
+ static TemporalAmount distance(final Instant self, final Instant other,
final boolean negate, final boolean absolute) {
+ /*
+ * Get the temporal value, or null if "now". Other indeterminate
values cause an exception to be thrown.
+ * We use null for "now" instead of fetching the current time for two
reasons: avoid mismatch by a few
+ * nanoseconds when comparing `t1` with `t2`, and for choosing a type
compatible with the other instant.
+ */
+ Temporal t1 = getDeterminatePosition(self);
+ Temporal t2 = getDeterminatePosition(other);
+ if (Objects.equals(t1, t2)) {
+ return Duration.ZERO;
+ }
+ /*
+ * Ensures that the given objects both have a date part, or that none
of them have a date part.
+ * Note that the "epoch day" field is supported by `LocalDate` as well
as the dates with zone ID.
+ */
+ boolean hasDate = isSupportedByBoth(ChronoField.EPOCH_DAY, t1, t2);
+ /*
+ * If at least one date has a timezone, then we require that both
dates have a timezone.
+ * It allows an unambiguous duration in number of days, without
time-varying months or years.
+ * If one date has a timezone and the other does not, a
`DateTimeException` will be thrown.
+ *
+ * Note 1: we could be lenient and handle the two dates as if they
were local, ignoring the timezone.
+ * But we avoid false sense of accuracy for now. We may revisit this
policy later if there is a need.
+ */
+ if (t1 != null && t1.isSupported(ChronoField.OFFSET_SECONDS)) {
+ if (t2 == null) t2 = ZonedDateTime.now();
+ final Duration p = Duration.between(t1, t2);
+ return (absolute || p.isNegative() == negate) ? p.abs() : null;
+ }
+ if (t2 != null && (!hasDate ||
t2.isSupported(ChronoField.OFFSET_SECONDS))) {
+ if (t1 == null) t1 = ZonedDateTime.now();
+ final Duration p = Duration.between(t2, t1); // Negative of
the result.
+ return (absolute || p.isNegative() != negate) ? p.abs() : null;
+ }
+ /*
+ * Ensure that the given temporal objects both have a time part, or
none of them have a time part.
+ * If only one of them has a time part, we do not interpret the other
one as an instant at midnight
+ * in order to avoid false sense of accuracy.
+ */
+ final boolean hasTime = isSupportedByBoth(ChronoField.SECOND_OF_DAY,
t1, t2);
+ if (t1 == null) t1 = LocalDateTime.now();
+ if (t2 == null) t2 = LocalDateTime.now();
+ ChronoLocalDate d1 = null, d2 = null;
+ if (hasDate) {
+ d1 = ChronoLocalDate.from(t1);
+ d2 = ChronoLocalDate.from(t2);
+ if (!absolute && (negate ? d1.isBefore(d2) : d1.isAfter(d2))) {
+ return null; // Stop early if we can.
+ }
+ hasDate = !d1.isEqual(d2);
+ }
+ /*
+ * Compute the duration in the time part. If negative (after negation
if `negate` is true),
+ * then we add the necessary number of days to make it positive and
remove the same number
+ * of days from the date. We adjust the date instead of the period
computed by `d1.until(d2)`
+ * in order to have the correct adjustment for the variable number of
days in each month.
+ */
+ Duration time = Duration.ZERO;
+ if (hasTime) {
+ time = Duration.between(LocalTime.from(t1), LocalTime.from(t2));
+ if (hasDate) {
+ if (negate ? JDK18.isPositive(time) : time.isNegative()) {
+ long n = time.toDays(); // Truncated
toward 0.
+ if (negate) {
+ d1 = d1.plus(++n, ChronoUnit.DAYS); // `n` is
positive. Reduces period by increasing the beginning.
+ } else {
+ d2 = d2.plus(--n, ChronoUnit.DAYS); // `n` is
negative. Reduces period by decreasing the ending.
+ }
+ time = time.minusDays(n); // If
negative, make positive. If positive, make negative.
+ }
+ }
+ }
+ /*
+ * Get the period for the date part, then combine with the time part
if non-zero.
+ * The result shall be either positive or null.
+ */
+ if (hasDate) {
+ ChronoPeriod period = d1.until(d2);
+ if (!period.isZero()) {
+ if (period.isNegative()) {
+ if (!(negate | absolute)) { // Equivalent
to (!negate && !absolute).
+ return null;
+ }
+ period = period.negated();
+ } else if (negate & !absolute) { // Equivalent
to (negate && !absolute).
+ return null;
+ }
+ return time.isZero() ? period : new
GeneralDuration(Period.from(period), time.abs());
+ }
+ }
+ return (absolute || time.isNegative() == negate) ? time.abs() : null;
+ }
+
+ /**
+ * Verifies if the given field is supported by both temporal objects.
+ * Either the field is supported by both objects, or either it is
supported by none of them.
+ * If one object support the field and the other does not, the two objects
are considered incompatible.
+ * At least one of the given objects shall be non-null.
+ *
+ * @param field the field to test.
+ * @param t1 the first temporal object, or {@code null} for "now".
+ * @param t2 the second temporal object, or {@code null} for "now".
+ * @return whether the given object is supported.
+ * @throws DateTimeException if the two objects are incompatible.
+ */
+ private static boolean isSupportedByBoth(final ChronoField field, final
Temporal t1, final Temporal t2) {
+ final boolean isSupported = (t1 != null ? t1 : t2).isSupported(field);
+ if (t1 != null && t2 != null && isSupported != t2.isSupported(field)) {
+ throw new
DateTimeException(Errors.format(Errors.Keys.CanNotConvertFromType_2,
+ (isSupported ? t2 : t1).getClass(),
+ (isSupported ? t1 : t2).getClass()));
+ }
+ return isSupported;
+ }
+
+ /**
+ * Returns the list of units that are supported by this implementation.
+ * This is the union of the units supported by the date part and by the
time part.
+ */
+ @Override
+ public List<TemporalUnit> getUnits() {
+ var prefix = period.getUnits();
+ var suffix = time.getUnits();
+ int i = prefix.size();
+ var units = prefix.toArray(new TemporalUnit[i + suffix.size()]);
+ for (TemporalUnit unit : suffix) {
+ units[i++] = unit;
+ }
+ return UnmodifiableArrayList.wrap(units);
+ }
+
+ /**
+ * Returns the value of the requested unit.
+ *
+ * @param unit the unit to get;
+ * @return value of the specified unit.
+ * @throws UnsupportedTemporalTypeException if the {@code unit} is not
supported.
+ */
+ @Override
+ public long get(final TemporalUnit unit) {
+ return (unit.isDateBased() ? period : time).get(unit);
+ }
+
+ /**
+ * Adds this duration to the specified temporal object.
+ *
+ * @param temporal the temporal object to add the amount to.
+ * @return an object with the addition done.
+ */
+ @Override
+ public Temporal addTo(Temporal temporal) {
+ return temporal.plus(period).plus(time);
+ }
+
+ /**
+ * Subtracts this duration from the specified temporal object.
+ *
+ * @param temporal the temporal object to subtract the amount from.
+ * @return an object with the subtraction done.
+ */
+ @Override
+ public Temporal subtractFrom(Temporal temporal) {
+ return temporal.minus(period).minus(time);
+ }
+
+ /**
+ * Compares this duration with the given object for equality.
+ *
+ * @param object the object to compare with this duration.
+ * @return whether the two objects are equal.
+ */
+ @Override
+ public boolean equals(final Object object) {
+ if (object instanceof GeneralDuration) {
+ final var other = (GeneralDuration) object;
+ return period.equals(other.period) && time.equals(other.time);
+ }
+ return false;
+ }
+
+ /**
+ * Returns a hash code value for this duration.
+ *
+ * @return a hash code value for this duration.
+ */
+ @Override
+ public int hashCode() {
+ return period.hashCode() * 31 + time.hashCode();
+ }
+
+ /**
+ * Returns this duration in ISO 8601 format.
+ */
+ @Override
+ public String toString() {
+ return period.toString() + time.toString().substring(1);
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/StandardDateFormat.java
similarity index 99%
rename from
endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
rename to
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/StandardDateFormat.java
index 6c4ee5e27f..ce58461976 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/StandardDateFormat.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.util.privy;
+package org.apache.sis.temporal;
import java.util.Calendar;
import java.util.Date;
@@ -42,6 +42,7 @@ import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.format.SignStyle;
import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.privy.Constants;
/**
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalDate.java
similarity index 86%
rename from
endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
rename to
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalDate.java
index 495237bbb7..86aa1a6259 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalDate.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.util.privy;
+package org.apache.sis.temporal;
import java.util.Date;
import java.time.DateTimeException;
@@ -23,10 +23,8 @@ import java.time.LocalTime;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
-import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
-import java.time.ZonedDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAccessor;
@@ -34,6 +32,7 @@ import java.time.chrono.ChronoZonedDateTime;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.LenientComparable;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.privy.Constants;
/**
@@ -198,39 +197,6 @@ public final class TemporalDate extends Date implements
LenientComparable {
return time.plusSeconds(r).plusNanos(Math.round((value - r) *
Constants.NANOS_PER_SECOND));
}
- /**
- * Returns {@code true} if objects of the given class have day, month and
hour fields.
- * This method is defined here for having a single class where to
concentrate such heuristic rules.
- * Note that {@link Instant} does not have date fields.
- *
- * @param date class of object to test (may be {@code null}).
- * @return whether the given class is {@link LocalDate} or one of the
classes with date + time.
- * This list may be expanded in future versions.
- */
- public static boolean hasDateFields(final Class<?> date) {
- return date == LocalDate.class
- || date == LocalDateTime.class
- || date == OffsetDateTime.class
- || date == ZonedDateTime.class;
- }
-
- /**
- * Returns {@code true} if objects of the given class have time fields.
- * This method is defined here for having a single class where to
concentrate such heuristic rules.
- * Note that {@link Instant} does not have hour fields.
- *
- * @param date class of object to test (may be {@code null}).
- * @return whether the given class is {@link LocalTime}, {@link
OffsetTime} or one of the classes with date + time.
- * This list may be expanded in future versions.
- */
- public static boolean hasTimeFields(final Class<?> date) {
- return date == LocalTime.class
- || date == OffsetTime.class
- || date == LocalDateTime.class
- || date == OffsetDateTime.class
- || date == ZonedDateTime.class;
- }
-
/**
* Compares two temporal objects that may not be of the same type.
* First, this method tries to compare the positions on the timeline.
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalUtilities.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalUtilities.java
new file mode 100644
index 0000000000..250fa7ef56
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/TemporalUtilities.java
@@ -0,0 +1,102 @@
+/*
+ * 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.temporal;
+
+import java.util.Date;
+import java.time.temporal.Temporal;
+import org.opengis.temporal.TemporalPrimitive;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.IndeterminateValue;
+import org.opengis.temporal.Instant;
+import org.opengis.temporal.Period;
+
+
+/**
+ * Utilities related to ISO 19108 objects.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @author Guilhem Legal (Geomatys)
+ */
+public final class TemporalUtilities {
+ /**
+ * Do not allow instantiation of this class.
+ */
+ private TemporalUtilities() {
+ }
+
+ /**
+ * Creates an instant for the given Java temporal instant.
+ *
+ * @param time the date for which to create instant, or {@code null}.
+ * @return the instant, or an unknown instant if the given time was null.
+ */
+ public static Instant createInstant(final Temporal time) {
+ return new DefaultInstant(time, (time != null) ? null :
IndeterminateValue.UNKNOWN);
+ }
+
+ /**
+ * Creates a period for the given begin and end instant.
+ *
+ * @param beginning the begin instant (inclusive), or {@code null}.
+ * @param ending the end instant (exclusive), or {@code null}.
+ * @return the period, or {@code null} if both arguments are null.
+ */
+ public static Period createPeriod(final Temporal beginning, final Temporal
ending) {
+ if (beginning == null && ending == null) {
+ return null;
+ }
+ return new DefaultPeriod(createInstant(beginning),
createInstant(ending));
+ }
+
+ /**
+ * Returns the given value as a temporal position, or {@code null} if not
available.
+ *
+ * @param time the instant or period for which to get a date, or {@code
null}.
+ * @return the temporal position, or {@code null} if indeterminate.
+ */
+ public static Temporal getInstant(final TemporalPrimitive time) {
+ if (time instanceof Instant) {
+ return ((Instant) time).getPosition();
+ }
+ return null;
+ }
+
+ /**
+ * Infers a value from the instant or extent as a {@link Date} object.
+ * This method is used for compatibility with legacy API and may disappear
in future SIS version.
+ *
+ * @param time the instant or period for which to get a date, or {@code
null}.
+ * @return the requested time as a Java date, or {@code null} if none.
+ */
+ public static Date getAnyDate(final TemporalPrimitive time) {
+ Temporal t = null;
+ if (time instanceof Instant) {
+ t = ((Instant) time).getPosition();
+ } else if (time instanceof Period) {
+ final var p = (Period) time;
+ Instant i = p.getEnding(); // Should never be null, but we
are paranoiac.
+ if (i == null || (t = i.getPosition()) == null) {
+ i = p.getBeginning();
+ if (i != null) {
+ t = i.getPosition();
+ }
+ }
+ }
+ return TemporalDate.toDate(t);
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/package-info.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/package-info.java
similarity index 70%
rename from
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/package-info.java
rename to
endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/package-info.java
index bc684a2a97..d6e0dce1ee 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/pending/temporal/package-info.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/package-info.java
@@ -16,11 +16,10 @@
*/
/**
- * Place-holder for a future implementation of {@code org.opengis.temporal}
interfaces.
- * Those interfaces should be derived from ISO 19108, but they overlap with
{@code java.time} standard API.
- * Furthermore, the ISO 19108 standard also overlaps with ISO 19111. How to
resolve those overlaps has not
- * yet been decided.
+ * Implementation of {@code org.opengis.temporal} interfaces.
+ * Contains also utility methods related to {@code java.time}.
+ * This package is for internal use by Apache SIS only.
*
* @author Martin Desruisseaux (Geomatys)
*/
-package org.apache.sis.pending.temporal;
+package org.apache.sis.temporal;
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TM_Primitive.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TM_Primitive.java
index 4596c8becb..8b5eff28bc 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TM_Primitive.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TM_Primitive.java
@@ -23,7 +23,7 @@ import org.opengis.temporal.TemporalPrimitive;
import org.apache.sis.xml.privy.XmlUtilities;
import org.apache.sis.xml.bind.Context;
import org.apache.sis.xml.bind.gco.PropertyType;
-import org.apache.sis.pending.temporal.TemporalUtilities;
+import org.apache.sis.temporal.TemporalUtilities;
import org.apache.sis.util.resources.Errors;
// Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -82,8 +82,10 @@ public class TM_Primitive extends PropertyType<TM_Primitive,
TemporalPrimitive>
*/
@XmlElement(name = "TimePeriod")
public final TimePeriod getTimePeriod() {
- Period period = TemporalUtilities.getPeriod(metadata);
- return (period != null) ? new TimePeriod(period) : null;
+ if (metadata instanceof Period) {
+ return new TimePeriod((Period) metadata);
+ }
+ return null;
}
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TimePeriodBound.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TimePeriodBound.java
index ab2ee6fb11..5b51345ec5 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TimePeriodBound.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/TimePeriodBound.java
@@ -16,13 +16,15 @@
*/
package org.apache.sis.xml.bind.gml;
-import java.time.temporal.Temporal;
import javax.xml.datatype.XMLGregorianCalendar;
import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlTransient;
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.Instant;
+
/**
* The {@linkplain TimePeriod#begin begin} or {@linkplain TimePeriod#end end}
position in
@@ -98,9 +100,14 @@ public abstract class TimePeriodBound {
* @param instant the instant of the new bound, or {@code null}.
* @param indeterminate the value to give to {@link
#indeterminatePosition} if the date is null.
*/
- GML3(final Temporal instant, final String indeterminate) {
- value = TimeInstant.toXML(instant);
- if (value == null) {
+ GML3(final Instant instant, final String indeterminate) {
+ if (instant != null) {
+ value = TimeInstant.toXML(instant.getPosition());
+ if (value == null) {
+ instant.getIndeterminatePosition().ifPresent((p) ->
indeterminatePosition = p.identifier());
+ }
+ }
+ if (value == null && indeterminatePosition == null) {
indeterminatePosition = indeterminate;
}
}
@@ -154,8 +161,8 @@ public abstract class TimePeriodBound {
*
* @param instant The instant of the new bound, or {@code null}.
*/
- GML2(final Temporal instant) {
- timeInstant = new TimeInstant(instant);
+ GML2(final Instant instant) {
+ timeInstant = new TimeInstant((instant != null) ?
instant.getPosition() : null);
}
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/privy/XmlUtilities.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/privy/XmlUtilities.java
index 2806f5d462..5fb093eaf8 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/privy/XmlUtilities.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/privy/XmlUtilities.java
@@ -48,7 +48,7 @@ import static
javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED;
import org.apache.sis.system.SystemListener;
import org.apache.sis.system.Modules;
import org.apache.sis.xml.bind.Context;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/DefaultCitationDateTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/DefaultCitationDateTest.java
index 92fa66b8ac..55e52af59c 100644
---
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/DefaultCitationDateTest.java
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/metadata/iso/citation/DefaultCitationDateTest.java
@@ -47,14 +47,14 @@ public final class DefaultCitationDateTest extends TestCase
{
*/
@Test
public void testCopyConstructor() {
- final CitationDate original = new CitationDate() {
+ final var original = new CitationDate() {
@Override public Temporal getReferenceDate() {return
Instant.ofEpochMilli(1305716658508L);}
@Override public DateType getDateType() {return
DateType.CREATION;}
};
- final DefaultCitationDate copy = new DefaultCitationDate(original);
+ final var copy = new DefaultCitationDate(original);
assertEquals(Instant.ofEpochMilli(1305716658508L),
copy.getReferenceDate());
assertEquals(DateType.CREATION, copy.getDateType());
- assertTrue (copy.equals(original, ComparisonMode.BY_CONTRACT));
- assertFalse(copy.equals(original, ComparisonMode.STRICT)); //
Opportunist test.
+ assertTrue (copy.equals(original, ComparisonMode.DEBUG));
+ assertFalse(copy.equals(original, ComparisonMode.STRICT)); //
Opportunist test.
}
}
diff --git
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultInstantTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultInstantTest.java
new file mode 100644
index 0000000000..d175036219
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultInstantTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.temporal;
+
+import java.time.LocalDate;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+import org.opengis.temporal.IndeterminateValue;
+
+// Test dependencies
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+import org.apache.sis.test.TestCase;
+
+
+/**
+ * Tests the {@link DefaultInstant} class.
+ *
+ * @author Mehdi Sidhoum (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
+ */
+public final class DefaultInstantTest extends TestCase {
+ /**
+ * Creates a new test case.
+ */
+ public DefaultInstantTest() {
+ }
+
+ /**
+ * Tests {@link DefaultInstant#getPosition()}.
+ * Opportunistically tests {@link
TemporalUtilities#createInstant(Temporal)} too.
+ */
+ @Test
+ public void testGetPosition() {
+ var date = LocalDate.of(2010, 5, 1);
+ var instant = TemporalUtilities.createInstant(date);
+ assertEquals(date, instant.getPosition());
+ }
+
+ /**
+ * Test of equals and hash code methods.
+ */
+ @Test
+ public void testEquals() {
+ var instant1 = new DefaultInstant(LocalDate.of(2000, 1, 1), null);
+ var instant2 = new DefaultInstant(LocalDate.of(1988, 1, 1), null);
+ var instant3 = new DefaultInstant(LocalDate.of(1988, 1, 1), null);
+
+ assertNotEquals(instant1, instant2);
+ assertNotEquals(instant1.hashCode(), instant2.hashCode());
+
+ assertEquals(instant3, instant2);
+ assertEquals(instant3.hashCode(), instant2.hashCode());
+ }
+
+ /**
+ * Tests {@link DefaultInstant#toString()}.
+ */
+ @Test
+ public void testToString() {
+ var date = LocalDate.of(2010, 5, 1);
+ assertEquals("2010-05-01", new DefaultInstant(date, null).toString());
+ assertEquals("after 2010-05-01", new DefaultInstant(date,
IndeterminateValue.AFTER).toString());
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultPeriodTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultPeriodTest.java
new file mode 100644
index 0000000000..6ea04f0a11
--- /dev/null
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/DefaultPeriodTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.temporal;
+
+import java.time.LocalDate;
+
+// Specific to the geoapi-3.1 and geoapi-4.0 branches:
+
+// Test dependencies
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+import org.apache.sis.test.TestCase;
+
+
+/**
+ * Tests the {@link DefaultPeriod} class.
+ *
+ * @author Mehdi Sidhoum (Geomatys)
+ * @author Martin Desruisseaux (Geomatys)
+ */
+public final class DefaultPeriodTest extends TestCase {
+ /**
+ * Creates a new test case.
+ */
+ public DefaultPeriodTest() {
+ }
+
+ /**
+ * Tests {@link DefaultPeriod#getBeginning()} and {@link
DefaultPeriod#getEnding()}.
+ * Opportunistically tests {@link TemporalUtilities#createPeriod(Temporal,
Temporal)} too.
+ */
+ @Test
+ public void testBounds() {
+ var beginning = LocalDate.of(2010, 5, 1);
+ var ending = LocalDate.of(2015, 8, 6);
+ var period = TemporalUtilities.createPeriod(beginning, ending);
+ assertEquals(beginning, period.getBeginning().getPosition());
+ assertEquals(ending, period.getEnding().getPosition());
+ }
+
+ /**
+ * Test of equals and hash code methods.
+ */
+ @Test
+ public void testEquals() {
+ var p1 = TemporalUtilities.createPeriod(LocalDate.of(2000, 1, 1),
LocalDate.of(2010, 1, 1));
+ var p2 = TemporalUtilities.createPeriod(LocalDate.of(1988, 1, 1),
LocalDate.of(2010, 1, 1));
+ var p3 = TemporalUtilities.createPeriod(LocalDate.of(1988, 1, 1),
LocalDate.of(2010, 1, 1));
+
+ assertNotEquals(p1, p2);
+ assertNotEquals(p1.hashCode(), p2.hashCode());
+
+ assertEquals(p3, p2);
+ assertEquals(p3.hashCode(), p2.hashCode());
+ }
+
+ /**
+ * Tests {@link DefaultPeriod#toString()}.
+ */
+ @Test
+ public void testToString() {
+ var p1 = TemporalUtilities.createPeriod(LocalDate.of(2000, 1, 1),
LocalDate.of(2010, 1, 1));
+ assertEquals("2000-01-01/2010-01-01", p1.toString());
+ }
+}
diff --git
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/StandardDateFormatTest.java
similarity index 99%
rename from
endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
rename to
endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/StandardDateFormatTest.java
index d20a8c7adf..01e4489973 100644
---
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/temporal/StandardDateFormatTest.java
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.sis.util.privy;
+package org.apache.sis.temporal;
import java.time.Instant;
import java.time.LocalDate;
diff --git
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/gml/TimePeriodTest.java
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/gml/TimePeriodTest.java
index 667ae3cd1a..9934516095 100644
---
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/gml/TimePeriodTest.java
+++
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/gml/TimePeriodTest.java
@@ -30,6 +30,7 @@ import org.apache.sis.xml.XML;
import org.apache.sis.xml.Namespaces;
import org.apache.sis.xml.MarshallerPool;
import org.apache.sis.xml.privy.XmlUtilities;
+import org.apache.sis.temporal.TemporalUtilities;
// Test dependencies
import org.junit.jupiter.api.Test;
@@ -108,8 +109,8 @@ public final class TimePeriodTest extends TestCase {
@Test
public void testPeriodGML2() throws JAXBException {
createContext();
- final var begin = new
TimePeriodBound.GML2(Instant.parse("1992-01-01T00:00:00Z"));
- final var end = new
TimePeriodBound.GML2(Instant.parse("2007-12-31T00:00:00Z"));
+ final var begin = new
TimePeriodBound.GML2(TemporalUtilities.createInstant(Instant.parse("1992-01-01T00:00:00Z")));
+ final var end = new
TimePeriodBound.GML2(TemporalUtilities.createInstant(Instant.parse("2007-12-31T00:00:00Z")));
testPeriod(begin, end,
"<gml:TimePeriod xmlns:gml=\"" + Namespaces.GML + "\">\n" +
" <gml:begin>\n" +
@@ -160,8 +161,8 @@ public final class TimePeriodTest extends TestCase {
@Test
public void testPeriodGML3() throws JAXBException {
createContext();
- final var begin = new
TimePeriodBound.GML3(Instant.parse("1992-01-01T00:00:00Z"), "before");
- final var end = new
TimePeriodBound.GML3(Instant.parse("2007-12-31T00:00:00Z"), "after");
+ final var begin = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(Instant.parse("1992-01-01T00:00:00Z")),
"before");
+ final var end = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(Instant.parse("2007-12-31T00:00:00Z")),
"after");
testPeriod(begin, end,
"<gml:TimePeriod xmlns:gml=\"" + Namespaces.GML + "\">\n" +
"
<gml:beginPosition>1992-01-01T01:00:00+01:00</gml:beginPosition>\n" +
@@ -178,8 +179,8 @@ public final class TimePeriodTest extends TestCase {
@Test
public void testSimplifiedPeriodGML3() throws JAXBException {
createContext();
- final var begin = new TimePeriodBound.GML3(LocalDate.of(1992, 1, 2),
"before");
- final var end = new TimePeriodBound.GML3(LocalDate.of(2007, 12, 31),
"after");
+ final var begin = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(LocalDate.of(1992, 1,
2)), "before");
+ final var end = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(LocalDate.of(2007, 12,
31)), "after");
testPeriod(begin, end,
"<gml:TimePeriod xmlns:gml=\"" + Namespaces.GML + "\">\n" +
" <gml:beginPosition>1992-01-02</gml:beginPosition>\n" +
@@ -197,7 +198,7 @@ public final class TimePeriodTest extends TestCase {
public void testBeforePeriodGML3() throws JAXBException {
createContext();
final var begin = new TimePeriodBound.GML3(null, "before");
- final var end = new TimePeriodBound.GML3(LocalDate.of(2007, 12, 31),
"after");
+ final var end = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(LocalDate.of(2007, 12,
31)), "after");
testPeriod(begin, end,
"<gml:TimePeriod xmlns:gml=\"" + Namespaces.GML + "\">\n" +
" <gml:beginPosition indeterminatePosition=\"before\"/>\n" +
@@ -214,7 +215,7 @@ public final class TimePeriodTest extends TestCase {
@Test
public void testAfterPeriodGML3() throws JAXBException {
createContext();
- final var begin = new TimePeriodBound.GML3(LocalDate.of(1992, 1, 2),
"before");
+ final var begin = new
TimePeriodBound.GML3(TemporalUtilities.createInstant(LocalDate.of(1992, 1, 2)),
"before");
final var end = new TimePeriodBound.GML3(null, "after");
testPeriod(begin, end,
"<gml:TimePeriod xmlns:gml=\"" + Namespaces.GML + "\">\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/CoordinateFormat.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/CoordinateFormat.java
index efc89b49e2..7ffd22a0b4 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/CoordinateFormat.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/geometry/CoordinateFormat.java
@@ -59,13 +59,13 @@ import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.Characters;
import org.apache.sis.util.privy.LocalizedParseException;
-import org.apache.sis.util.privy.TemporalDate;
import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.privy.Numerics;
import org.apache.sis.math.DecimalFunctions;
import org.apache.sis.math.MathFunctions;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.measure.Angle;
import org.apache.sis.measure.AngleFormat;
import org.apache.sis.measure.Latitude;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
index 63087a09c4..b4c8de9054 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/AbstractParser.java
@@ -37,7 +37,7 @@ import org.opengis.util.InternationalString;
import org.apache.sis.system.Loggers;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.measure.Units;
import org.apache.sis.measure.UnitFormat;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
index 7fa79fc822..4fa4993c0d 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
@@ -72,8 +72,8 @@ import org.apache.sis.util.collection.IntegerList;
import org.apache.sis.util.privy.X364;
import org.apache.sis.util.privy.Numerics;
import org.apache.sis.util.privy.Constants;
-import org.apache.sis.util.privy.TemporalDate;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.TemporalDate;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.system.Configuration;
import org.apache.sis.metadata.simple.SimpleExtent;
import org.apache.sis.metadata.iso.extent.Extents;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
index f95fd49678..e8cb817f10 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
@@ -54,9 +54,9 @@ import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.OptionalCandidate;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.system.Loggers;
import org.apache.sis.util.privy.Constants;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.system.Loggers;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.referencing.ImmutableIdentifier;
import org.apache.sis.referencing.privy.ReferencingFactoryContainer;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
index 917dcaaebc..5e730428f7 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/AbstractDatum.java
@@ -35,7 +35,7 @@ import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.iso.Types;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.metadata.privy.Identifiers;
import org.apache.sis.metadata.privy.NameToIdentifier;
import org.apache.sis.metadata.privy.ImplementationHelper;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
index 7343d3db34..71296d4885 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
@@ -92,9 +92,9 @@ import org.apache.sis.util.Workaround;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.StandardDateFormat;
import org.apache.sis.util.privy.Strings;
import org.apache.sis.util.privy.URLs;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.metadata.iso.citation.DefaultCitation;
import org.apache.sis.metadata.iso.citation.DefaultOnlineResource;
import org.apache.sis.metadata.iso.extent.DefaultExtent;
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ExtentSelector.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ExtentSelector.java
index d9c7155512..ea947ae67b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ExtentSelector.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/ExtentSelector.java
@@ -27,8 +27,8 @@ import org.apache.sis.metadata.iso.extent.Extents;
import org.apache.sis.math.MathFunctions;
import org.apache.sis.measure.Range;
import org.apache.sis.util.resources.Errors;
-import org.apache.sis.util.privy.TemporalDate;
import org.apache.sis.util.privy.Constants;
+import org.apache.sis.temporal.TemporalDate;
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
index 949b1c0a2d..b933292c8f 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/test/integration/MetadataVerticalTest.java
@@ -39,7 +39,7 @@ import org.opengis.referencing.datum.VerticalDatum;
import org.apache.sis.system.Loggers;
import org.apache.sis.xml.NilObject;
import org.apache.sis.xml.NilReason;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
// Test dependencies
import org.junit.jupiter.api.Test;
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/XMLMetadata.java
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/XMLMetadata.java
index 87fa31eaba..9c34f8352d 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/XMLMetadata.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/main/org/apache/sis/storage/geotiff/reader/XMLMetadata.java
@@ -40,7 +40,7 @@ import javax.xml.transform.stax.StAXSource;
import javax.xml.namespace.QName;
import jakarta.xml.bind.JAXBException;
import org.apache.sis.io.stream.ChannelDataInput;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.storage.base.MetadataBuilder;
import org.apache.sis.storage.event.StoreListeners;
import org.apache.sis.storage.geotiff.base.Tags;
diff --git
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/reader/XMLMetadataTest.java
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/reader/XMLMetadataTest.java
index ea8bf109af..53ec6be1af 100644
---
a/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/reader/XMLMetadataTest.java
+++
b/endorsed/src/org.apache.sis.storage.geotiff/test/org/apache/sis/storage/geotiff/reader/XMLMetadataTest.java
@@ -138,7 +138,7 @@ public final class XMLMetadataTest extends TestCase {
" ├─Citation……………………………… My image\n" +
" └─Extent\n" +
" └─Temporal element\n" +
- " └─Extent……………… [2018-02-28T03:48:00Z …
2018-02-28T04:04:00Z]\n",
+ " └─Extent………………
2018-02-28T03:48:00Z/2018-02-28T04:04:00Z\n",
metadata.toString());
}
@@ -158,7 +158,7 @@ public final class XMLMetadataTest extends TestCase {
" └─Identification info\n" +
" └─Extent\n" +
" └─Temporal element\n" +
- " └─Extent……………… [2018-02-28T03:04Z …
2018-02-28T04:48Z]\n",
+ " └─Extent………………
2018-02-28T03:04Z/2018-02-28T04:48Z\n",
metadata.toString());
}
}
diff --git
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
index 850a2606d5..44f971a890 100644
---
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
+++
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/ChannelDecoder.java
@@ -58,12 +58,12 @@ import org.apache.sis.io.stream.ChannelDataInput;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.privy.Constants;
import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.StandardDateFormat;
-import org.apache.sis.util.privy.TemporalDate;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.resources.Vocabulary;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.collection.TableColumn;
+import org.apache.sis.temporal.StandardDateFormat;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.setup.GeometryLibrary;
import org.apache.sis.measure.Units;
import org.apache.sis.math.Vector;
diff --git
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/VariableInfo.java
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/VariableInfo.java
index a64cdfe017..3604d9344a 100644
---
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/VariableInfo.java
+++
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/classic/VariableInfo.java
@@ -50,11 +50,11 @@ import org.apache.sis.io.stream.Region;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.Classes;
-import org.apache.sis.util.privy.StandardDateFormat;
import org.apache.sis.util.privy.UnmodifiableArrayList;
import org.apache.sis.util.collection.TableColumn;
import org.apache.sis.util.collection.TreeTable;
import org.apache.sis.util.resources.Errors;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.measure.Units;
import org.apache.sis.math.Vector;
diff --git
a/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java
b/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java
index cb57b2828f..8bb79e7d3d 100644
---
a/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java
+++
b/endorsed/src/org.apache.sis.storage.netcdf/test/org/apache/sis/storage/netcdf/base/TestCase.java
@@ -31,7 +31,7 @@ import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreMock;
import org.apache.sis.storage.event.StoreListeners;
import org.apache.sis.storage.netcdf.ucar.DecoderWrapper;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.setup.GeometryLibrary;
// Test dependencies
diff --git
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
index 9186fcc28c..998733e41d 100644
---
a/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
+++
b/endorsed/src/org.apache.sis.storage.xml/main/org/apache/sis/storage/xml/stream/StaxStreamReader.java
@@ -40,8 +40,8 @@ import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import org.apache.sis.xml.bind.Context;
import org.apache.sis.util.privy.Strings;
-import org.apache.sis.util.privy.StandardDateFormat;
import org.apache.sis.io.stream.IOUtilities;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreContentException;
import org.apache.sis.util.collection.BackingStoreException;
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java
index 3c2685401a..89eca3c4cf 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/Store.java
@@ -52,7 +52,7 @@ import org.apache.sis.util.ArraysExt;
import org.apache.sis.util.CharSequences;
import org.apache.sis.util.privy.UnmodifiableArrayList;
import org.apache.sis.util.privy.Numerics;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.StandardDateFormat;
import org.apache.sis.storage.DataOptionKey;
import org.apache.sis.storage.DataStoreException;
import org.apache.sis.storage.DataStoreContentException;
diff --git
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/TimeEncoding.java
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/TimeEncoding.java
index 1571c6b88b..b8ecf2b5f9 100644
---
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/TimeEncoding.java
+++
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/csv/TimeEncoding.java
@@ -22,8 +22,8 @@ import javax.measure.Unit;
import javax.measure.quantity.Time;
import org.opengis.referencing.datum.TemporalDatum;
import org.apache.sis.converter.SurjectiveConverter;
-import org.apache.sis.util.privy.StandardDateFormat;
-import org.apache.sis.util.privy.TemporalDate;
+import org.apache.sis.temporal.StandardDateFormat;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.measure.Units;
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/RangeFormat.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/RangeFormat.java
index 30f8441fd2..24326f7b41 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/RangeFormat.java
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/RangeFormat.java
@@ -35,6 +35,12 @@ import java.text.ParsePosition;
import java.time.Instant;
import java.time.format.FormatStyle;
import java.time.format.DateTimeFormatterBuilder;
+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.temporal.Temporal;
import java.lang.reflect.InaccessibleObjectException;
import javax.measure.Unit;
@@ -43,7 +49,6 @@ import org.apache.sis.util.Localized;
import org.apache.sis.util.UnconvertibleObjectException;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.privy.LocalizedParseException;
-import org.apache.sis.util.privy.TemporalDate;
import org.apache.sis.util.privy.Numerics;
@@ -362,8 +367,8 @@ public class RangeFormat extends Format implements
Localized {
elementFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT,
DateFormat.SHORT, locale);
unitFormat = null;
} else if (Temporal.class.isAssignableFrom(elementType)) {
- final FormatStyle dateStyle =
TemporalDate.hasDateFields(elementType) ? FormatStyle.SHORT : null;
- final FormatStyle timeStyle =
TemporalDate.hasTimeFields(elementType) ? FormatStyle.SHORT : null;
+ final FormatStyle dateStyle = hasDateFields(elementType) ?
FormatStyle.SHORT : null;
+ final FormatStyle timeStyle = hasTimeFields(elementType) ?
FormatStyle.SHORT : null;
elementFormat = new
DateTimeFormatterBuilder().appendLocalized(dateStyle,
timeStyle).toFormatter(locale).toFormat();
unitFormat = null;
} else {
@@ -402,6 +407,39 @@ public class RangeFormat extends Format implements
Localized {
return (c == closeInclusive) || (c == closeExclusive) || (c ==
closeExclusiveAlt);
}
+ /**
+ * Returns {@code true} if objects of the given class have day, month and
hour fields.
+ * This method is defined here for having a single class where to
concentrate such heuristic rules.
+ * Note that {@link Instant} does not have date fields.
+ *
+ * @param date class of object to test (may be {@code null}).
+ * @return whether the given class is {@link LocalDate} or one of the
classes with date + time.
+ * This list may be expanded in future versions.
+ */
+ public static boolean hasDateFields(final Class<?> date) {
+ return date == LocalDate.class
+ || date == LocalDateTime.class
+ || date == OffsetDateTime.class
+ || date == ZonedDateTime.class;
+ }
+
+ /**
+ * Returns {@code true} if objects of the given class have time fields.
+ * This method is defined here for having a single class where to
concentrate such heuristic rules.
+ * Note that {@link Instant} does not have hour fields.
+ *
+ * @param date class of object to test (may be {@code null}).
+ * @return whether the given class is {@link LocalTime}, {@link
OffsetTime} or one of the classes with date + time.
+ * This list may be expanded in future versions.
+ */
+ public static boolean hasTimeFields(final Class<?> date) {
+ return date == LocalTime.class
+ || date == OffsetTime.class
+ || date == LocalDateTime.class
+ || date == OffsetDateTime.class
+ || date == ZonedDateTime.class;
+ }
+
/**
* Returns this formatter locale. This is the locale specified at
construction time if any,
* or the {@linkplain Locale#getDefault() default locale} at construction
time otherwise.
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK18.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK18.java
index 3596bf6da7..419bcc225f 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK18.java
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/pending/jdk/JDK18.java
@@ -16,6 +16,8 @@
*/
package org.apache.sis.pending.jdk;
+import java.time.Duration;
+
/**
* Place holder for some functionalities defined in a JDK more recent than
Java 11.
@@ -62,4 +64,13 @@ public final class JDK18 {
}
return r;
}
+
+ /**
+ * Checks if the duration is positive, excluding zero.
+ *
+ * @return true if this duration has a total length greater than zero.
+ */
+ public static boolean isPositive(final Duration d) {
+ return !(d.isNegative() || d.isZero());
+ }
}
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
index 3ebaf7cd64..e8cc5e393d 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.java
@@ -501,6 +501,11 @@ public class Errors extends IndexedResourceBundle {
*/
public static final short InconsistentUnitsForCS_1 = 87;
+ /**
+ * The position is indeterminate.
+ */
+ public static final short IndeterminatePosition = 206;
+
/**
* Index {0} is out of bounds.
*/
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.properties
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.properties
index 955faafe3e..c348e5bafc 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.properties
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors.properties
@@ -112,6 +112,7 @@ IncompatibleUnitDimension_5 = The \u201c{0}\u201d
unit of measurement has
InconsistentAttribute_2 = Value \u201c{1}\u201d of attribute
\u2018{0}\u2019 is inconsistent with other attributes.
InconsistentTableColumns = Inconsistent table columns.
InconsistentUnitsForCS_1 = Unit of measurement \u201c{0}\u201d is
inconsistent with coordinate system axes.
+IndeterminatePosition = The position is indeterminate.
IndexOutOfBounds_1 = Index {0} is out of bounds.
IndicesOutOfBounds_2 = Indices ({0}, {1}) are out of bounds.
InfiniteArgumentValue_1 = Argument \u2018{0}\u2019 cannot take an
infinite value.
diff --git
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors_fr.properties
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors_fr.properties
index cfc7abb465..ef040968eb 100644
---
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors_fr.properties
+++
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/resources/Errors_fr.properties
@@ -109,6 +109,7 @@ IncompatibleUnitDimension_5 = L\u2019unit\u00e9 de
mesure \u00ab\u202f{0}\
InconsistentAttribute_2 = La valeur \u00ab\u202f{1}\u202f\u00bb de
l\u2019attribut \u2018{0}\u2019 n\u2019est pas coh\u00e9rente avec celles des
autres attributs.
InconsistentTableColumns = Les colonnes des tables ne sont pas
coh\u00e9rentes.
InconsistentUnitsForCS_1 = L\u2019unit\u00e9 de mesure
\u00ab\u202f{0}\u202f\u00bb n\u2019est pas coh\u00e9rente avec les axes du
syst\u00e8me de coordonn\u00e9es.
+IndeterminatePosition = La position est ind\u00e9termin\u00e9e.
IndexOutOfBounds_1 = L\u2019index {0} est en dehors des limites
permises.
IndicesOutOfBounds_2 = Les index ({0}, {1}) sont en dehors des
limites permises.
InfiniteArgumentValue_1 = L\u2019argument \u2018{0}\u2019 ne peut
pas prendre une valeur infinie.
diff --git a/geoapi/snapshot b/geoapi/snapshot
index df67b0319b..044faffa03 160000
--- a/geoapi/snapshot
+++ b/geoapi/snapshot
@@ -1 +1 @@
-Subproject commit df67b0319be5ed161459bfa804ff3e34f366ce3d
+Subproject commit 044faffa03ac7337c5c3d5af3fe73fb9a30cce05
diff --git a/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/CQL.java
b/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/CQL.java
index 14f8a580de..c747caff37 100644
--- a/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/CQL.java
+++ b/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/CQL.java
@@ -61,7 +61,7 @@ import
org.apache.sis.cql.internal.CQLParser.ExpressionUnaryContext;
import org.apache.sis.cql.internal.CQLParser.FilterContext;
import org.apache.sis.cql.internal.CQLParser.FilterGeometryContext;
import org.apache.sis.cql.internal.CQLParser.FilterTermContext;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.StandardDateFormat;
import static org.apache.sis.cql.internal.CQLParser.*;
diff --git
a/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/FilterToCQLVisitor.java
b/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/FilterToCQLVisitor.java
index b7a24b8b69..aebf59b3cb 100644
---
a/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/FilterToCQLVisitor.java
+++
b/incubator/src/org.apache.sis.cql/main/org/apache/sis/cql/FilterToCQLVisitor.java
@@ -48,7 +48,7 @@ import org.apache.sis.geometry.wrapper.Geometries;
import org.apache.sis.geometry.wrapper.GeometryWrapper;
import org.apache.sis.filter.privy.FunctionNames;
import org.apache.sis.filter.privy.Visitor;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.temporal.StandardDateFormat;
/**