Repository: Wikidata/Wikidata-Toolkit
Pull request #443 (2019-09-27 11:11:48)

Improvements to export of RDF time values
I've recently looked a bit at differences between WIkidata-Toolkit's RDF generation and the data in the Wikidata RDF dumps. I noticed quite a few differences in how dates are treated, which this PR removes. 

One issue that's not part of this PR yet is handling of year 0, as I still need to look into how that works exactly. Also the year adjustment for years < 0 is unclear to me, I found that most often I had to add one instead of subtract one to get the year that wikidata has in its dumps (I will change that when I have looked into that difference more throughly). 


Patch:
diff --git a/pom.xml b/pom.xml
index 58023235..3d85ea58 100644
--- a/pom.xml
+++ b/pom.xml
@@ -82,6 +82,7 @@
 		<mockitoVersion>1.10.19</mockitoVersion>
 		<rdf4jVersion>2.5.2</rdf4jVersion>
 		<slf4jVersion>1.7.26</slf4jVersion>
+		<threetenVersion>1.5.0</threetenVersion>
 	</properties>
 
 	<dependencies>
diff --git a/wdtk-datamodel/pom.xml b/wdtk-datamodel/pom.xml
index 9ee558d2..927d8301 100644
--- a/wdtk-datamodel/pom.xml
+++ b/wdtk-datamodel/pom.xml
@@ -41,6 +41,11 @@
 			<artifactId>jackson-databind</artifactId>
 			<version>${jacksonVersion}</version>
 		</dependency>
+		<dependency>
+			<groupId>org.threeten</groupId>
+			<artifactId>threeten-extra</artifactId>
+			<version>${threetenVersion}</version>
+		</dependency>
 	</dependencies>
 	
 	<build>
diff --git a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/EntityDocumentBuilder.java b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/EntityDocumentBuilder.java
index 7e6fee17..fe223bd9 100644
--- a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/EntityDocumentBuilder.java
+++ b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/EntityDocumentBuilder.java
@@ -47,7 +47,7 @@ import org.wikidata.wdtk.datamodel.interfaces.TermedStatementDocument;
 public abstract class EntityDocumentBuilder<T extends EntityDocumentBuilder<T, O>, O extends TermedStatementDocument>
 		extends AbstractDataObjectBuilder<T, O> {
 
-	EntityIdValue entityIdValue;
+	final EntityIdValue entityIdValue;
 	final ArrayList<MonolingualTextValue> labels = new ArrayList<>();
 	final ArrayList<MonolingualTextValue> descriptions = new ArrayList<>();
 	final ArrayList<MonolingualTextValue> aliases = new ArrayList<>();
@@ -98,19 +98,6 @@ public abstract class EntityDocumentBuilder<T extends EntityDocumentBuilder<T, O
 		this.revisionId = revisionId;
 		return getThis();
 	}
