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 76bddb705e Introduce a `java.util.Date` subclass as a wrapper around a 
`Temporal` for situation where we have to mix legacy date API with new time 
API. Opportunistically move time constants to the `Constants` class.
76bddb705e is described below

commit 76bddb705ed107711db475c6f348b79748ab850d
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Fri May 24 17:53:36 2024 +0200

    Introduce a `java.util.Date` subclass as a wrapper around a `Temporal`
    for situation where we have to mix legacy date API with new time API.
    Opportunistically move time constants to the `Constants` class.
---
 .../main/org/apache/sis/console/AboutCommand.java  |   4 +-
 .../apache/sis/feature/FeatureMemoryBenchmark.java |   4 +-
 .../org/apache/sis/filter/TemporalFilterTest.java  |   2 +-
 .../sis/metadata/iso/acquisition/DefaultEvent.java |   4 +-
 .../metadata/iso/citation/DefaultCitationDate.java |   4 +-
 .../metadata/iso/extent/DefaultTemporalExtent.java |  14 +-
 .../apache/sis/metadata/iso/extent/Extents.java    |  11 +-
 .../sis/metadata/iso/legacy/TemporalToDate.java    |   4 +-
 .../sis/metadata/privy/ImplementationHelper.java   |  38 ----
 .../sis/pending/temporal/TemporalUtilities.java    |   8 +-
 .../sis/xml/bind/gml/UniversalTimeAdapter.java     |   2 +-
 .../apache/sis/xml/bind/lan/LanguageCodeTest.java  |   2 +-
 .../org/apache/sis/geometry/CoordinateFormat.java  |   9 +-
 .../main/org/apache/sis/referencing/CommonCRS.java |   2 +-
 .../sis/referencing/crs/DefaultTemporalCRS.java    |   4 +-
 .../sis/referencing/datum/AbstractDatum.java       |   4 +-
 .../sis/referencing/datum/TimeDependentBWP.java    |   4 +-
 .../factory/ConcurrentAuthorityFactory.java        |   6 +-
 .../sis/referencing/factory/ReferenceKeeper.java   |   4 +-
 .../referencing/factory/sql/EPSGDataAccess.java    |   2 +-
 .../sis/referencing/factory/sql/EPSGInstaller.java |   4 +-
 .../org/apache/sis/referencing/internal/Epoch.java |   4 +-
 .../apache/sis/referencing/internal/Legacy.java    |  17 --
 .../sis/io/wkt/GeodeticObjectParserTest.java       |   2 +-
 .../org/apache/sis/referencing/CommonCRSTest.java  |   5 +-
 .../referencing/crs/DefaultTemporalCRSTest.java    |   4 +-
 .../sis/referencing/datum/HardCodedDatum.java      |   2 +-
 .../referencing/datum/TimeDependentBWPTest.java    |   2 +-
 .../factory/ConcurrentAuthorityFactoryTest.java    |   2 +-
 .../operation/CoordinateOperationFinderTest.java   |   2 +-
 .../projection/MercatorMethodComparison.java       |   2 +-
 .../operation/projection/ProjectionBenchmark.java  |   5 +-
 .../apache/sis/storage/netcdf/base/Decoder.java    |   4 +-
 .../org/apache/sis/storage/netcdf/base/HYCOM.java  |   4 +-
 .../sis/storage/netcdf/classic/ChannelDecoder.java |   3 +-
 .../apache/sis/storage/netcdf/base/TestCase.java   |   4 +-
 .../sis/storage/sql/feature/ValueGetter.java       |  10 +-
 .../sis/storage/AbstractGridCoverageResource.java  |   4 +-
 .../org/apache/sis/storage/base/LegalSymbols.java  |   2 +-
 .../apache/sis/storage/base/MetadataBuilder.java   |   4 +-
 .../org/apache/sis/storage/csv/TimeEncoding.java   |   5 +-
 .../sis/storage/test/CoverageReadConsistency.java  |   4 +-
 .../main/org/apache/sis/io/CompoundFormat.java     |   2 +-
 .../main/org/apache/sis/measure/RangeFormat.java   |   6 +-
 .../main/org/apache/sis/measure/Units.java         |   4 +-
 .../main/org/apache/sis/setup/About.java           |   2 +-
 .../apache/sis/util/logging/MonolineFormatter.java |   2 +-
 .../main/org/apache/sis/util/privy/Constants.java  |  48 +++++
 .../org/apache/sis/util/privy/DoubleDouble.java    |   2 +-
 .../apache/sis/util/privy/StandardDateFormat.java  | 151 +------------
 .../org/apache/sis/util/privy/TemporalDate.java    | 236 +++++++++++++++++++++
 .../org/apache/sis/measure/RangeFormatTest.java    |   2 +-
 .../test/org/apache/sis/test/TestUtilities.java    |   2 +-
 .../org/apache/sis/util/collection/CacheTest.java  |   4 +-
 .../apache/sis/util/collection/RangeSetTest.java   |   4 +-
 .../org/apache/sis/util/privy/ConstantsTest.java   |  51 +++++
 .../sis/util/privy/StandardDateFormatTest.java     |  14 --
 .../main/org/apache/sis/gui/map/MapCanvas.java     |   2 +-
 .../apache/sis/gui/referencing/AuthorityCodes.java |   6 +-
 59 files changed, 439 insertions(+), 326 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
 
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
index ec5f061b5a..3744340a70 100644
--- 
a/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
+++ 
b/endorsed/src/org.apache.sis.console/main/org/apache/sis/console/AboutCommand.java
@@ -36,7 +36,7 @@ import org.apache.sis.util.resources.Messages;
 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.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.X364;
 import org.apache.sis.system.Loggers;
 import org.apache.sis.system.Supervisor;
