From bf6452a475745c9da2d786f800e4f406020cdb64 Mon Sep 17 00:00:00 2001 From: Bart Hanssens Date: Fri, 2 Sep 2022 15:06:22 +0100 Subject: [PATCH] GH-4104: fix issue with Instant, turn it into datetimestamp value Signed-off-by:Bart Hanssens --- .../rdf4j/model/base/AbstractLiteral.java | 22 ++++++++++++++----- .../eclipse/rdf4j/model/util/ValuesTest.java | 13 +++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java index 0dc34b6d93f..1a3043dc008 100644 --- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java +++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/base/AbstractLiteral.java @@ -14,6 +14,7 @@ import static java.lang.Math.abs; import static java.time.temporal.ChronoField.DAY_OF_MONTH; import static java.time.temporal.ChronoField.HOUR_OF_DAY; +import static java.time.temporal.ChronoField.INSTANT_SECONDS; import static java.time.temporal.ChronoField.MINUTE_OF_HOUR; import static java.time.temporal.ChronoField.MONTH_OF_YEAR; import static java.time.temporal.ChronoField.NANO_OF_SECOND; @@ -522,7 +523,7 @@ static class TemporalAccessorLiteral extends AbstractLiteral { private static final ChronoField[] FIELDS = { YEAR, MONTH_OF_YEAR, DAY_OF_MONTH, HOUR_OF_DAY, MINUTE_OF_HOUR, SECOND_OF_MINUTE, NANO_OF_SECOND, - OFFSET_SECONDS + OFFSET_SECONDS, INSTANT_SECONDS }; private static final DateTimeFormatter LOCAL_TIME_FORMATTER = new DateTimeFormatterBuilder() @@ -584,6 +585,12 @@ static class TemporalAccessorLiteral extends AbstractLiteral { .toFormatter(); + private static final DateTimeFormatter DATETIMESTAMP_FORMATTER = new DateTimeFormatterBuilder() + + .appendInstant() + + .toFormatter(); + private static final DateTimeFormatter DASH_FORMATTER = new DateTimeFormatterBuilder() .appendLiteral("--") @@ -620,13 +627,16 @@ private static Map datatypes() { int time = key(HOUR_OF_DAY, MINUTE_OF_HOUR, SECOND_OF_MINUTE); int nano = key(NANO_OF_SECOND); int zone = key(OFFSET_SECONDS); + int instant = key(INSTANT_SECONDS); Map datatypes = new HashMap<>(); - datatypes.put(date + time, CoreDatatype.XSD.DATETIME); datatypes.put(date + time + nano, CoreDatatype.XSD.DATETIME); datatypes.put((date + time + zone), CoreDatatype.XSD.DATETIME); datatypes.put((date + time + nano + zone), CoreDatatype.XSD.DATETIME); + datatypes.put((date + time + instant + zone), CoreDatatype.XSD.DATETIME); + datatypes.put((date + time + instant + nano + zone), CoreDatatype.XSD.DATETIME); + datatypes.put((instant + nano), CoreDatatype.XSD.DATETIMESTAMP); datatypes.put(time, CoreDatatype.XSD.TIME); datatypes.put(time + nano, CoreDatatype.XSD.TIME); @@ -649,6 +659,7 @@ private static Map formatters() { final Map formatters = new EnumMap<>(CoreDatatype.XSD.class); + formatters.put(CoreDatatype.XSD.DATETIMESTAMP, DATETIMESTAMP_FORMATTER); formatters.put(CoreDatatype.XSD.DATETIME, DATETIME_FORMATTER); formatters.put(CoreDatatype.XSD.TIME, OFFSET_TIME_FORMATTER); formatters.put(CoreDatatype.XSD.DATE, OFFSET_DATE_FORMATTER); @@ -705,18 +716,17 @@ private static int key(Predicate include, ChronoField... fields) { private final CoreDatatype.XSD datatype; TemporalAccessorLiteral(TemporalAccessor value) { - this.value = value; - datatype = DATATYPES.get(key(value)); + datatype = DATATYPES.get(key(this.value)); if (datatype == null) { throw new IllegalArgumentException(String.format( - "value <%s> cannot be represented by an XML Schema date/time datatype", value + "value <%s> cannot be represented by an XML Schema date/time datatype", this.value )); } - this.label = FORMATTERS.get(datatype).format(value); + this.label = FORMATTERS.get(datatype).format(this.value); } @Override diff --git a/core/model/src/test/java/org/eclipse/rdf4j/model/util/ValuesTest.java b/core/model/src/test/java/org/eclipse/rdf4j/model/util/ValuesTest.java index 13965f01617..3e814ebaa4f 100644 --- a/core/model/src/test/java/org/eclipse/rdf4j/model/util/ValuesTest.java +++ b/core/model/src/test/java/org/eclipse/rdf4j/model/util/ValuesTest.java @@ -23,6 +23,7 @@ import java.math.BigDecimal; import java.math.BigInteger; +import java.time.Instant; import java.time.LocalDateTime; import java.time.Period; import java.util.Date; @@ -508,6 +509,18 @@ public void testTemporalAccessorLiteralNull() { } + @Test + public void testTemporalAccessorLiteralInstant() { + final Instant value = Instant.ofEpochSecond(1234567890, 12); + Literal literal = literal(value); + + assertThat(literal).isNotNull(); + assertThat(literal.temporalAccessorValue()).isEqualTo(value); + assertThat(literal.getLabel()).isEqualTo(value.toString()); + assertThat(literal.getDatatype()).isEqualTo(XSD.DATETIMESTAMP); + assertThat(literal.getCoreDatatype()).isEqualTo(CoreDatatype.XSD.DATETIMESTAMP); + } + @Test public void testTriple() { Triple triple = triple(RDF.ALT, RDF.TYPE, RDFS.CONTAINER);