В SparQL как отличить год, например 2017, и 1 января 2017 года?

Следующие запросы SPARQL, использующие REST API Wikidata, возвращают дату типа xsd:datetime1 января:

>>> # Inception of Manchester United F.C. = in 1875
>>> wikidata_rest_query("SELECT ?date WHERE { wd:Q18656 wdt:P571 ?date }")
{'head': {'vars': ['date']},
 'results': {'bindings': [{'date': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
     'type': 'literal',
     'value': '1875-01-01T00:00:00Z'}}]}}

>>> # Istanbul nightclub attack = on January 1st 2017
>>> wikidata_rest_query("SELECT ?date WHERE { wd:Q28094271 wdt:P585 ?date }")
{'head': {'vars': ['date']},
 'results': {'bindings': [{'date': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
     'type': 'literal',
     'value': '2017-01-01T00:00:00Z'}}]}}

В первом случае дата просто означает "в 1875 году", а не буквально 1 января 1875 года в полночь. Во втором случае дата фактически означает "1 января 2017 года", но не конкретно в полночь. Я бы предпочел ответы типа "1875" и "2017-01-01".

При просмотре страниц Wikidata по этим темам (" Манчестер Юнайтед" и " Атака ночного клуба Стамбул 2017") отображается правильный уровень детализации (т.е. 1875 в первом случае, но 1 января 2017 года во втором), поэтому они должны иметь правильная информация в их базе данных, и, надеюсь, есть способ запросить ее.

Есть идеи?

Заметка

Я пытался запрашивать datatype(?date), надеясь увидеть разницу, но она возвращается xsd:datetime в обоих примерах.

редактировать

Вот код Python 3 wikidata_rest_query(), если вы хотите проверить запросы выше:

from urllib.request import urlopen, quote
import json

def wikidata_rest_query(query):
    url = "https://query.wikidata.org/sparql?query=%s&format=json" % quote(query)
    with urlopen(url) as f:
        response = f.read().decode("utf-8")
    return json.loads(response)

1 ответ

Викиданные решили эту проблему, сохранив дополнительную информацию о каждом xsd:datetimeв частности timePrecision:

>>> query = """
... SELECT ?time ?timeprecision ?timezone ?timecalendar WHERE {
...     wd:Q18656 p:P571/psv:P571 ?timenode.
...     ?timenode wikibase:timeValue         ?time.
...     ?timenode wikibase:timePrecision     ?timeprecision.
...     ?timenode wikibase:timeTimezone      ?timezone.
...     ?timenode wikibase:timeCalendarModel ?timecalendar.
... }
... """
>>> wikidata_rest_query(query)
{'head': {'vars': ['time', 'timeprecision', 'timezone', 'timecalendar']},
 'results': {'bindings': [{'time': {'datatype': 'http://www.w3.org/2001/XMLSchema#dateTime',
     'type': 'literal',
     'value': '1875-01-01T00:00:00Z'},
    'timecalendar': {'type': 'uri',
     'value': 'http://www.wikidata.org/entity/Q1985727'},
    'timeprecision': {'datatype': 'http://www.w3.org/2001/XMLSchema#integer',
     'type': 'literal',
     'value': '9'},
    'timezone': {'datatype': 'http://www.w3.org/2001/XMLSchema#integer',
     'type': 'literal',
     'value': '0'}}]}}

timePrecision равен 9, что означает год. Другие возможные точности перечислены здесь:

Коды точности: 0: миллиард лет, 1: сто миллионов лет, 3: миллион лет, 4: сто тысяч лет, 5: десять тысяч лет, 6: тысячелетие, 7: век, 8: десятилетие, 9: год, 10: месяц, 11: день, 12: час, 13: минута, 14: секунда.

Если вы попробуете Стамбульский запрос, вы получите timePrecision равно 11: день, как и ожидалось.

Было бы проще, если бы мы могли просто написать timePrecision(?date), но это жизнь, и, по крайней мере, у нас есть решение.

Другие вопросы по тегам