-	
-	/**
-	 * Changes the entity value id for the constructed document.
-	 * See {@link EntityDocument#getEntityId()}.
-	 * 
-	 * @param entityId
-	 *          the entity id
-	 * @return builder object to continue construction
-	 */
-	public T withEntityId(EntityIdValue entityId) {
-		this.entityIdValue = entityId;
-		return getThis();
-	}
 
 	/**
 	 * Adds an additional label to the constructed document.
diff --git a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilder.java b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilder.java
index 7bf52cf2..726f6493 100644
--- a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilder.java
+++ b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilder.java
@@ -23,8 +23,6 @@ package org.wikidata.wdtk.datamodel.helpers;
 import java.util.Arrays;
 import java.util.HashMap;
 
-import org.wikidata.wdtk.datamodel.interfaces.EntityDocument;
-import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.ItemDocument;
 import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.SiteLink;
@@ -125,22 +123,6 @@ public class ItemDocumentBuilder extends
 		withSiteLink(factory.getSiteLink(title, siteKey, Arrays.asList(badges)));
 		return this;
 	}
-	
-	/**
-	 * Changes the entity value id for the constructed document.
-	 * See {@link EntityDocument#getEntityId()}.
-	 * 
-	 * @param entityId
-	 *          the entity id, which must be an ItemIdValue
-	 * @return builder object to continue construction
-	 */
-	@Override
-	public ItemDocumentBuilder withEntityId(EntityIdValue entityId) {
-		if (!(entityId instanceof ItemIdValue)) {
-			throw new IllegalArgumentException("The entity id of an ItemDocument must be an ItemIdValue.");
-		}
-		return super.withEntityId(entityId);
-	}
 
 	@Override
 	protected ItemDocumentBuilder getThis() {
diff --git a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilder.java b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilder.java
index 9bb25039..04766924 100644
--- a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilder.java
+++ b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilder.java
@@ -21,8 +21,6 @@ package org.wikidata.wdtk.datamodel.helpers;
  */
 
 import org.wikidata.wdtk.datamodel.interfaces.DatatypeIdValue;
-import org.wikidata.wdtk.datamodel.interfaces.EntityDocument;
-import org.wikidata.wdtk.datamodel.interfaces.EntityIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.ItemDocument;
 import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
 import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
@@ -105,22 +103,6 @@ public class PropertyDocumentBuilder extends
 		return forPropertyIdAndDatatype(propertyIdValue,
 				factory.getDatatypeIdValue(datatypeId));
 	}
-	
-	/**
-	 * Changes the entity value id for the constructed document.
-	 * See {@link EntityDocument#getEntityId()}.
-	 * 
-	 * @param entityId
-	 *          the entity id, which must be an ItemIdValue
-	 * @return builder object to continue construction
-	 */
-	@Override
-	public PropertyDocumentBuilder withEntityId(EntityIdValue entityId) {
-		if (!(entityId instanceof PropertyIdValue)) {
-			throw new IllegalArgumentException("The entity id of a PropertyDocument must be an PropertyIdValue.");
-		}
-		return super.withEntityId(entityId);
-	}
 
 	/**
 	 * Returns the {@link ItemDocument} that has been built.
diff --git a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImpl.java b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImpl.java
index ca512913..469b0b4a 100644
--- a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImpl.java
+++ b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImpl.java
@@ -20,7 +20,13 @@ package org.wikidata.wdtk.datamodel.implementation;
  * #L%
  */
 
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import org.apache.commons.lang3.Validate;
+import org.threeten.extra.chrono.JulianDate;
 import org.wikidata.wdtk.datamodel.helpers.Equality;
 import org.wikidata.wdtk.datamodel.helpers.Hash;
 import org.wikidata.wdtk.datamodel.helpers.ToString;
@@ -28,11 +34,9 @@ import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.TimeValue;
 import org.wikidata.wdtk.datamodel.interfaces.ValueVisitor;
 
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import com.fasterxml.jackson.annotation.JsonCreator;
-import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import java.time.DateTimeException;
+import java.time.LocalDate;
+import java.util.Optional;
 
 /**
  * Jackson implementation of {@link TimeValue}.
@@ -207,6 +211,36 @@ public class TimeValueImpl extends ValueImpl implements TimeValue {
 		return ToString.toString(this);
 	}
 
+	@Override
+	public Optional<TimeValue> toGregorian() {
+		// already in Gregorian calendar
+		if (this.getPreferredCalendarModel().equals(TimeValue.CM_GREGORIAN_PRO)) {
+			return Optional.of(this);
+		}
+
+		// convert Julian
+		if (this.getPreferredCalendarModel().equals(TimeValue.CM_JULIAN_PRO)
+				&& this.getPrecision() >= TimeValue.PREC_DAY
+				&& this.value.year > Integer.MIN_VALUE && this.value.year < Integer.MAX_VALUE
+		) {
+			try {
+				final JulianDate julian = JulianDate.of((int) this.value.year, this.value.month, this.value.day);
+				final LocalDate date = LocalDate.from(julian);
+				return Optional.of(new TimeValueImpl(
+						date.getYear(), (byte) date.getMonth().getValue(), (byte) date.getDayOfMonth(),
+						this.value.hour, this.value.minute, this.value.second,
+						(byte) this.value.precision, this.value.before, this.value.after,
+						this.value.timezone, TimeValue.CM_GREGORIAN_PRO
+				));
+			} catch(DateTimeException e) {
+				return Optional.empty();
+			}
+
+		}
+
+		return Optional.empty();
+	}
+
 	/**
 	 * Helper object that represents the JSON object structure of the value.
 	 */
