diff --git a/extensions/wikidata/module/langs/translation-en.json b/extensions/wikidata/module/langs/translation-en.json
index 6367bf462..5b688d6c6 100644
--- a/extensions/wikidata/module/langs/translation-en.json
+++ b/extensions/wikidata/module/langs/translation-en.json
@@ -154,5 +154,7 @@
"warnings-messages/no-unit-provided/title": "Unit missing for {property_entity}",
"warnings-messages/no-unit-provided/body": "Values such as {example_value} on {example_item_entity} are expected to have units.",
"warnings-messages/invalid-entity-type/title": "{property_entity} used on items",
- "warnings-messages/invalid-entity-type/body": "Uses of {property_entity} on items such as {example_entity} are invalid."
+ "warnings-messages/invalid-entity-type/body": "Uses of {property_entity} on items such as {example_entity} are invalid.",
+ "warnings-messages/early-gregorian-date/title": "Early dates in the Gregorian calendar",
+ "warnings-messages/early-gregorian-date/body": "Dates earlier than October 1582 (such as in year {example_year}) are unlikely to be expressed using the Gregorian calendar. See the manual to specify the appropriate calendar for your dates."
}
diff --git a/extensions/wikidata/src/org/openrefine/wikidata/qa/EditInspector.java b/extensions/wikidata/src/org/openrefine/wikidata/qa/EditInspector.java
index 86b876b8c..531894588 100644
--- a/extensions/wikidata/src/org/openrefine/wikidata/qa/EditInspector.java
+++ b/extensions/wikidata/src/org/openrefine/wikidata/qa/EditInspector.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
+import org.openrefine.wikidata.qa.scrutinizers.CalendarScrutinizer;
import org.openrefine.wikidata.qa.scrutinizers.DistinctValuesScrutinizer;
import org.openrefine.wikidata.qa.scrutinizers.EditScrutinizer;
import org.openrefine.wikidata.qa.scrutinizers.EntityTypeScrutinizer;
@@ -79,6 +80,7 @@ public class EditInspector {
register(new QuantityScrutinizer());
register(new RestrictedValuesScrutinizer());
register(new EntityTypeScrutinizer());
+ register(new CalendarScrutinizer());
}
/**
diff --git a/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizer.java b/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizer.java
new file mode 100644
index 000000000..928cfc542
--- /dev/null
+++ b/extensions/wikidata/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizer.java
@@ -0,0 +1,31 @@
+package org.openrefine.wikidata.qa.scrutinizers;
+
+import org.openrefine.wikidata.qa.QAWarning;
+import org.wikidata.wdtk.datamodel.helpers.Datamodel;
+import org.wikidata.wdtk.datamodel.interfaces.TimeValue;
+import org.wikidata.wdtk.datamodel.interfaces.Value;
+
+public class CalendarScrutinizer extends ValueScrutinizer {
+
+ public static final String earlyGregorianDateType = "early-gregorian-date";
+
+ public static final TimeValue earliestGregorian = Datamodel.makeTimeValue(
+ 1582, (byte)10, (byte)15, (byte)0, (byte)0, (byte)0, (byte)11, 0, 0, 0, TimeValue.CM_GREGORIAN_PRO);
+
+ @Override
+ public void scrutinize(Value value) {
+ if(TimeValue.class.isInstance(value)) {
+ TimeValue time = (TimeValue)value;
+ if(time.getPreferredCalendarModel().equals(earliestGregorian.getPreferredCalendarModel()) &&
+ time.getPrecision() >= 10 &&
+ (time.getYear() < earliestGregorian.getYear() ||
+ time.getYear() == earliestGregorian.getYear() && time.getMonth() < earliestGregorian.getMonth() ||
+ time.getYear() == earliestGregorian.getYear() && time.getMonth() == earliestGregorian.getMonth() && time.getDay() < earliestGregorian.getDay())) {
+ QAWarning warning = new QAWarning(earlyGregorianDateType, null, QAWarning.Severity.WARNING, 1);
+ warning.setProperty("example_year", Long.toString(time.getYear()));
+ addIssue(warning);
+ }
+ }
+ }
+
+}
diff --git a/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizerTest.java b/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizerTest.java
new file mode 100644
index 000000000..5acb2b254
--- /dev/null
+++ b/extensions/wikidata/tests/src/org/openrefine/wikidata/qa/scrutinizers/CalendarScrutinizerTest.java
@@ -0,0 +1,37 @@
+package org.openrefine.wikidata.qa.scrutinizers;
+
+import org.testng.annotations.Test;
+import org.wikidata.wdtk.datamodel.helpers.Datamodel;
+import org.wikidata.wdtk.datamodel.interfaces.TimeValue;
+
+public class CalendarScrutinizerTest extends ValueScrutinizerTest {
+
+ @Override
+ public EditScrutinizer getScrutinizer() {
+ return new CalendarScrutinizer();
+ }
+
+ @Test
+ public void testScrutinizeRecentValue() {
+ scrutinize(Datamodel.makeTimeValue(1978L, (byte)3, (byte)4, (byte)0, (byte)0, (byte)0, 11, TimeValue.CM_GREGORIAN_PRO));
+ assertNoWarningRaised();
+ }
+
+ @Test
+ public void testScrutinizeCloseValue() {
+ scrutinize(Datamodel.makeTimeValue(1582L, (byte)10, (byte)17, (byte)0, (byte)0, (byte)0, 11, TimeValue.CM_GREGORIAN_PRO));
+ assertNoWarningRaised();
+ }
+
+ @Test
+ public void testScrutinizeEarlyYear() {
+ scrutinize(Datamodel.makeTimeValue(1400L, (byte)1, (byte)1, (byte)0, (byte)0, (byte)0, (byte)9, 0, 0, 0, TimeValue.CM_GREGORIAN_PRO));
+ assertNoWarningRaised();
+ }
+
+ @Test
+ public void testScrutinizeEarlyDay() {
+ scrutinize(Datamodel.makeTimeValue(1440L, (byte)10, (byte)17, (byte)0, (byte)0, (byte)0, 11, TimeValue.CM_GREGORIAN_PRO));
+ assertWarningsRaised(CalendarScrutinizer.earlyGregorianDateType);
+ }
+}