В SparQL как отличить год, например 2017, и 1 января 2017 года?
Следующие запросы SPARQL, использующие REST API Wikidata, возвращают дату типа xsd:datetime
1 января:
>>> # 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)
, но это жизнь, и, по крайней мере, у нас есть решение.