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 9b2fe86 `RangeFormat` should accept ranges of objects from the
`java.time` package (at lest the main types).
9b2fe86 is described below
commit 9b2fe865ae3c2a64d588084b00c0ef679b04cbb3
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Mar 17 00:06:56 2021 +0100
`RangeFormat` should accept ranges of objects from the `java.time` package
(at lest the main types).
---
.../sis/internal/util/StandardDateFormat.java | 39 ++++++++++++++++++-
.../main/java/org/apache/sis/measure/Range.java | 2 +-
.../java/org/apache/sis/measure/RangeFormat.java | 38 ++++++++++++++++---
.../org/apache/sis/measure/RangeFormatTest.java | 44 +++++++++++++++++++++-
.../java/org/apache/sis/measure/RangeTest.java | 16 +++++++-
5 files changed, 128 insertions(+), 11 deletions(-)
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
index 75fd103..9f9cc38 100644
---
a/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
+++
b/core/sis-utility/src/main/java/org/apache/sis/internal/util/StandardDateFormat.java
@@ -27,12 +27,14 @@ 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;
@@ -50,9 +52,9 @@ import org.apache.sis.util.CharSequences;
* the time is optional. For this class, "Standard" is interpreted as "close
to ISO 19162 requirements",
* which is not necessarily identical to other ISO standards.
*
- * External users should use nothing else than the parsing and formatting
methods.
+ * <p>External users should use nothing else than the parsing and formatting
methods.
* The methods for configuring the {@code DateFormat} instances may or may not
work
- * depending on the branch.
+ * depending on the branch.</p>
*
* <p>The main usage for this class is Well Known Text (WKT) parsing and
formatting.
* ISO 19162 uses ISO 8601:2004 for the dates. Any precision is allowed: the
date could have only the year,
@@ -312,6 +314,39 @@ replace: if (Character.isWhitespace(c)) {
}
/**
+ * 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.
*/
diff --git a/core/sis-utility/src/main/java/org/apache/sis/measure/Range.java
b/core/sis-utility/src/main/java/org/apache/sis/measure/Range.java
index 14d22f1..5cb6f5c 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/measure/Range.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/measure/Range.java
@@ -721,7 +721,7 @@ public class Range<E extends Comparable<? super E>>
implements CheckedContainer<
}
/**
- * Formats this range using the provider formatter. This method is invoked
when a
+ * Formats this range using the provided formatter. This method is invoked
when a
* {@code Range} object is formatted using the {@code "%s"} conversion
specifier of
* {@link Formatter}. Users don't need to invoke this method explicitly.
*
diff --git
a/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java
b/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java
index 50e2796..cb21a87 100644
--- a/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java
+++ b/core/sis-utility/src/main/java/org/apache/sis/measure/RangeFormat.java
@@ -31,6 +31,10 @@ import java.text.AttributedCharacterIterator;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.ParsePosition;
+import java.time.format.FormatStyle;
+import java.time.format.DateTimeFormatterBuilder;
+import java.time.temporal.Temporal;
+import java.time.Instant;
import java.security.AccessController;
import javax.measure.Unit;
import org.apache.sis.util.Numbers;
@@ -39,6 +43,7 @@ import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.util.UnconvertibleObjectException;
import org.apache.sis.internal.util.LocalizedParseException;
+import org.apache.sis.internal.util.StandardDateFormat;
import org.apache.sis.internal.util.FinalFieldSetter;
import org.apache.sis.internal.util.Numerics;
@@ -94,7 +99,7 @@ import org.apache.sis.internal.util.Numerics;
* </ul>
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
*
* @see Range#toString()
* @see <a href="https://en.wikipedia.org/wiki/ISO_31-11">Wikipedia: ISO
31-11</a>
@@ -358,9 +363,14 @@ public class RangeFormat extends Format implements
Localized {
} else if (Number.class.isAssignableFrom(elementType)) {
elementFormat = NumberFormat.getNumberInstance(locale);
unitFormat = new UnitFormat(locale);
- } else if (Date.class.isAssignableFrom(elementType)) {
+ } else if (Date.class.isAssignableFrom(elementType) || elementType ==
Instant.class) {
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;
+ elementFormat = new
DateTimeFormatterBuilder().appendLocalized(dateStyle,
timeStyle).toFormatter(locale).toFormat();
+ unitFormat = null;
} else {
throw new
IllegalArgumentException(Errors.format(Errors.Keys.UnsupportedType_1,
elementType));
}
@@ -528,7 +538,8 @@ public class RangeFormat extends Format implements
Localized {
/**
* Casts the given object to a {@code Range}, or throws an {@code
IllegalArgumentException}
- * if the given object is not a {@code Range} instance.
+ * if the given object is not a {@code Range} instance. This is used for
validating argument
+ * of {@link Object} type in formatting methods.
*/
private static Range<?> cast(final Object range) throws
IllegalArgumentException {
if (range instanceof Range<?>) {
@@ -610,8 +621,8 @@ public class RangeFormat extends Format implements
Localized {
for (; field <= UNIT_FIELD; field++) {
final Object value;
switch (field) {
- case MIN_VALUE_FIELD: value = minValue; break;
- case MAX_VALUE_FIELD: value = maxValue; break;
+ case MIN_VALUE_FIELD: value = toFormattable(minValue); break;
+ case MAX_VALUE_FIELD: value = toFormattable(maxValue); break;
case UNIT_FIELD: value = range.unit(); break;
default: throw new AssertionError(field);
}
@@ -1016,7 +1027,8 @@ public class RangeFormat extends Format implements
Localized {
}
/**
- * Converts the given value to the a {@link #elementType} type.
+ * Converts the given value to an instance of the {@link #elementType}
type.
+ * This method is partially the converse of {@link #toFormattable(Object)}.
*/
@SuppressWarnings("unchecked")
private Object convert(final Object value) throws
UnconvertibleObjectException {
@@ -1026,11 +1038,25 @@ public class RangeFormat extends Format implements
Localized {
if (value instanceof Number &&
Number.class.isAssignableFrom(elementType)) {
return Numbers.cast((Number) value, (Class<? extends Number>)
elementType);
}
+ if (value instanceof Date && elementType == Instant.class) {
+ return ((Date) value).toInstant();
+ }
throw new UnconvertibleObjectException(Errors.format(
Errors.Keys.IllegalClass_2, elementType, value.getClass()));
}
/**
+ * Converts the given object to a type that {@code format(…)} method can
process.
+ * This method is partially the converse of {@link #convert(Object)}.
+ */
+ private Object toFormattable(final Object value) {
+ if (value instanceof Instant && elementType == Instant.class) {
+ return Date.from((Instant) value);
+ }
+ return value;
+ }
+
+ /**
* Returns a "nil" value. This is used for creating empty ranges.
*/
private Object valueOfNil() {
diff --git
a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
index 0226cf2..ba197fa 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeFormatTest.java
@@ -19,6 +19,9 @@ package org.apache.sis.measure;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
+import java.time.Instant;
+import java.time.LocalTime;
+import java.time.LocalDate;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
@@ -39,7 +42,7 @@ import static
org.apache.sis.internal.util.StandardDateFormat.UTC;
* Tests parsing and formatting done by the {@link RangeFormat} class.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.8
+ * @version 1.1
* @since 0.3
* @module
*/
@@ -302,6 +305,45 @@ public final strictfp class RangeFormatTest extends
TestCase {
}
/**
+ * Tests formatting a range of {@link LocalDate} objects.
+ */
+ @Test
+ public void testFormatLocalDate() {
+ format = new RangeFormat(Locale.CANADA_FRENCH, LocalDate.class);
+ final Range<LocalDate> range = new Range<>(LocalDate.class,
+ LocalDate.parse("2019-12-23"), true,
+ LocalDate.parse("2020-05-31"), true);
+
+ assertEquals("[2019-12-23 … 2020-05-31]", format.format(range));
+ }
+
+ /**
+ * Tests formatting a range of {@link LocalTime} objects.
+ */
+ @Test
+ public void testFormatLocalTime() {
+ format = new RangeFormat(Locale.FRANCE, LocalTime.class);
+ final Range<LocalTime> range = new Range<>(LocalTime.class,
+ LocalTime.parse("06:00:00"), true,
+ LocalTime.parse("18:00:00"), true);
+
+ assertEquals("[06:00 … 18:00]", format.format(range));
+ }
+
+ /**
+ * Tests formatting a range of {@link Instant} objects.
+ */
+ @Test
+ public void testFormatInstant() {
+ format = new RangeFormat(Locale.FRANCE, Instant.class);
+ final Range<Instant> range = new Range<>(Instant.class,
+ Instant.parse("2019-12-23T06:00:00Z"), true,
+ Instant.parse("2020-05-31T18:00:00Z"), true);
+
+ assertEquals("[23/12/2019 07:00 … 31/05/2020 20:00]",
format.format(range));
+ }
+
+ /**
* Tests the {@link RangeFormat#formatToCharacterIterator(Object)} method
with dates.
*/
@Test
diff --git
a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
index e00a646..d0732e3 100644
--- a/core/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
+++ b/core/sis-utility/src/test/java/org/apache/sis/measure/RangeTest.java
@@ -17,6 +17,7 @@
package org.apache.sis.measure;
import java.util.Locale;
+import java.time.Instant;
import org.apache.sis.test.TestCase;
import org.junit.Test;
@@ -28,7 +29,8 @@ import static org.apache.sis.test.Assert.*;
* Tests the {@link Range} class.
*
* @author Joe White
- * @version 0.3
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
* @since 0.3
* @module
*/
@@ -323,6 +325,18 @@ public final strictfp class RangeTest extends TestCase {
}
/**
+ * Tests the {@link Range#formatTo(Formatter, int, int, int)} method with
a range of instants.
+ */
+ @Test
+ public void testFormatInstantTo() {
+ final Range<Instant> range = new Range<>(Instant.class,
+ Instant.parse("2019-12-23T06:00:00Z"), true,
+ Instant.parse("2020-05-31T18:00:00Z"), true);
+
+ assertEquals("[23/12/2019 07:00 … 31/05/2020 20:00]",
String.format(Locale.FRANCE, "%s", range));
+ }
+
+ /**
* Tests the {@link Range#equals(Object)} method.
*/
@Test