diff --git a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/interfaces/TimeValue.java b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/interfaces/TimeValue.java
index 50f55ec0..6b5dff23 100644
--- a/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/interfaces/TimeValue.java
+++ b/wdtk-datamodel/src/main/java/org/wikidata/wdtk/datamodel/interfaces/TimeValue.java
@@ -20,6 +20,8 @@ package org.wikidata.wdtk.datamodel.interfaces;
  * #L%
  */
 
+import java.util.Optional;
+
 /**
  * Time values represent points and intervals in time, and additional
  * information about their format. Information includes a specific time point,
@@ -279,4 +281,13 @@ public interface TimeValue extends Value {
 	 */
 	int getAfterTolerance();
 
+	/**
+	 * Convert the value to the Gregorian calendar, if possible.
+	 * This conversion can fail if not enough information is available
+	 * (for example, we need at least day precision to convert from Julian to Gregorian).
+	 *
+	 * @return a TimeValue that uses the Gregorian calendar, or {@ref Optional::empty} if the conversion failed.
+	 */
+	Optional<TimeValue> toGregorian();
+
 }
diff --git a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/Vocabulary.java b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/Vocabulary.java
index 6538148a..4f50a0d0 100644
--- a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/Vocabulary.java
+++ b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/Vocabulary.java
@@ -554,6 +554,7 @@ public class Vocabulary {
 		md.update(value.getHour());
 		md.update(value.getMinute());
 		md.update(value.getSecond());
+		md.update(value.getPrecision());
 		updateMessageDigestWithString(md, value.getPreferredCalendarModel());
 		updateMessageDigestWithInt(md, value.getBeforeTolerance());
 		updateMessageDigestWithInt(md, value.getAfterTolerance());
diff --git a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/GlobeCoordinatesValueConverter.java b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/GlobeCoordinatesValueConverter.java
index b22571d6..a86d89db 100644
--- a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/GlobeCoordinatesValueConverter.java
+++ b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/GlobeCoordinatesValueConverter.java
@@ -105,9 +105,9 @@ public class GlobeCoordinatesValueConverter extends
 					.append("> ");
 		}
 		builder.append("Point(");
-		builder.append(value.getLongitude());
-		builder.append(" ");
 		builder.append(value.getLatitude());
+		builder.append(" ");
+		builder.append(value.getLongitude());
 		builder.append(")");
 		return this.rdfWriter.getLiteral(builder.toString(),
 				RdfWriter.OGC_LOCATION);