@@ -139,7 +139,7 @@ final class AboutCommand extends CommandRunner {
                  * Logs a message telling how long it took to receive the 
reply.
                  * Sometimes the delay gives a hint about the server charge.
                  */
-                double delay = (System.nanoTime() - time) / (double) 
StandardDateFormat.NANOS_PER_SECOND;   // In seconds.
+                double delay = (System.nanoTime() - time) / (double) 
Constants.NANOS_PER_SECOND;   // In seconds.
                 if (delay >= 0.1) {
                     final double scale = (delay >= 10) ? 1 : (delay >= 1) ? 10 
: 100;
                     delay = Math.rint(delay * scale) / scale;
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/FeatureMemoryBenchmark.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/FeatureMemoryBenchmark.java
index eb1cefe92e..f8256c1a5b 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/FeatureMemoryBenchmark.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/feature/FeatureMemoryBenchmark.java
@@ -21,7 +21,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Random;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 
 // Test dependencies
 import org.apache.sis.test.Benchmark;
@@ -182,7 +182,7 @@ public final class FeatureMemoryBenchmark {
                 long time = System.nanoTime();
                 b.run();
                 time = System.nanoTime() - time;
-                System.console().printf("Ellapsed time: %f%n", time / (float) 
StandardDateFormat.NANOS_PER_SECOND);
+                System.console().printf("Ellapsed time: %f%n", time / (float) 
Constants.NANOS_PER_SECOND);
                 return;
             }
         }
diff --git 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
index eadba1cb1a..249639181b 100644
--- 
a/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
+++ 
b/endorsed/src/org.apache.sis.feature/test/org/apache/sis/filter/TemporalFilterTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.sis.filter;
 
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLISECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.MILLISECONDS_PER_DAY;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
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 a4a0395f38..e03d430ddf 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,8 +31,8 @@ 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 static org.apache.sis.metadata.privy.ImplementationHelper.toDate;
-import static org.apache.sis.metadata.privy.ImplementationHelper.toInstant;
+import static org.apache.sis.util.privy.TemporalDate.toDate;
+import static org.apache.sis.util.privy.TemporalDate.toInstant;
 
 
 /**
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 a906d34cd2..ebf05dae98 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,8 +25,8 @@ 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 static org.apache.sis.metadata.privy.ImplementationHelper.toDate;
-import static org.apache.sis.metadata.privy.ImplementationHelper.toInstant;
+import static org.apache.sis.util.privy.TemporalDate.toDate;
+import static org.apache.sis.util.privy.TemporalDate.toInstant;
 
 
 /**
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 e013f83590..4dcfbc663c 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
@@ -32,7 +32,7 @@ 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.StandardDateFormat;
+import org.apache.sis.util.privy.TemporalDate;
 import org.apache.sis.xml.NilObject;
 import org.apache.sis.xml.NilReason;
 
@@ -200,14 +200,6 @@ public class DefaultTemporalExtent extends ISOMetadata 
implements TemporalExtent
         return Optional.ofNullable(getBound(extent, false));
     }
 
-    /**
-     * Helper method for the deprecated methods.
-     */
-    @Deprecated(forRemoval=true)
-    private static Date toDate(final Optional<Temporal> date) {
-        return date.map((t) -> Date.from(StandardDateFormat.toInstant(t, 
null))).orElse(null);
-    }
-
     /**
      * The start date and time for the content of the dataset.
      * This method tries to infer it from the {@linkplain #getExtent() extent}.
@@ -218,7 +210,7 @@ public class DefaultTemporalExtent extends ISOMetadata 
implements TemporalExtent
      */
     @Deprecated(since="1.5", forRemoval=true)
     public Date getStartTime() {
-        return toDate(getBeginning());
+        return TemporalDate.toDate(getBeginning().orElse(null));
     }
 
     /**
@@ -231,7 +223,7 @@ public class DefaultTemporalExtent extends ISOMetadata 
implements TemporalExtent
      */
     @Deprecated(since="1.5", forRemoval=true)
     public Date getEndTime() {
-        return toDate(getEnding());
+        return TemporalDate.toDate(getEnding().orElse(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 aafebdac38..43024032b8 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
@@ -70,10 +70,9 @@ 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.StandardDateFormat;
+import org.apache.sis.util.privy.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.ImplementationHelper.toDate;
 import static 
org.apache.sis.metadata.privy.ReferencingServices.AUTHALIC_RADIUS;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
@@ -499,7 +498,7 @@ public final class Extents extends Static {
             if (min == null && max == null) {
                 return null;
             }
-            return new Range<>(Date.class, toDate(min), true, toDate(max), 
true);
+            return new Range<>(Date.class, TemporalDate.toDate(min), true, 
TemporalDate.toDate(max), true);
         }).orElse(null);
     }
 
@@ -536,7 +535,7 @@ public final class Extents extends Static {
      */
     @Deprecated(since="1.5", forRemoval=true)
     public static Date getDate(final Extent extent, final double location) {
-        return toDate(getInstant(extent, null, location).orElse(null));
+        return TemporalDate.toDate(getInstant(extent, null, 
location).orElse(null));
     }
 
     /**
@@ -592,8 +591,8 @@ public final class Extents extends Static {
                 if (t instanceof DefaultTemporalExtent) {
                     final var dt = (DefaultTemporalExtent) t;
                     // Maybe user has overridden those methods.
-                    startTime = 
StandardDateFormat.toInstant(dt.getBeginning().orElse(null), zone);
-                    endTime   = StandardDateFormat.toInstant(dt.getEnding()   
.orElse(null), zone);
+                    startTime = 
TemporalDate.toInstant(dt.getBeginning().orElse(null), zone);
+                    endTime   = TemporalDate.toInstant(dt.getEnding()   
.orElse(null), zone);
                 } else {
                     final TemporalPrimitive p = t.getExtent();
                     startTime = DefaultTemporalExtent.getBound(p, true);
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 851d89f81f..2249cde9ff 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.metadata.privy.ImplementationHelper;
+import org.apache.sis.util.privy.TemporalDate;
 
 
 /**
@@ -74,7 +74,7 @@ public final class TemporalToDate extends 
AbstractCollection<Date> {
             /** Returns the next temporal object, converted to a date. */
             @Override public Date next() {
                 // Following may throw `DateTimeException` if the temporal 
does not support a required field.
-                return ImplementationHelper.toDate(dates.next());
+                return TemporalDate.toDate(dates.next());
             }
 
             /** Remove the last date returned by the iterator. */
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/privy/ImplementationHelper.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/privy/ImplementationHelper.java
index a2a1eff6e3..def420f0cc 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/privy/ImplementationHelper.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/metadata/privy/ImplementationHelper.java
@@ -22,9 +22,6 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Objects;
-import java.time.Instant;
-import java.time.ZoneOffset;
-import java.time.temporal.Temporal;
 import org.apache.sis.xml.NilObject;
 import org.apache.sis.xml.NilReason;
 import org.apache.sis.xml.IdentifierSpace;
@@ -34,7 +31,6 @@ import org.apache.sis.util.resources.Errors;
 import org.apache.sis.xml.bind.Context;
 import org.apache.sis.util.privy.Strings;
 import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.StandardDateFormat;
 
 
 /**
@@ -56,40 +52,6 @@ public final class ImplementationHelper extends Static {
     private ImplementationHelper() {
     }
 
-    /**
-     * Returns the instant value for the given date, or {@code null} if the 
date is null.
-     * This is a temporary method for compatibility with legacy API.
-     *
-     * @param  value  the date, or {@code null}.
-     * @return the instant, or {@code null}.
-     */
-    public static Instant toInstant(final Date value) {
-        return (value != null) ? value.toInstant() : null;
-    }
-
-    /**
-     * Converts the instant to a date object, or returns null if the given 
time is null.
-     * This is a temporary method for compatibility with legacy API.
-     *
-     * @param  value  the instant, or {@code null}.
-     * @return the date for the given instant, or {@code null}.
-     */
-    public static Date toDate(final Instant value) {
-        return (value != null) ? Date.from(value) : null;
-    }
-
-    /**
-     * Converts the temporal to a date object, or returns null if the given 
time is null.
-     * If the temporal object does not specify its timezone, then UTC is 
assumed.
-     * This is a temporary method for compatibility with legacy API.
-     *
-     * @param  value  the temporal value, or {@code null}.
-     * @return the date for the given value, or {@code null}.
-     */
-    public static Date toDate(final Temporal value) {
-        return (value != null) ? Date.from(StandardDateFormat.toInstant(value, 
ZoneOffset.UTC)) : null;
-    }
-
     /**
      * Returns the milliseconds value of the given date, or {@link 
Long#MIN_VALUE}
      * if the date is null.
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
index 32b7a66e39..baedbaaaed 100644
--- 
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
@@ -21,7 +21,7 @@ import java.time.Instant;
 import java.time.ZoneOffset;
 import java.time.temporal.Temporal;
 import org.opengis.temporal.TemporalPrimitive;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.TemporalDate;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.temporal.Period;
@@ -71,8 +71,8 @@ public final class TemporalUtilities {
      * @todo Needs to avoid assuming UTC timezone.
      */
     public static TemporalPrimitive createPeriod(final Temporal begin, final 
Temporal end) {
-        return createPeriod(StandardDateFormat.toInstant(begin, 
ZoneOffset.UTC),
-                            StandardDateFormat.toInstant(end,   
ZoneOffset.UTC));
+        return createPeriod(TemporalDate.toInstant(begin, ZoneOffset.UTC),
+                            TemporalDate.toInstant(end,   ZoneOffset.UTC));
     }
 
     /**
@@ -132,7 +132,7 @@ public final class TemporalUtilities {
             var p = (Period) time;
             Instant instant;
             if ((instant = p.getEnding()) != null || (instant = 
p.getBeginning()) != null) {
-                return Date.from(instant);
+                return TemporalDate.toDate(instant);
             }
         }
         return null;
diff --git 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/UniversalTimeAdapter.java
 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/UniversalTimeAdapter.java
index 7379d4f426..1c9106557c 100644
--- 
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/UniversalTimeAdapter.java
+++ 
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/xml/bind/gml/UniversalTimeAdapter.java
@@ -42,7 +42,7 @@ public final class UniversalTimeAdapter extends 
XmlAdapter<XMLGregorianCalendar,
     /**
      * The timezone of the date to marshal with this adapter.
      */
-    private static final TimeZone UTC = 
TimeZone.getTimeZone(org.apache.sis.util.privy.StandardDateFormat.UTC);
+    private static final TimeZone UTC = 
TimeZone.getTimeZone(org.apache.sis.util.privy.Constants.UTC);
 
     /**
      * Empty constructor for JAXB only.
diff --git 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/lan/LanguageCodeTest.java
 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/lan/LanguageCodeTest.java
index d53f5b6c1b..a5737d98b4 100644
--- 
a/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/lan/LanguageCodeTest.java
+++ 
b/endorsed/src/org.apache.sis.metadata/test/org/apache/sis/xml/bind/lan/LanguageCodeTest.java
@@ -27,7 +27,7 @@ import org.apache.sis.xml.XML;
 import org.apache.sis.xml.MarshallerPool;
 import org.apache.sis.xml.bind.cat.CodeListUID;
 import org.apache.sis.xml.privy.LegacyNamespaces;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
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 88e7c4806d..efc89b49e2 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,7 +59,8 @@ 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.StandardDateFormat;
+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;
@@ -579,7 +580,7 @@ public class CoordinateFormat extends 
CompoundFormat<DirectPosition> {
                     }
                     types  [i] = DATE;
                     formats[i] = getFormat(Date.class);
-                    epochs [i] = StandardDateFormat.toInstant(((TemporalCRS) 
t).getDatum().getOrigin(), null);
+                    epochs [i] = TemporalDate.toInstant(((TemporalCRS) 
t).getDatum().getOrigin(), null);
                     setConverter(dimension, i, 
unit.asType(Time.class).getConverterTo(Units.SECOND));
                     if (direction == AxisDirection.PAST) {
                         negate(i);
@@ -1490,7 +1491,7 @@ abort:  if (dimensions != 0 && groundAccuracy != null) 
try {
                     case ANGLE:     valueObject = new Angle     (value); break;
                     case DATE: {
                         if (Double.isFinite(value)) {
-                            valueObject = 
Date.from(StandardDateFormat.addSeconds(epochs[i], value));
+                            valueObject = 
TemporalDate.toDate(TemporalDate.addSeconds(epochs[i], value));
                         } else {
                             if (i != 0) toAppendTo.append(separator);
                             toAppendTo.append(String.valueOf(value));
@@ -1671,7 +1672,7 @@ skipSep:    if (i != 0) {
                 value = ((Angle) object).degrees();
             } else if (object instanceof Date) {
                 final Duration d = JDK23.until(epochs[i], ((Date) 
object).toInstant());
-                value = d.getSeconds() + (d.getNano() / (double) 
StandardDateFormat.NANOS_PER_SECOND);
+                value = d.getSeconds() + (d.getNano() / (double) 
Constants.NANOS_PER_SECOND);
             } else {
                 value = ((Number) object).doubleValue();
             }
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
index 8d9043203e..f9f1937210 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CommonCRS.java
@@ -84,7 +84,7 @@ import org.apache.sis.util.logging.Logging;
 import org.apache.sis.math.MathFunctions;
 import org.apache.sis.measure.Latitude;
 import org.apache.sis.measure.Units;
-import static org.apache.sis.util.privy.StandardDateFormat.SECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.SECONDS_PER_DAY;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.referencing.datum.RealizationMethod;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
index 5e6476b81d..0c3a5579d9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultTemporalCRS.java
@@ -42,8 +42,8 @@ import org.apache.sis.metadata.privy.ImplementationHelper;
 import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.measure.Units;
 import org.apache.sis.math.Fraction;
-import static org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_SECOND;
-import static org.apache.sis.util.privy.StandardDateFormat.MILLIS_PER_SECOND;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_SECOND;
+import static org.apache.sis.util.privy.Constants.MILLIS_PER_SECOND;
 
 
 /**
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 a525851b79..ce18679d10 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
@@ -45,7 +45,7 @@ import static org.apache.sis.util.Utilities.deepEquals;
 import static org.apache.sis.util.collection.Containers.property;
 
 // Specific to the main and geoapi-4.0 branches:
-import org.apache.sis.referencing.internal.Legacy;
+import org.apache.sis.util.privy.TemporalDate;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.metadata.Identifier;
@@ -477,7 +477,7 @@ public class AbstractDatum extends AbstractIdentifiedObject 
implements Datum {
     @XmlElement(name = "realizationEpoch")
     @UML(identifier="realizationEpoch", obligation=OPTIONAL, 
specification=ISO_19111, version=2007)
     private Date getRealizationEpoch() {
-        return getAnchorEpoch().map(Legacy::toDate).orElse(null);
+        return getAnchorEpoch().map(TemporalDate::toDate).orElse(null);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/TimeDependentBWP.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/TimeDependentBWP.java
index 7542035ed7..a92486dfb9 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/TimeDependentBWP.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/TimeDependentBWP.java
@@ -24,7 +24,7 @@ import org.opengis.metadata.extent.Extent;
 import org.opengis.referencing.datum.GeodeticDatum;
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.apache.sis.util.privy.DoubleDouble;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import static org.apache.sis.util.ArgumentChecks.*;
 
 
@@ -175,7 +175,7 @@ public class TimeDependentBWP extends BursaWolfParameters {
         if (time != null) {
             final Duration d = Duration.between(timeReference, time);
             if (!d.isZero()) {      // Returns null for 0 as an optimization.
-                return 
DoubleDouble.of(d).divide(StandardDateFormat.MILLIS_PER_TROPICAL_YEAR * 
StandardDateFormat.NANOS_PER_MILLISECOND);
+                return 
DoubleDouble.of(d).divide(Constants.MILLIS_PER_TROPICAL_YEAR * 
Constants.NANOS_PER_MILLISECOND);
             }
         }
         return null;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
index f7d6ab7758..6f4fecb534 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ConcurrentAuthorityFactory.java
@@ -57,7 +57,7 @@ import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.PerformanceLevel;
 import org.apache.sis.util.collection.Cache;
 import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.metadata.simple.SimpleCitation;
 import org.apache.sis.system.ReferenceQueueConsumer;
 import org.apache.sis.system.DelayedExecutor;
@@ -219,7 +219,7 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
                 value = depth;
             } else {
                 text = "%s made available %d seconds ago";
-                value = Math.round((System.nanoTime() - timestamp) / (double) 
StandardDateFormat.NANOS_PER_SECOND);
+                value = Math.round((System.nanoTime() - timestamp) / (double) 
Constants.NANOS_PER_SECOND);
             }
             return String.format(text, Classes.getShortClassName(factory), 
value);
         }
@@ -493,7 +493,7 @@ public abstract class ConcurrentAuthorityFactory<DAO 
extends GeodeticAuthorityFa
                     caller = "create".concat(type.getSimpleName());
                 }
                 final Level level = PerformanceLevel.forDuration(time, 
TimeUnit.NANOSECONDS);
-                final Double duration = time / (double) 
StandardDateFormat.NANOS_PER_SECOND;
+                final Double duration = time / (double) 
Constants.NANOS_PER_SECOND;
                 final Messages resources = Messages.forLocale(null);
                 final LogRecord record;
                 if (code != null) {
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ReferenceKeeper.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ReferenceKeeper.java
index 63e06fcfcb..25d466f05f 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ReferenceKeeper.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/ReferenceKeeper.java
@@ -20,7 +20,7 @@ import org.opengis.referencing.IdentifiedObject;
 import org.apache.sis.system.Configuration;
 import org.apache.sis.system.DelayedExecutor;
 import org.apache.sis.system.DelayedRunnable;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 
 
 /**
@@ -56,7 +56,7 @@ final class ReferenceKeeper {
      * Time to wait before to remove entries from this map. Current value is 5 
minutes.
      */
     @Configuration
-    private static final long EXPIRATION_TIME = 5L * 60 * 
StandardDateFormat.NANOS_PER_SECOND;
+    private static final long EXPIRATION_TIME = 5L * 60 * 
Constants.NANOS_PER_SECOND;
 
     /**
      * The objects to retain by strong reference. May contains duplicated 
values and {@code null} anywhere.
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 1efdfe9e5c..7343d3db34 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
@@ -117,8 +117,8 @@ import org.apache.sis.measure.MeasurementRange;
 import org.apache.sis.measure.NumberRange;
 import org.apache.sis.measure.Units;
 import org.apache.sis.pending.jdk.JDK16;
+import static org.apache.sis.util.privy.Constants.UTC;
 import static org.apache.sis.util.Utilities.equalsIgnoreMetadata;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
 import static 
org.apache.sis.referencing.internal.ServicesForMetadata.CONNECTION;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
index d78915130d..dfd4171ba0 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/sql/EPSGInstaller.java
@@ -30,7 +30,7 @@ import org.apache.sis.util.StringBuilders;
 import org.apache.sis.util.Exceptions;
 import org.apache.sis.metadata.sql.privy.ScriptRunner;
 import org.apache.sis.metadata.sql.privy.SQLUtilities;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.system.Fallback;
 import org.apache.sis.util.resources.Messages;
 import org.apache.sis.util.logging.PerformanceLevel;
@@ -247,7 +247,7 @@ final class EPSGInstaller extends ScriptRunner {
         time = System.nanoTime() - time;
         InstallationScriptProvider.log(Messages.forLocale(locale).getLogRecord(
                 PerformanceLevel.forDuration(time, TimeUnit.NANOSECONDS),
-                Messages.Keys.InsertDuration_2, numRows, time / (float) 
StandardDateFormat.NANOS_PER_SECOND));
+                Messages.Keys.InsertDuration_2, numRows, time / (float) 
Constants.NANOS_PER_SECOND));
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
index 80e0e3f8a8..558fff3fef 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
@@ -27,7 +27,7 @@ import org.apache.sis.io.wkt.Formatter;
 import org.apache.sis.io.wkt.FormattableObject;
 import org.apache.sis.math.DecimalFunctions;
 import org.apache.sis.referencing.privy.WKTKeywords;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 
 
 /**
@@ -70,7 +70,7 @@ public final class Epoch extends FormattableObject {
                 fractionDigits = 2;
             } else if (epoch.isSupported(ChronoField.NANO_OF_DAY)) {
                 day = epoch.getLong(ChronoField.NANO_OF_DAY);
-                day /= StandardDateFormat.MILLISECONDS_PER_DAY * (long) 
StandardDateFormat.NANOS_PER_MILLISECOND;
+                day /= (double) Constants.NANOSECONDS_PER_DAY;
                 fractionDigits = (epoch.get(ChronoField.NANO_OF_SECOND) != 0) 
? 16 : 8;
             }
             day += epoch.get(ChronoField.DAY_OF_YEAR) - 1;
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
index 8ad7a7d87c..eb27eb484d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Legacy.java
@@ -30,10 +30,6 @@ import 
org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis;
 import org.apache.sis.referencing.privy.ReferencingUtilities;
 
 // Specific to the main and geoapi-4.0 branches:
-import java.util.Date;
-import java.time.ZoneOffset;
-import java.time.temporal.Temporal;
-import org.apache.sis.util.privy.StandardDateFormat;
 
 
 /**
@@ -137,17 +133,4 @@ public final class Legacy {
         }
         return cs;
     }
-
-    /**
-     * Converts a {@link java.time} object to a legacy {@link Date} object.
-     * If the time zone is not specified, UTC is assumed.
-     *
-     * @param  t  the date to convert.
-     * @return the given temporal object as a date, or {@code null} if the 
method doesn't know how to convert.
-     * @throws ArithmeticException if numeric overflow occurs.
-     */
-    public static Date toDate(final Temporal t) {
-        // Do not use `Date.from(Instant)` because we want the 
`ArithmeticException` in case of overflow.
-        return new Date(StandardDateFormat.toInstant(t, 
ZoneOffset.UTC).toEpochMilli());
-    }
 }
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
index bbbbc4bf11..4610b54611 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
@@ -43,7 +43,7 @@ import 
org.apache.sis.referencing.factory.GeodeticObjectFactory;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.measure.Units;
-import static org.apache.sis.util.privy.StandardDateFormat.SECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.SECONDS_PER_DAY;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
index b9be982d52..712918bd4a 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/CommonCRSTest.java
@@ -39,7 +39,6 @@ import org.opengis.referencing.datum.VerticalDatum;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.metadata.privy.AxisNames;
 import org.apache.sis.referencing.internal.VerticalDatumTypes;
-import org.apache.sis.util.privy.StandardDateFormat;
 import org.apache.sis.util.privy.Constants;
 
 // Test dependencies
@@ -50,7 +49,7 @@ import org.apache.sis.test.TestCase;
 import static org.apache.sis.test.Assertions.assertEqualsIgnoreMetadata;
 import static org.apache.sis.test.Assertions.assertMessageContains;
 import static org.apache.sis.test.TestUtilities.*;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.referencing.datum.RealizationMethod;
@@ -256,7 +255,7 @@ public final class CommonCRSTest extends TestCase {
     @Test
     public void testTemporal() {
         final var julianEpoch = (Instant) 
CommonCRS.Temporal.JULIAN.datum().getOrigin();
-        final double SECONDS_PER_DAY = StandardDateFormat.SECONDS_PER_DAY;
+        final double SECONDS_PER_DAY = Constants.SECONDS_PER_DAY;
         final double julianEpochSecond = julianEpoch.getEpochSecond() / 
SECONDS_PER_DAY;
         assertTrue(julianEpochSecond < 0);
         /*
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
index 8ea5a07f5c..2ee0116c1d 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultTemporalCRSTest.java
@@ -22,8 +22,8 @@ import java.util.Date;
 import java.util.Map;
 import org.apache.sis.referencing.datum.DefaultTemporalDatum;
 import org.apache.sis.io.wkt.Convention;
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLISECONDS_PER_DAY;
-import static 
org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_MILLISECOND;
+import static org.apache.sis.util.privy.Constants.MILLISECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_MILLISECOND;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
index 51b89396f7..3edb04e959 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/HardCodedDatum.java
@@ -22,7 +22,7 @@ import java.time.Instant;
 import org.apache.sis.referencing.NamedIdentifier;
 import org.apache.sis.referencing.internal.VerticalDatumTypes;
 import org.apache.sis.measure.Units;
-import static org.apache.sis.util.privy.StandardDateFormat.SECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.SECONDS_PER_DAY;
 
 // Test dependencies
 import org.apache.sis.metadata.iso.citation.HardCodedCitations;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/TimeDependentBWPTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/TimeDependentBWPTest.java
index f76edfaef7..662d94215c 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/TimeDependentBWPTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/TimeDependentBWPTest.java
@@ -23,7 +23,7 @@ import org.opengis.referencing.operation.Matrix;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import 
org.apache.sis.referencing.operation.matrix.NoninvertibleMatrixException;
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLIS_PER_TROPICAL_YEAR;
+import static org.apache.sis.util.privy.Constants.MILLIS_PER_TROPICAL_YEAR;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
index ffc67ffc6e..e9bf0141a7 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/factory/ConcurrentAuthorityFactoryTest.java
@@ -24,7 +24,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 import java.lang.reflect.Field;
 import org.opengis.util.FactoryException;
-import static 
org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_MILLISECOND;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_MILLISECOND;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
index 660811908d..649738efde 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
@@ -53,7 +53,7 @@ import org.apache.sis.referencing.crs.DefaultCompoundCRS;
 import org.apache.sis.referencing.crs.DefaultDerivedCRS;
 import org.apache.sis.io.wkt.WKTFormat;
 import org.apache.sis.measure.Units;
-import static org.apache.sis.util.privy.StandardDateFormat.SECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.SECONDS_PER_DAY;
 import static org.apache.sis.referencing.privy.Formulas.LINEAR_TOLERANCE;
 import static org.apache.sis.referencing.privy.Formulas.ANGULAR_TOLERANCE;
 import static 
org.apache.sis.referencing.privy.PositionalAccuracyConstant.DATUM_SHIFT_APPLIED;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
index 30f40d4aa9..d83bdc2496 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MercatorMethodComparison.java
@@ -26,7 +26,7 @@ import org.apache.sis.math.Statistics;
 import org.apache.sis.math.StatisticsFormat;
 import org.apache.sis.referencing.internal.Resources;
 import org.apache.sis.metadata.privy.ReferencingServices;
-import static org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_SECOND;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_SECOND;
 
 // Test dependencies
 import org.apache.sis.test.Benchmark;
diff --git 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ProjectionBenchmark.java
 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ProjectionBenchmark.java
index cd093e9ed3..673af07dc7 100644
--- 
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ProjectionBenchmark.java
+++ 
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/ProjectionBenchmark.java
@@ -28,7 +28,6 @@ import org.apache.sis.math.StatisticsFormat;
 import org.apache.sis.measure.Latitude;
 import org.apache.sis.parameter.Parameters;
 import org.apache.sis.util.privy.Constants;
-import org.apache.sis.util.privy.StandardDateFormat;
 import org.apache.sis.referencing.operation.provider.AbstractProvider;
 import org.apache.sis.referencing.operation.transform.LinearTransform;
 import org.apache.sis.referencing.operation.transform.MathTransforms;
@@ -219,7 +218,7 @@ public final class ProjectionBenchmark {
             long time = System.nanoTime();
             projection.transform(sources, 0, targets, 0, NUM_POINTS);
             time = System.nanoTime() - time;
-            final double seconds = time / (double) 
StandardDateFormat.NANOS_PER_SECOND;
+            final double seconds = time / (double) Constants.NANOS_PER_SECOND;
             System.out.printf("%s time: %1.4f%n", performance.name(), seconds);
             performance.accept(seconds);
         }
@@ -235,7 +234,7 @@ public final class ProjectionBenchmark {
             kernel.transform(targets, 0, targets, 0, NUM_POINTS);
             time = System.nanoTime() - time;
             denormalize.transform(targets, 0, targets, 0, NUM_POINTS);
-            final double seconds = time / (double) 
StandardDateFormat.NANOS_PER_SECOND;
+            final double seconds = time / (double) Constants.NANOS_PER_SECOND;
             System.out.printf("%s time: %1.4f%n", performance.name(), seconds);
             performance.accept(seconds);
         }
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
index 9daee7355a..e264766e4a 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/Decoder.java
@@ -47,7 +47,7 @@ import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.logging.PerformanceLevel;
 import org.apache.sis.util.collection.TreeTable;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.iso.DefaultNameFactory;
 import org.apache.sis.referencing.privy.ReferencingFactoryContainer;
 
@@ -520,7 +520,7 @@ public abstract class Decoder extends 
ReferencingFactoryContainer {
         final Logger logger = listeners.getLogger();
         if (logger.isLoggable(level)) {
             final LogRecord record = resources().getLogRecord(level, 
resourceKey,
-                    getFilename(), time / (double) 
StandardDateFormat.NANOS_PER_SECOND);
+                    getFilename(), time / (double) Constants.NANOS_PER_SECOND);
             Logging.completeAndLog(logger, caller, method, record);
         }
     }
diff --git 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/HYCOM.java
 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/HYCOM.java
index 70cf3a0e98..543f9f12e4 100644
--- 
a/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/HYCOM.java
+++ 
b/endorsed/src/org.apache.sis.storage.netcdf/main/org/apache/sis/storage/netcdf/base/HYCOM.java
@@ -25,7 +25,7 @@ import java.util.regex.Pattern;
 import org.apache.sis.math.Vector;
 import org.apache.sis.measure.Units;
 import org.apache.sis.storage.DataStoreException;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 
 
 /**
@@ -112,7 +112,7 @@ final class HYCOM {
                             int month = (int) (date % 100); date /= 100;
                             calendar.set(Math.toIntExact(date), month - 1, 
day, 0, 0, 0);
                             date = calendar.getTimeInMillis() - origin;        
             // Milliseconds since epoch.
-                            time += date / (double) 
StandardDateFormat.MILLISECONDS_PER_DAY;
+                            time += date / (double) 
Constants.MILLISECONDS_PER_DAY;
                             times[i] = time;
                         }
                         variable.setValues(times);
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 4888794c25..a91de6055d 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
@@ -59,6 +59,7 @@ 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;
@@ -886,7 +887,7 @@ public final class ChannelDecoder extends Decoder {
             for (int i=0; i<values.length; i++) {
                 final Number value = values[i];
                 if (value != null) {
-                    dates[i] = StandardDateFormat.addSeconds(epoch, 
converter.convert(value.doubleValue()));
+                    dates[i] = TemporalDate.addSeconds(epoch, 
converter.convert(value.doubleValue()));
                 }
             }
         } catch (IncommensurableException | MeasurementParseException | 
DateTimeException | ArithmeticException e) {
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 39d5f64018..8a251001bd 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
@@ -30,7 +30,7 @@ import org.apache.sis.storage.AbstractResource;
 import org.apache.sis.storage.DataStoreException;
 import org.apache.sis.storage.event.StoreListeners;
 import org.apache.sis.storage.netcdf.ucar.DecoderWrapper;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.TemporalDate;
 import org.apache.sis.setup.GeometryLibrary;
 
 // Test dependencies
@@ -265,6 +265,6 @@ public abstract class TestCase extends 
org.apache.sis.test.TestCase {
      * @throws IOException if an error occurred while reading the netCDF file.
      */
     protected final void assertAttributeEquals(final Instant expected, final 
String attributeName) throws IOException {
-        assertEquals(expected, 
StandardDateFormat.toInstant(decoder.dateValue(attributeName), ZoneOffset.UTC), 
attributeName);
+        assertEquals(expected, 
TemporalDate.toInstant(decoder.dateValue(attributeName), ZoneOffset.UTC), 
attributeName);
     }
 }
diff --git 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/ValueGetter.java
 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/ValueGetter.java
index ec948302cf..b1158d119d 100644
--- 
a/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/ValueGetter.java
+++ 
b/endorsed/src/org.apache.sis.storage.sql/main/org/apache/sis/storage/sql/feature/ValueGetter.java
@@ -33,7 +33,7 @@ import java.time.ZoneOffset;
 import java.math.BigDecimal;
 import org.apache.sis.math.Vector;
 import org.apache.sis.util.Numbers;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.UnmodifiableArrayList;
 
 
@@ -361,8 +361,8 @@ public class ValueGetter<T> {
              * `Time.toLocalTime()` does not use sub-second precision.
              * However, some databases provide millisecond precision.
              */
-            final int milli = (int) (time.getTime() % 
StandardDateFormat.MILLIS_PER_SECOND);
-            return time.toLocalTime().withNano(milli * 
StandardDateFormat.NANOS_PER_MILLISECOND);
+            final int milli = (int) (time.getTime() % 
Constants.MILLIS_PER_SECOND);
+            return time.toLocalTime().withNano(milli * 
Constants.NANOS_PER_MILLISECOND);
         }
     }
 
@@ -440,8 +440,8 @@ public class ValueGetter<T> {
             final Time time = source.getTime(columnIndex);
             if (time == null) return null;
             final int offsetMinute = -time.getTimezoneOffset();
-            final int milli = (int) (time.getTime() % 
StandardDateFormat.MILLIS_PER_SECOND);
-            return time.toLocalTime().withNano(milli * 
StandardDateFormat.NANOS_PER_MILLISECOND)
+            final int milli = (int) (time.getTime() % 
Constants.MILLIS_PER_SECOND);
+            return time.toLocalTime().withNano(milli * 
Constants.NANOS_PER_MILLISECOND)
                     .atOffset(ZoneOffset.ofHoursMinutes(offsetMinute / 60, 
offsetMinute % 60));
         }
     }
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractGridCoverageResource.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractGridCoverageResource.java
index 46a0e93bda..a0abd3b89a 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractGridCoverageResource.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/AbstractGridCoverageResource.java
@@ -37,7 +37,7 @@ import org.apache.sis.measure.Longitude;
 import org.apache.sis.measure.AngleFormat;
 import org.apache.sis.util.logging.PerformanceLevel;
 import org.apache.sis.io.stream.IOUtilities;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.storage.base.MetadataBuilder;
 import org.apache.sis.storage.internal.Resources;
 
@@ -203,7 +203,7 @@ public abstract class AbstractGridCoverageResource extends 
AbstractResource impl
             final Locale locale = listeners.getLocale();
             final Object[] parameters = new Object[6];
             parameters[0] = IOUtilities.filename(file != null ? file : 
listeners.getSourceName());
-            parameters[5] = nanos / (double) 
StandardDateFormat.NANOS_PER_SECOND;
+            parameters[5] = nanos / (double) Constants.NANOS_PER_SECOND;
             domain.getGeographicExtent().ifPresentOrElse((box) -> {
                 final AngleFormat f = new AngleFormat(locale);
                 double min = box.getSouthBoundLatitude();
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/LegalSymbols.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/LegalSymbols.java
index 7ead46568e..570b35d2e2 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/LegalSymbols.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/LegalSymbols.java
@@ -27,7 +27,7 @@ import org.apache.sis.metadata.iso.citation.AbstractParty;
 import org.apache.sis.metadata.iso.citation.DefaultCitation;
 import org.apache.sis.metadata.iso.citation.DefaultCitationDate;
 import org.apache.sis.metadata.iso.constraint.DefaultLegalConstraints;
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLISECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.MILLISECONDS_PER_DAY;
 
 // Specific to the geoapi-4.0 branch:
 import org.apache.sis.metadata.iso.citation.DefaultResponsibility;
diff --git 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
index fed534b477..336e8caf38 100644
--- 
a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
+++ 
b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java
@@ -71,7 +71,7 @@ import org.apache.sis.util.iso.Names;
 import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.privy.CollectionsExt;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.Strings;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.metadata.ModifiableMetadata;
@@ -2029,7 +2029,7 @@ public class MetadataBuilder {
     public final void addTemporalResolution(final double duration) {
         if (Double.isFinite(duration)) {
             addIfNotPresent(identification().getTemporalResolutions(),
-                    Duration.ofMillis(Math.round(duration * 
StandardDateFormat.MILLISECONDS_PER_DAY)));
+                    Duration.ofNanos(Math.round(duration * 
Constants.NANOSECONDS_PER_DAY)));
         }
     }
 
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 d753fee7eb..1571c6b88b 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
@@ -23,6 +23,7 @@ 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.referencing.CommonCRS;
 import org.apache.sis.measure.Units;
 
@@ -63,7 +64,7 @@ class TimeEncoding extends 
SurjectiveConverter<String,Instant> {
      * Creates a new time encoding.
      */
     TimeEncoding(final TemporalDatum datum, final Unit<Time> unit) {
-        this.origin   = StandardDateFormat.toInstant(datum.getOrigin(), null);
+        this.origin   = TemporalDate.toInstant(datum.getOrigin(), null);
         this.interval = unit.getConverterTo(Units.SECOND).convert(1);
     }
 
@@ -91,7 +92,7 @@ class TimeEncoding extends 
SurjectiveConverter<String,Instant> {
      */
     @Override
     public Instant apply(final String time) {
-        return StandardDateFormat.addSeconds(origin, Double.parseDouble(time) 
* interval);
+        return TemporalDate.addSeconds(origin, Double.parseDouble(time) * 
interval);
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
index bef0a6f80e..1f92a0b74f 100644
--- 
a/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
+++ 
b/endorsed/src/org.apache.sis.storage/test/org/apache/sis/storage/test/CoverageReadConsistency.java
@@ -33,7 +33,7 @@ import org.apache.sis.storage.GridCoverageResource;
 import org.apache.sis.storage.RasterLoadingStrategy;
 import org.apache.sis.util.Workaround;
 import org.apache.sis.util.ArraysExt;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.Numerics;
 import org.apache.sis.image.PixelIterator;
 import org.apache.sis.math.Statistics;
@@ -458,7 +458,7 @@ nextSlice:  for (;;) {
                 break;
             }
             if (durations != null) {
-                durations.accept((System.nanoTime() - startTime) / (double) 
StandardDateFormat.NANOS_PER_MILLISECOND);
+                durations.accept((System.nanoTime() - startTime) / (double) 
Constants.NANOS_PER_MILLISECOND);
             }
         }
         /*
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/CompoundFormat.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/CompoundFormat.java
index d45660df53..5d912fa649 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/CompoundFormat.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/io/CompoundFormat.java
@@ -48,7 +48,7 @@ import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.privy.MetadataServices;
 import org.apache.sis.util.privy.LocalizedParseException;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 
 /**
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 6bf6a90d87..30f8441fd2 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
@@ -43,7 +43,7 @@ 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.StandardDateFormat;
+import org.apache.sis.util.privy.TemporalDate;
 import org.apache.sis.util.privy.Numerics;
 
 
@@ -362,8 +362,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 = 
StandardDateFormat.hasDateFields(elementType) ? FormatStyle.SHORT : null;
-            final FormatStyle timeStyle = 
StandardDateFormat.hasTimeFields(elementType) ? FormatStyle.SHORT : null;
+            final FormatStyle dateStyle = 
TemporalDate.hasDateFields(elementType) ? FormatStyle.SHORT : null;
+            final FormatStyle timeStyle = 
TemporalDate.hasTimeFields(elementType) ? FormatStyle.SHORT : null;
             elementFormat = new 
DateTimeFormatterBuilder().appendLocalized(dateStyle, 
timeStyle).toFormatter(locale).toFormat();
             unitFormat    = null;
         } else {
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/Units.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/Units.java
index d3689b66c1..a5405d349b 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/Units.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/measure/Units.java
@@ -35,8 +35,8 @@ import static org.apache.sis.measure.UnitRegistry.CGS;
 import static org.apache.sis.measure.UnitRegistry.IMPERIAL;
 import static org.apache.sis.measure.UnitRegistry.OTHER;
 import static org.apache.sis.measure.UnitRegistry.PREFIXABLE;
-import static org.apache.sis.util.privy.StandardDateFormat.SECONDS_PER_DAY;
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLIS_PER_TROPICAL_YEAR;
+import static org.apache.sis.util.privy.Constants.SECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.MILLIS_PER_TROPICAL_YEAR;
 
 
 /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
index 30b539fe37..f004670739 100644
--- a/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
+++ b/endorsed/src/org.apache.sis.util/main/org/apache/sis/setup/About.java
@@ -59,7 +59,7 @@ import org.apache.sis.system.Shutdown;
 import org.apache.sis.system.DataDirectory;
 import static org.apache.sis.util.collection.TableColumn.NAME;
 import static org.apache.sis.util.collection.TableColumn.VALUE_AS_TEXT;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 
 /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java
index 6cb9e9d2f3..976029cacc 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/logging/MonolineFormatter.java
@@ -42,7 +42,7 @@ import org.apache.sis.util.privy.Strings;
 import org.apache.sis.util.internal.AutoMessageFormat;
 import org.apache.sis.io.IO;
 import org.apache.sis.io.LineAppender;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 
 /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
index f4a975c711..eb93271cbc 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/Constants.java
@@ -49,6 +49,54 @@ public final class Constants extends Static {
      */
     public static final byte DEFAULT_INDENTATION = 2;
 
+    /**
+     * The length of a day in number of seconds.
+     * Can be casted to {@code float} with exact precision.
+     */
+    public static final int SECONDS_PER_DAY = 24*60*60;
+
+    /**
+     * The length of a day in number of milliseconds.
+     * Can be casted to {@code float} with exact precision.
+     */
+    public static final int MILLISECONDS_PER_DAY = SECONDS_PER_DAY * 1000;
+
+    /**
+     * The length of a day in number of nanoseconds.
+     */
+    public static final long NANOSECONDS_PER_DAY = MILLISECONDS_PER_DAY * 
(long) 1_000_000;
+
+    /**
+     * Number of milliseconds in one second.
+     * Can be casted to {@code float} with exact precision.
+     */
+    public static final int MILLIS_PER_SECOND = 1000;
+
+    /**
+     * Number of nanoseconds in one millisecond.
+     * Can be casted to {@code float} with exact precision.
+     */
+    public static final int NANOS_PER_MILLISECOND = 1000_000;
+
+    /**
+     * Number of nanoseconds in one second.
+     * Can be casted to {@code float} with exact precision.
+     */
+    public static final int NANOS_PER_SECOND = 1000_000_000;
+
+    /**
+     * Length of a year as defined by the International Union of Geological 
Sciences (IUGS), in milliseconds.
+     * This is the unit of measurement used in EPSG geodetic dataset 
(EPSG:1029).
+     */
+    public static final long MILLIS_PER_TROPICAL_YEAR = 31556925445L;
+
+    /**
+     * The {@value} timezone ID.
+     *
+     * @see java.time.ZoneOffset#UTC
+     */
+    public static final String UTC = "UTC";
+
     /**
      * The {@value} protocol.
      */
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/DoubleDouble.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/DoubleDouble.java
index 1c341b9fd2..15f522bcde 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/DoubleDouble.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/DoubleDouble.java
@@ -264,7 +264,7 @@ public final class DoubleDouble extends Number implements 
Comparable<DoubleDoubl
      * @return the given duration, in nanoseconds.
      */
     public static DoubleDouble of(final Duration value) {
-        return 
of(value.getSeconds()).multiply(StandardDateFormat.NANOS_PER_SECOND).add(value.getNano());
+        return 
of(value.getSeconds()).multiply(Constants.NANOS_PER_SECOND).add(value.getNano());
     }
 
     /**
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
index c51296f401..6c4ee5e27f 100644
--- 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/StandardDateFormat.java
@@ -27,25 +27,21 @@ import java.text.ParsePosition;
 import java.text.ParseException;
 import java.time.DateTimeException;
 import java.time.Instant;
-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.TemporalQuery;
 import java.time.temporal.TemporalAccessor;
-import java.time.chrono.ChronoZonedDateTime;
 import java.time.format.DateTimeFormatter;
 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.resources.Errors;
 
 
 /**
@@ -68,13 +64,6 @@ import org.apache.sis.util.resources.Errors;
  */
 @SuppressWarnings("serial")     // Not intended to be serialized.
 public final class StandardDateFormat extends DateFormat {
-    /**
-     * The {@value} timezone ID.
-     *
-     * @see ZoneOffset#UTC
-     */
-    public static final String UTC = "UTC";
-
     /**
      * Midnight (00:00) UTC.
      */
@@ -219,140 +208,6 @@ replace:    if (Character.isWhitespace(c)) {
         return text.subSequence(lower, upper);
     }
 
-    /**
-     * The length of a day in number of seconds.
-     * Can be casted to {@code float} with exact precision.
-     */
-    public static final int SECONDS_PER_DAY = 24*60*60;
-
-    /**
-     * The length of a day in number of milliseconds.
-     * Can be casted to {@code float} with exact precision.
-     */
-    public static final int MILLISECONDS_PER_DAY = SECONDS_PER_DAY*1000;
-
-    /**
-     * Number of milliseconds in one second.
-     * Can be casted to {@code float} with exact precision.
-     */
-    public static final int MILLIS_PER_SECOND = 1000;
-
-    /**
-     * Number of nanoseconds in one millisecond.
-     * Can be casted to {@code float} with exact precision.
-     */
-    public static final int NANOS_PER_MILLISECOND = 1000_000;
-
-    /**
-     * Number of nanoseconds in one second.
-     * Can be casted to {@code float} with exact precision.
-     */
-    public static final int NANOS_PER_SECOND = 1000_000_000;
-
-    /**
-     * Length of a year as defined by the International Union of Geological 
Sciences (IUGS), in milliseconds.
-     * This is the unit of measurement used in EPSG geodetic dataset 
(EPSG:1029).
-     */
-    public static final long MILLIS_PER_TROPICAL_YEAR = 31556925445L;
-
-    /**
-     * Converts the given temporal object into an instant.
-     * If the timezone is unspecified, then UTC is assumed.
-     *
-     * @param  date  the temporal object to convert, or {@code null}.
-     * @param  zone  the timezone to use if the time is local, or {@code null} 
if none.
-     * @return the instant for the given temporal object, or {@code null} if 
the argument was null.
-     * @throws DateTimeException if the given date does not support a field 
required by this method.
-     */
-    public static Instant toInstant(final TemporalAccessor date, final ZoneId 
zone) {
-        if (date == null) {
-            return null;
-        }
-        if (date instanceof Instant) {
-            return (Instant) date;
-        } else if (date instanceof OffsetDateTime) {
-            return ((OffsetDateTime) date).toInstant();
-        } else if (date instanceof ChronoZonedDateTime) {
-            return ((ChronoZonedDateTime) date).toInstant();
-        } else if (zone != null) {
-            if (date instanceof LocalDateTime) {
-                final var t = (LocalDateTime) date;
-                if (zone instanceof ZoneOffset) {
-                    return t.atOffset((ZoneOffset) zone).toInstant();
-                } else {
-                    return t.atZone(zone).toInstant();
-                }
-            } else if (date instanceof LocalDate) {
-                final var t = (LocalDate) date;
-                return t.atStartOfDay(zone).toInstant();
-            }
-        }
-        Instant time;
-        final ChronoField nano;
-        if (zone == null || date.isSupported(ChronoField.INSTANT_SECONDS)) {
-            time = 
Instant.ofEpochSecond(date.getLong(ChronoField.INSTANT_SECONDS));
-            nano = ChronoField.NANO_OF_SECOND;
-        } else if (zone.equals(ZoneOffset.UTC)) {
-            // Note that the timezone of the temporal value is unknown here. 
We assume UTC.
-            time = 
Instant.ofEpochSecond(Math.multiplyExact(date.getLong(ChronoField.EPOCH_DAY), 
SECONDS_PER_DAY));
-            nano = ChronoField.NANO_OF_DAY;
-        } else {
-            throw new 
DateTimeException(Errors.format(Errors.Keys.CanNotConvertFromType_2, 
date.getClass(), Instant.class));
-        }
-        if (date.isSupported(nano)) {
-            time = time.plusNanos(date.getLong(nano));
-        }
-        return time;
-    }
-
-    /**
-     * Adds the given amount of seconds to the given instant.
-     *
-     * @param  time   the instant to which to add seconds, or {@code null}.
-     * @param  value  number of seconds.
-     * @return the shifted time, or {@code null} if the given instant was null 
or the given value was NaN.
-     */
-    public static Instant addSeconds(final Instant time, final double value) {
-        if (time == null || Double.isNaN(value)) {
-            return null;
-        }
-        final long r = Math.round(value);
-        return time.plusSeconds(r).plusNanos(Math.round((value - r) * 
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;
-    }
-
     /**
      * The {@code java.time} parser and formatter. This is usually the {@link 
#FORMAT} instance
      * unless a different locale or timezone has been specified.
@@ -391,7 +246,7 @@ replace:    if (Character.isWhitespace(c)) {
      */
     public StandardDateFormat(final Locale locale, final TimeZone zone) {
         this(locale);
-        if (!UTC.equals(zone.getID())) {
+        if (!Constants.UTC.equals(zone.getID())) {
             setTimeZone(zone);
         }
     }
@@ -507,7 +362,7 @@ replace:    if (Character.isWhitespace(c)) {
     @Override
     public Date parse(final String text, final ParsePosition position) {
         try {
-            return Date.from(toInstant(format.parse(text, position), 
getZone()));
+            return Date.from(TemporalDate.toInstant(format.parse(text, 
position), getZone()));
         } catch (DateTimeException | ArithmeticException e) {
             position.setErrorIndex(getErrorIndex(e, position));
             return null;
@@ -524,7 +379,7 @@ replace:    if (Character.isWhitespace(c)) {
     @Override
     public Date parse(final String text) throws ParseException {
         try {
-            return Date.from(toInstant(format.parse(toISO(text, 0, 
text.length())), getZone()));
+            return Date.from(TemporalDate.toInstant(format.parse(toISO(text, 
0, text.length())), getZone()));
         } catch (RuntimeException e) {
             throw (ParseException) new ParseException(e.getLocalizedMessage(), 
getErrorIndex(e, null)).initCause(e);
         }
diff --git 
a/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
new file mode 100644
index 0000000000..ed081ca8c3
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.util/main/org/apache/sis/util/privy/TemporalDate.java
@@ -0,0 +1,236 @@
+/*
+ * 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.util.privy;
+
+import java.util.Date;
+import java.time.DateTimeException;
+import java.time.Instant;
+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;
+import java.time.chrono.ChronoZonedDateTime;
+import org.apache.sis.util.resources.Errors;
+
+
+/**
+ * A date which is wrapping a {@code java.time} temporal object.
+ * This is used for interoperability in a situation where we are mixing
+ * legacy API working on {@link Date} with newer API working on {@link 
Temporal}.
+ *
+ * <h2>Design note</h2>
+ * This class intentionally don't implement {@link Temporal} in order to force 
unwrapping
+ * if a temporal object is desired.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public final class TemporalDate extends Date {     // Intentionally do not 
implement Temporal.
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 8239300258490556354L;
+
+    /**
+     * The temporal object wrapped by this date.
+     */
+    @SuppressWarnings("serial")     // Most implementations are serializable.
+    private final Temporal temporal;
+
+    /**
+     * Creates a new date for the given instant.
+     *
+     * @param  temporal the temporal object to wrap in a new date.
+     * @throws ArithmeticException if numeric overflow occurs.
+     */
+    private TemporalDate(final Instant temporal) {
+        super(temporal.toEpochMilli());
+        this.temporal = temporal;
+    }
+
+    /**
+     * Creates a new date for the given temporal.
+     *
+     * @param  temporal the temporal object to wrap in a new date.
+     * @throws ArithmeticException if numeric overflow occurs.
+     */
+    private TemporalDate(final Temporal temporal) {
+        super(toInstant(temporal, ZoneOffset.UTC).toEpochMilli());
+        this.temporal = temporal;
+    }
+
+    /**
+     * Returns the given temporal object as a date.
+     * Used for interoperability in situations where old and new Java API are 
mixed.
+     *
+     * @param  time  the temporal object to return as a date, or {@code null}.
+     * @return the given temporal object as a date, or {@code null} if the 
given argument was null.
+     * @throws ArithmeticException if numeric overflow occurs.
+     */
+    public static Date toDate(final Temporal time) {
+        return (time == null) ? null : new TemporalDate(time);
+    }
+
+    /**
+     * Returns the given temporal object as a date.
+     * Used for interoperability in situations where old and new Java API are 
mixed.
+     *
+     * @param  time  the temporal object to return as a date, or {@code null}.
+     * @return the given temporal object as a date, or {@code null} if the 
given argument was null.
+     * @throws ArithmeticException if numeric overflow occurs.
+     */
+    public static Date toDate(final Instant time) {
+        return (time == null) ? null : new TemporalDate(time);
+    }
+
+    /**
+     * Returns the given date as a temporal object.
+     * Used for interoperability in situations where old and new Java API are 
mixed.
+     *
+     * @param  time  the date to return as a temporal object, or {@code null}.
+     * @return the given date as a temporal object, or {@code null} if the 
given argument was null.
+     */
+    public static Temporal toTemporal(final Date time) {
+        return (time == null) ? null : (time instanceof TemporalDate) ? 
((TemporalDate) time).temporal : time.toInstant();
+    }
+
+    /**
+     * Returns the given date as an instant object.
+     * Used for interoperability in situations where old and new Java API are 
mixed.
+     *
+     * @param  time  the date to return as an instant object, or {@code null}.
+     * @return the given date as an instant object, or {@code null} if the 
given argument was null.
+     */
+    public static Instant toInstant(final Date time) {
+        return (time == null) ? null : time.toInstant();
+    }
+
+    /**
+     * Converts the given temporal object into an instant.
+     * If the timezone is unspecified, then UTC is assumed.
+     *
+     * @param  date  the temporal object to convert, or {@code null}.
+     * @param  zone  the timezone to use if the time is local, or {@code null} 
if none.
+     * @return the instant for the given temporal object, or {@code null} if 
the argument was null.
+     * @throws DateTimeException if the given date does not support a field 
required by this method.
+     */
+    public static Instant toInstant(final TemporalAccessor date, final ZoneId 
zone) {
+        if (date == null) {
+            return null;
+        }
+        if (date instanceof Instant) {
+            return (Instant) date;
+        } else if (date instanceof OffsetDateTime) {
+            return ((OffsetDateTime) date).toInstant();
+        } else if (date instanceof ChronoZonedDateTime) {
+            return ((ChronoZonedDateTime) date).toInstant();
+        } else if (zone != null) {
+            if (date instanceof LocalDateTime) {
+                final var t = (LocalDateTime) date;
+                if (zone instanceof ZoneOffset) {
+                    return t.atOffset((ZoneOffset) zone).toInstant();
+                } else {
+                    return t.atZone(zone).toInstant();
+                }
+            } else if (date instanceof LocalDate) {
+                final var t = (LocalDate) date;
+                return t.atStartOfDay(zone).toInstant();
+            }
+        }
+        Instant time;
+        final ChronoField nano;
+        if (zone == null || date.isSupported(ChronoField.INSTANT_SECONDS)) {
+            time = 
Instant.ofEpochSecond(date.getLong(ChronoField.INSTANT_SECONDS));
+            nano = ChronoField.NANO_OF_SECOND;
+        } else if (zone.equals(ZoneOffset.UTC)) {
+            // Note that the timezone of the temporal value is unknown here. 
We assume UTC.
+            time = 
Instant.ofEpochSecond(Math.multiplyExact(date.getLong(ChronoField.EPOCH_DAY), 
Constants.SECONDS_PER_DAY));
+            nano = ChronoField.NANO_OF_DAY;
+        } else {
+            throw new 
DateTimeException(Errors.format(Errors.Keys.CanNotConvertFromType_2, 
date.getClass(), Instant.class));
+        }
+        if (date.isSupported(nano)) {
+            time = time.plusNanos(date.getLong(nano));
+        }
+        return time;
+    }
+
+    /**
+     * Returns this date as an instant.
+     */
+    @Override
+    public Instant toInstant() {
+        if (temporal instanceof Instant) {
+            return (Instant) temporal;
+        }
+        return super.toInstant();
+    }
+
+    /**
+     * Adds the given amount of seconds to the given instant.
+     *
+     * @param  time   the instant to which to add seconds, or {@code null}.
+     * @param  value  number of seconds.
+     * @return the shifted time, or {@code null} if the given instant was null 
or the given value was NaN.
+     */
+    public static Instant addSeconds(final Instant time, final double value) {
+        if (time == null || Double.isNaN(value)) {
+            return null;
+        }
+        final long r = Math.round(value);
+        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;
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/RangeFormatTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/RangeFormatTest.java
index eeae5b3436..7e2772dab1 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/RangeFormatTest.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/measure/RangeFormatTest.java
@@ -30,7 +30,7 @@ import java.text.AttributedCharacterIterator;
 import static java.lang.StrictMath.*;
 import static java.lang.Double.POSITIVE_INFINITY;
 import static java.lang.Double.NEGATIVE_INFINITY;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
index a8e8616a97..5222779e1d 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/test/TestUtilities.java
@@ -47,7 +47,7 @@ import org.apache.sis.util.collection.TreeTable;
 import org.apache.sis.util.collection.TableColumn;
 import org.apache.sis.util.collection.TreeTableFormat;
 import org.apache.sis.util.privy.X364;
-import static org.apache.sis.util.privy.StandardDateFormat.UTC;
+import static org.apache.sis.util.privy.Constants.UTC;
 
 // Test dependencies
 import static org.junit.jupiter.api.Assertions.*;
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/CacheTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/CacheTest.java
index fe06e325bd..9c92a1e71d 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/CacheTest.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/CacheTest.java
@@ -29,7 +29,7 @@ import static java.lang.StrictMath.*;
 import org.apache.sis.math.Statistics;
 import org.apache.sis.math.StatisticsFormat;
 import org.apache.sis.util.CharSequences;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 
 // Test dependencies
 import org.junit.jupiter.api.Tag;
@@ -290,7 +290,7 @@ public final class CacheTest extends TestCaseWithGC {
         for (int i=0; i<10; i++) {
             final long t = System.nanoTime();
             out.printf("Cache size: %4d (after %3d ms)%n", cache.size(),
-                       round((t - time) / (double) 
StandardDateFormat.NANOS_PER_MILLISECOND));
+                       round((t - time) / (double) 
Constants.NANOS_PER_MILLISECOND));
             time = t;
             Thread.sleep(250);
             if (i >= 2) {
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/RangeSetTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/RangeSetTest.java
index 2e216b82d2..685210ca4a 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/RangeSetTest.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/collection/RangeSetTest.java
@@ -25,8 +25,8 @@ import java.util.Collections;
 import java.util.SortedSet;
 import org.apache.sis.measure.Range;
 import org.apache.sis.measure.NumberRange;
-import static 
org.apache.sis.util.privy.StandardDateFormat.MILLISECONDS_PER_DAY;
-import static org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_SECOND;
+import static org.apache.sis.util.privy.Constants.MILLISECONDS_PER_DAY;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_SECOND;
 
 // Test dependencies
 import org.junit.jupiter.api.Test;
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/ConstantsTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/ConstantsTest.java
new file mode 100644
index 0000000000..aab12ffd2f
--- /dev/null
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/ConstantsTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.util.privy;
+
+import java.util.concurrent.TimeUnit;
+
+// Test dependencies
+import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.*;
+import org.apache.sis.test.TestCase;
+
+
+/**
+ * Tests the {@link ConstantsTest} class.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ */
+public final class ConstantsTest extends TestCase {
+    /**
+     * Creates a new test case.
+     */
+    public ConstantsTest() {
+    }
+
+    /**
+     * Verifies the constant values related to time duration.
+     */
+    @Test
+    public void verifyConstantValues() {
+        assertEquals(TimeUnit.DAYS.toSeconds(1),       
Constants.SECONDS_PER_DAY);
+        assertEquals(TimeUnit.DAYS.toMillis(1),        
Constants.MILLISECONDS_PER_DAY);
+        assertEquals(TimeUnit.DAYS.toNanos(1),         
Constants.NANOSECONDS_PER_DAY);
+        assertEquals(TimeUnit.MILLISECONDS.toNanos(1), 
Constants.NANOS_PER_MILLISECOND);
+        assertEquals(TimeUnit.SECONDS.toNanos(1),      
Constants.NANOS_PER_SECOND);
+        assertEquals(365.24219 * (24*60*60 * 1000),    
Constants.MILLIS_PER_TROPICAL_YEAR, 0.00001 * (24*60*60 * 1000));
+    }
+}
diff --git 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
index 44658ca20b..d20a8c7adf 100644
--- 
a/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
+++ 
b/endorsed/src/org.apache.sis.util/test/org/apache/sis/util/privy/StandardDateFormatTest.java
@@ -20,7 +20,6 @@ import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.Date;
-import java.util.concurrent.TimeUnit;
 import java.text.ParseException;
 
 // Test dependencies
@@ -42,19 +41,6 @@ public final class StandardDateFormatTest extends TestCase {
     public StandardDateFormatTest() {
     }
 
-    /**
-     * Verifies the {@link StandardDateFormat#MILLISECONDS_PER_DAY}, {@link 
StandardDateFormat#NANOS_PER_MILLISECOND}
-     * and {@link StandardDateFormat#NANOS_PER_SECOND} constant values.
-     */
-    @Test
-    public void verifyConstantValues() {
-        assertEquals(TimeUnit.DAYS.toSeconds(1),       
StandardDateFormat.SECONDS_PER_DAY);
-        assertEquals(TimeUnit.DAYS.toMillis(1),        
StandardDateFormat.MILLISECONDS_PER_DAY);
-        assertEquals(TimeUnit.MILLISECONDS.toNanos(1), 
StandardDateFormat.NANOS_PER_MILLISECOND);
-        assertEquals(TimeUnit.SECONDS.toNanos(1),      
StandardDateFormat.NANOS_PER_SECOND);
-        assertEquals(365.24219 * (24*60*60 * 1000),    
StandardDateFormat.MILLIS_PER_TROPICAL_YEAR, 0.00001 * (24*60*60 * 1000));
-    }
-
     /**
      * Tests {@link StandardDateFormat#toISO(CharSequence, int, int)}.
      */
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
index a7ee91086e..92b01353e6 100644
--- a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
+++ b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/map/MapCanvas.java
@@ -89,7 +89,7 @@ import org.apache.sis.portrayal.PlanarCanvas;
 import org.apache.sis.portrayal.RenderException;
 import org.apache.sis.portrayal.TransformChangeEvent;
 import static org.apache.sis.gui.internal.LogHandler.LOGGER;
-import static 
org.apache.sis.util.privy.StandardDateFormat.NANOS_PER_MILLISECOND;
+import static org.apache.sis.util.privy.Constants.NANOS_PER_MILLISECOND;
 
 // Specific to the geoapi-3.1 and geoapi-4.0 branches:
 import org.opengis.coordinate.MismatchedDimensionException;
diff --git 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
index 92e0c60078..78301442fd 100644
--- 
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
+++ 
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/AuthorityCodes.java
@@ -41,7 +41,7 @@ import org.apache.sis.util.iso.Types;
 import org.apache.sis.util.logging.Logging;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.collection.BackingStoreException;
-import org.apache.sis.util.privy.StandardDateFormat;
+import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.Strings;
 import org.apache.sis.gui.internal.BackgroundThreads;
 import static org.apache.sis.gui.internal.LogHandler.LOGGER;
@@ -67,7 +67,7 @@ final class AuthorityCodes extends ObservableListBase<Code>
      * The delay value is a compromise between fast user experience and giving 
enough time for doing a few
      * large data transfers instead of many small data transfers.
      */
-    private static final long REFRESH_DELAY = 
StandardDateFormat.NANOS_PER_SECOND / 10;
+    private static final long REFRESH_DELAY = Constants.NANOS_PER_SECOND / 10;
 
     /**
      * The table view which use this list, or {@code null} if we don't need 
this information anymore.
@@ -447,7 +447,7 @@ final class AuthorityCodes extends ObservableListBase<Code>
                  * the `toDescribe` list to be populated with more requests, 
then process them.
                  */
                 if (codes.isEmpty()) {
-                    Thread.sleep(REFRESH_DELAY / 
StandardDateFormat.NANOS_PER_MILLISECOND);
+                    Thread.sleep(REFRESH_DELAY / 
Constants.NANOS_PER_MILLISECOND);
                     return new PartialResult(null, 
processNameRequests(factory));
                 }
             } catch (BackingStoreException e) {

Reply via email to