diff --git a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/QuantityValueConverter.java b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/QuantityValueConverter.java
index 22ab65d2..e0fb9d86 100644
--- a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/QuantityValueConverter.java
+++ b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/QuantityValueConverter.java
@@ -52,7 +52,7 @@ public class QuantityValueConverter extends
 			if (simple) {
 				this.rdfConversionBuffer.addDatatypeProperty(propertyIdValue);
 				return this.rdfWriter.getLiteral(value.getNumericValue()
-						.toPlainString(), RdfWriter.XSD_DECIMAL);
+						.toString(), RdfWriter.XSD_DECIMAL);
 			} else {
 				IRI valueUri = this.rdfWriter.getUri(Vocabulary.getQuantityValueUri(value));
 
@@ -73,16 +73,16 @@ public class QuantityValueConverter extends
 		this.rdfWriter.writeTripleValueObject(resource, RdfWriter.RDF_TYPE,
 				RdfWriter.WB_QUANTITY_VALUE);
 		this.rdfWriter.writeTripleLiteralObject(resource,
-				RdfWriter.WB_QUANTITY_AMOUNT, value.getNumericValue().toPlainString(),
+				RdfWriter.WB_QUANTITY_AMOUNT, value.getNumericValue().toString(),
 				RdfWriter.XSD_DECIMAL);
 		if(value.getLowerBound() != null) {
 			this.rdfWriter.writeTripleLiteralObject(resource,
-					RdfWriter.WB_QUANTITY_LOWER_BOUND, value.getLowerBound().toPlainString(),
+					RdfWriter.WB_QUANTITY_LOWER_BOUND, value.getLowerBound().toString(),
 					RdfWriter.XSD_DECIMAL);
 		}
 		if(value.getUpperBound() != null) {
 			this.rdfWriter.writeTripleLiteralObject(resource,
-					RdfWriter.WB_QUANTITY_UPPER_BOUND, value.getUpperBound().toPlainString(),
+					RdfWriter.WB_QUANTITY_UPPER_BOUND, value.getUpperBound().toString(),
 					RdfWriter.XSD_DECIMAL);
 		}
 		String unitIri = ("1".equals(value.getUnit()))
diff --git a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/TimeValueConverter.java b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/TimeValueConverter.java
index 278a6dfd..1423fee6 100644
--- a/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/TimeValueConverter.java
+++ b/wdtk-rdf/src/main/java/org/wikidata/wdtk/rdf/values/TimeValueConverter.java
@@ -33,6 +33,8 @@ import org.wikidata.wdtk.rdf.PropertyRegister;
 import org.wikidata.wdtk.rdf.RdfWriter;
 import org.wikidata.wdtk.rdf.Vocabulary;
 
+import java.time.Month;
+
 public class TimeValueConverter extends BufferedValueConverter<TimeValue> {
 
 	public TimeValueConverter(RdfWriter rdfWriter,
@@ -111,16 +113,60 @@ public class TimeValueConverter extends BufferedValueConverter<TimeValue> {
 	 * @return the RDF literal
 	 */
 	private static Literal getTimeLiteral(TimeValue value, RdfWriter rdfWriter) {
+		/* we need to check for year zero before julian date conversion,
+		 since that can change the year (if the date is 1 Jan 1 for example)
+		*/
+		boolean yearZero = value.getYear() == 0;
+
+		value = value.toGregorian().orElse(value);
+
 		long year = value.getYear();
 
-		//Year normalization
-		if (year == 0 || (year < 0 && value.getPrecision() >= TimeValue.PREC_YEAR)) {
-			year--;
+		/* https://www.mediawiki.org/wiki/Wikibase/DataModel/JSON#time says the following about the JSON mapping:
+
+		  The format used for Gregorian and Julian dates use a notation resembling ISO 8601. E.g. “+1994-01-01T00:00:00Z”.
+		  The year is represented by at least four digits, zeros are added on the left side as needed.
+		  Years BCE are represented as negative numbers, using the historical numbering, in which year 0 is undefined,
+		   and the year 1 BCE is represented as -0001, the year 44 BCE is represented as -0044, etc.,
+		   like XSD 1.0 (ISO 8601:1988) does.
+		  In contrast, the RDF mapping relies on XSD 1.1 (ISO 8601:2004) dates that use the proleptic Gregorian calendar
+		  and astronomical year numbering, where the year 1 BCE is represented as +0000 and the year 44 BCE
+		  is represented as -0043.
+		*/
+		// map negative dates from historical numbering to XSD 1.1
+		if (year < 0 && value.getPrecision() >= TimeValue.PREC_YEAR) {
+			year++;
+		}
+
+		byte month = value.getMonth();
+		byte day = value.getDay();
+
+		if ((value.getPrecision() < TimeValue.PREC_MONTH || month == 0) && !yearZero) {
+			month = 1;
 		}
 
-		String timestamp = String.format("%04d-%02d-%02dT%02d:%02d:%02dZ",
-				year, value.getMonth(), value.getDay(),
+		if ((value.getPrecision() < TimeValue.PREC_DAY || day == 0) && !yearZero) {
+			day = 1;
+		}
+
+		if (value.getPrecision() >= TimeValue.PREC_DAY && !yearZero) {
+			int maxDays = Byte.MAX_VALUE;
+			if (month > 0 && month < 13) {
+				boolean leap =  (year % 4L) == 0L && (year % 100L != 0L || year % 400L == 0L);
+				maxDays = Month.of(month).length(leap);
+			}
+			if (day > maxDays) {
+				day = (byte)maxDays;
+			}
+		}
+
+		String minus = year < 0 ? "-" : "";
+		String timestamp = String.format("%s%04d-%02d-%02dT%02d:%02d:%02dZ",
+				minus, Math.abs(year), month, day,
 				value.getHour(), value.getMinute(), value.getSecond());
+		if (yearZero) {
+			return rdfWriter.getLiteral("+" + timestamp);
+		}
 		return rdfWriter.getLiteral(timestamp, RdfWriter.XSD_DATETIME);
 	}
 


Test patch:
diff --git a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilderTest.java b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilderTest.java
index 05533dbb..0e625958 100644
--- a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilderTest.java
+++ b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/ItemDocumentBuilderTest.java
@@ -30,7 +30,6 @@ import org.junit.Test;
 import org.wikidata.wdtk.datamodel.interfaces.ItemDocument;
 import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.MonolingualTextValue;
-import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.SiteLink;
 import org.wikidata.wdtk.datamodel.interfaces.Statement;
 import org.wikidata.wdtk.datamodel.interfaces.StatementGroup;
@@ -119,26 +118,6 @@ public class ItemDocumentBuilderTest {
 		ItemDocument withAlias = ItemDocumentBuilder.fromItemDocument(initial).withAlias(alias3).build();
 		assertEquals(withAlias.getAliases().get("fr"), Arrays.asList(alias1, alias2, alias3));
 	}
-	
-	@Test
-	public void testChangeOfSubjectId() {
-		MonolingualTextValue label = Datamodel.makeMonolingualTextValue("pleutre",
-				"fr");
-		ItemDocument initial = Datamodel.makeItemDocument(i,
-				Collections.singletonList(label), Collections.emptyList(), Collections.emptyList(),
-				Collections.singletonList(sg),
-				Collections.emptyMap(), 4567);
-		
-		ItemDocument copy = ItemDocumentBuilder.fromItemDocument(initial).withEntityId(ItemIdValue.NULL).build();
-		
-		assertEquals(ItemIdValue.NULL, copy.getEntityId());
-		assertEquals("pleutre", copy.findLabel("fr"));
-	}
-	
-	@Test(expected = IllegalArgumentException.class)
-	public void testInvalidChangeOfSubjectId() {
-		ItemDocumentBuilder.forItemId(ItemIdValue.NULL).withRevisionId(1234).withEntityId(PropertyIdValue.NULL);
-	}
 
 	@Test(expected = IllegalStateException.class)
 	public void testDoubleBuild() {
diff --git a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilderTest.java b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilderTest.java
index 06b6f6fc..ee8dd915 100644
--- a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilderTest.java
+++ b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/helpers/PropertyDocumentBuilderTest.java
@@ -27,7 +27,6 @@ import java.util.Collections;
 
 import org.junit.Test;
 import org.wikidata.wdtk.datamodel.interfaces.DatatypeIdValue;
-import org.wikidata.wdtk.datamodel.interfaces.ItemIdValue;
 import org.wikidata.wdtk.datamodel.interfaces.MonolingualTextValue;
 import org.wikidata.wdtk.datamodel.interfaces.PropertyDocument;
 import org.wikidata.wdtk.datamodel.interfaces.PropertyIdValue;
@@ -75,9 +74,4 @@ public class PropertyDocumentBuilderTest {
 		PropertyDocument withAlias = PropertyDocumentBuilder.fromPropertyDocument(initial).withAlias(alias).build();
 		assertEquals(withAlias.getAliases().get("en"), Collections.singletonList(alias));
 	}
-	
-	@Test(expected = IllegalArgumentException.class)
-	public void testInvalidSubjectId() {
-		PropertyDocumentBuilder.forPropertyIdAndDatatype(PropertyIdValue.NULL, DatatypeIdValue.DT_EXTERNAL_ID).withEntityId(ItemIdValue.NULL);
-	}
 }
diff --git a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImplTest.java b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImplTest.java
index 30e22ea8..8d9c8897 100644
--- a/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImplTest.java
+++ b/wdtk-datamodel/src/test/java/org/wikidata/wdtk/datamodel/implementation/TimeValueImplTest.java
@@ -28,6 +28,7 @@ import org.junit.Test;
 import org.wikidata.wdtk.datamodel.interfaces.TimeValue;
 
 import java.io.IOException;
+import java.util.NoSuchElementException;
 
 public class TimeValueImplTest {
 
@@ -151,4 +152,23 @@ public class TimeValueImplTest {
 		assertEquals(t1, mapper.readValue(JSON_TIME_VALUE, ValueImpl.class));
 	}
 
+	@Test
+	public void testJulianToGregorian() {
+		final TimeValue tJulian = new TimeValueImpl(1143, (byte)10, (byte) 5, (byte) 1, (byte) 2,
+				(byte) 0, TimeValue.PREC_MINUTE, 0, 1, 0,
+				TimeValue.CM_JULIAN_PRO);
+		final TimeValue gregorian = tJulian.toGregorian().orElseThrow(NoSuchElementException::new);
+		assertEquals(1143, gregorian.getYear());
+		assertEquals(10, gregorian.getMonth());
+		assertEquals(12, gregorian.getDay());
+		assertEquals(1, gregorian.getHour());
+		assertEquals(2, gregorian.getMinute());
+		assertEquals(0, gregorian.getSecond());
+		assertEquals(TimeValue.PREC_MINUTE, gregorian.getPrecision());
+		assertEquals(0, gregorian.getBeforeTolerance());
+		assertEquals(1, gregorian.getAfterTolerance());
+		assertEquals(0, gregorian.getTimezoneOffset());
+		assertEquals(TimeValue.CM_GREGORIAN_PRO, gregorian.getPreferredCalendarModel());
+	}
+
 }
diff --git a/wdtk-rdf/src/test/resources/ItemDocument.rdf b/wdtk-rdf/src/test/resources/ItemDocument.rdf
index 2a543593..20048c8e 100644
--- a/wdtk-rdf/src/test/resources/ItemDocument.rdf
+++ b/wdtk-rdf/src/test/resources/ItemDocument.rdf
@@ -11,9 +11,9 @@
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
 
 <http://www.wikidata.org/entity/statement/Q10-none2> a <http://wikiba.se/ontology#Statement> , <http://wikiba.se/ontology#BestRank> ;
-	<http://www.wikidata.org/prop/statement/value/P569> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> ;
+	<http://www.wikidata.org/prop/statement/value/P569> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> ;
 	<http://www.wikidata.org/prop/statement/P569> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
-	<http://www.wikidata.org/prop/qualifier/value/P15> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> ;
+	<http://www.wikidata.org/prop/qualifier/value/P15> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> ;
 	<http://www.wikidata.org/prop/qualifier/P15> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
 	<http://www.w3.org/ns/prov#wasDerivedFrom> <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> ;
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
@@ -22,7 +22,7 @@
 	<http://www.wikidata.org/prop/statement/P549> "TestString" ;
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
 
-<http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> a <http://wikiba.se/ontology#TimeValue> ;
+<http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> a <http://wikiba.se/ontology#TimeValue> ;
 	<http://wikiba.se/ontology#timeValue> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
 	<http://wikiba.se/ontology#timePrecision> "32"^^<http://www.w3.org/2001/XMLSchema#int> ;
 	<http://wikiba.se/ontology#timeTimezone> "0"^^<http://www.w3.org/2001/XMLSchema#int> ;
@@ -145,4 +145,4 @@ _:node1a5d5pvl8x8 a <http://www.w3.org/2002/07/owl#Restriction> ;
 <http://www.wikidata.org/prop/reference/P549> a <http://www.w3.org/2002/07/owl#DatatypeProperty> .
 
 <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> a <http://wikiba.se/ontology#Reference> ;
-	<http://www.wikidata.org/prop/reference/value/P112> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> .
+	<http://www.wikidata.org/prop/reference/value/P112> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> .
diff --git a/wdtk-rdf/src/test/resources/ItemDocumentUnknownPropertyTypes.rdf b/wdtk-rdf/src/test/resources/ItemDocumentUnknownPropertyTypes.rdf
index bb027ca5..f5f954aa 100644
--- a/wdtk-rdf/src/test/resources/ItemDocumentUnknownPropertyTypes.rdf
+++ b/wdtk-rdf/src/test/resources/ItemDocumentUnknownPropertyTypes.rdf
@@ -11,9 +11,9 @@
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
 
 <http://www.wikidata.org/entity/statement/Q10-none2> a <http://wikiba.se/ontology#Statement> , <http://wikiba.se/ontology#BestRank> ;
-	<http://www.wikidata.org/prop/statement/value/P569> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> ;
+	<http://www.wikidata.org/prop/statement/value/P569> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> ;
 	<http://www.wikidata.org/prop/statement/P569> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
-	<http://www.wikidata.org/prop/qualifier/value/P15> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> ;
+	<http://www.wikidata.org/prop/qualifier/value/P15> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> ;
 	<http://www.wikidata.org/prop/qualifier/P15> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
 	<http://www.w3.org/ns/prov#wasDerivedFrom> <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> ;
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
@@ -22,7 +22,7 @@
 	<http://www.wikidata.org/prop/statement/P549> "TestString" ;
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
 
-<http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> a <http://wikiba.se/ontology#TimeValue> ;
+<http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> a <http://wikiba.se/ontology#TimeValue> ;
 	<http://wikiba.se/ontology#timeValue> "0306-11-03T13:07:06Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
 	<http://wikiba.se/ontology#timePrecision> "32"^^<http://www.w3.org/2001/XMLSchema#int> ;
 	<http://wikiba.se/ontology#timeTimezone> "0"^^<http://www.w3.org/2001/XMLSchema#int> ;
@@ -113,4 +113,4 @@ _:node1c3irgg7cx14 a <http://www.w3.org/2002/07/owl#Restriction> ;
 <http://www.wikidata.org/prop/reference/P549> a <http://www.w3.org/2002/07/owl#DatatypeProperty> .
 
 <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> a <http://wikiba.se/ontology#Reference> ;
-	<http://www.wikidata.org/prop/reference/value/P112> <http://www.wikidata.org/value/ec11d94e4f5bb7b00a79196734f49066> .
+	<http://www.wikidata.org/prop/reference/value/P112> <http://www.wikidata.org/value/9e335050c59079e3f3c216b8cf077d07> .
diff --git a/wdtk-rdf/src/test/resources/StatementCplx.rdf b/wdtk-rdf/src/test/resources/StatementCplx.rdf
index ea161bde..c637f09c 100644
--- a/wdtk-rdf/src/test/resources/StatementCplx.rdf
+++ b/wdtk-rdf/src/test/resources/StatementCplx.rdf
@@ -1,5 +1,5 @@
 <http://localhost/entity/Q0> <http://www.wikidata.org/prop/P0> <http://www.wikidata.org/entity/statement/Q0-> .
 <http://www.wikidata.org/entity/statement/Q0-> a <http://wikiba.se/ontology#Statement> ;
 	<http://www.wikidata.org/prop/statement/value/P0> <http://www.wikidata.org/value/ffc4e2c3e1979c0dd53184be282bd01c> ;
-	<http://www.wikidata.org/prop/statement/P0> "Point(13.0 51.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> ;
+	<http://www.wikidata.org/prop/statement/P0> "Point(51.0 13.0)"^^<http://www.opengis.net/ont/geosparql#wktLiteral> ;
 	<http://wikiba.se/ontology#rank> <http://wikiba.se/ontology#NormalRank> .
diff --git a/wdtk-rdf/src/test/resources/TimeValue.rdf b/wdtk-rdf/src/test/resources/TimeValue.rdf
index 3ec6f511..eeabbc3b 100644
--- a/wdtk-rdf/src/test/resources/TimeValue.rdf
+++ b/wdtk-rdf/src/test/resources/TimeValue.rdf
@@ -1,5 +1,5 @@
 
-<http://www.wikidata.org/value/916df1a6567186e91bd43adc424eeec0> a <http://wikiba.se/ontology#TimeValue> ;
+<http://www.wikidata.org/value/c0d63bd8e4e71569494de00985d094c2> a <http://wikiba.se/ontology#TimeValue> ;
 	<http://wikiba.se/ontology#timeValue> "2008-01-01T00:00:00Z"^^<http://www.w3.org/2001/XMLSchema#dateTime> ;
 	<http://wikiba.se/ontology#timePrecision> "9"^^<http://www.w3.org/2001/XMLSchema#int> ;
 	<http://wikiba.se/ontology#timeTimezone> "0"^^<http://www.w3.org/2001/XMLSchema#int> ;
diff --git a/wdtk-rdf/src/test/resources/completeRDFDocument.rdf b/wdtk-rdf/src/test/resources/completeRDFDocument.rdf
index 9c33cfe1..eeec874f 100644
--- a/wdtk-rdf/src/test/resources/completeRDFDocument.rdf
+++ b/wdtk-rdf/src/test/resources/completeRDFDocument.rdf
@@ -99,9 +99,9 @@ wikibase:badge a owl:ObjectProperty .
 	wikibase:rank wikibase:NormalRank .
 
 <http://www.wikidata.org/entity/statement/Q10-none2> a wikibase:Statement , <http://wikiba.se/ontology#BestRank> ;
-	<http://www.wikidata.org/prop/statement/value/P569> wdv:ec11d94e4f5bb7b00a79196734f49066 ;
+	<http://www.wikidata.org/prop/statement/value/P569> wdv:9e335050c59079e3f3c216b8cf077d07 ;
 	<http://www.wikidata.org/prop/statement/P569> "0306-11-03T13:07:06Z"^^xsd:dateTime ;
-	<http://www.wikidata.org/prop/qualifier/value/P15> wdv:ec11d94e4f5bb7b00a79196734f49066 ;
+	<http://www.wikidata.org/prop/qualifier/value/P15> wdv:9e335050c59079e3f3c216b8cf077d07 ;
 	<http://www.wikidata.org/prop/qualifier/P15> "0306-11-03T13:07:06Z"^^xsd:dateTime ;
 	prov:wasDerivedFrom <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> ;
 	wikibase:rank wikibase:NormalRank .
@@ -110,7 +110,7 @@ wikibase:badge a owl:ObjectProperty .
 	<http://www.wikidata.org/prop/statement/P549> "TestString" ;
 	wikibase:rank wikibase:NormalRank .
 
-wdv:ec11d94e4f5bb7b00a79196734f49066 a wikibase:TimeValue ;
+wdv:9e335050c59079e3f3c216b8cf077d07 a wikibase:TimeValue ;
 	wikibase:timeValue "0306-11-03T13:07:06Z"^^xsd:dateTime ;
 	wikibase:timePrecision "32"^^xsd:int ;
 	wikibase:timeTimezone "0"^^xsd:int ;
@@ -173,7 +173,7 @@ wdv:ec11d94e4f5bb7b00a79196734f49066 a wikibase:TimeValue ;
 <http://www.wikidata.org/prop/reference/P549> a owl:DatatypeProperty .
 
 <http://www.wikidata.org/reference/29b7008efe33a96335e456305edfb481> a wikibase:Reference ;
-	<http://www.wikidata.org/prop/reference/value/P112> wdv:ec11d94e4f5bb7b00a79196734f49066 .
+	<http://www.wikidata.org/prop/reference/value/P112> wdv:9e335050c59079e3f3c216b8cf077d07 .
 	
 <http://www.wikidata.org/prop/novalue/P10> a owl:Class ;
 	owl:complementOf _:node1a5d6h9m9x1 .