Как преобразовать литерал xsd:dateTime в xsd:date в GraphDB?

Я пытаюсь преобразовать xsd:dateTime в xsd:date, чтобы иметь возможность ФИЛЬТРОВАТЬ объекты только по датам. Но, выполнив следующие действия в GraphDB

PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?s ?e { 
    VALUES (?start ?end) {("2011-02-02T14:45:14"^^xsd:dateTime "2011-02-04T14:45:13"^^xsd:dateTime)}
    BIND ( xsd:date(?start) AS ?s)
    BIND ( xsd:date(?end) AS ?e)
}

Я получаю следующую ошибку

org.eclipse.rdf4j.query.QueryEvaluationException: Unknown function 'http://www.w3.org/2001/XMLSchema#date'

Но, как видно здесь, Javascript-функции GraphDB используется xsd: функция даты.


person SVS    schedule 03.10.2019    source источник
comment
Я уверен, что документация здесь просто неверна. Согласно стандарту SPARQL 1.1 эта функция не существует: w3.org/TR/sparql11- query/#FunctionMapping И в документах GraphDB функция также не указана как расширение: graphdb.ontotext.com/documentation/standard/devhub/   -  person UninformedUser    schedule 03.10.2019
comment
Но да, я могу воспроизвести ошибку, пока xsd:dateTime действительно работает. Так что либо этой функции больше нет в RDF4J, либо ее никогда не было. Кстати, для Virtuoso это сработало бы, так что иногда тройные магазины поддерживают различные дополнительные функции w.r.t. стандарт   -  person UninformedUser    schedule 03.10.2019
comment
@AKSW, спасибо! Не могли бы вы предложить какие-либо способы, как решить это SPARQL? Или мне нужно создать пользовательские функции для GraphDB в этом случае, сказав в GraphDB Javascript Functions   -  person SVS    schedule 03.10.2019
comment
Ну да. Я предполагаю, что пользовательская функция Javascript может сделать это за вас. Я до сих пор не уверен, какой тип вернет функция Javascript. В худшем случае вы можете просто вернуть дату в виде строки, а затем вызвать BIND (STRDT(jsfn:date(?start), xsd:date) as ?s)   -  person UninformedUser    schedule 03.10.2019
comment
другой обходной путь: bind(strdt(concat(str(year(?start)),"-", str(month(?start)),"-", str(day(?start))), xsd:date) as ?s)   -  person UninformedUser    schedule 03.10.2019
comment
или bind(strdt(SUBSTR(str(?start), 0, 11), xsd:date) as ?s) - но я не очень доволен обоими, первый опускает начальные нули для года, месяца и дня, т.е. 2011-02-02 становится 2011-2-2, что (афаик) недействительно. у второго могут возникнуть проблемы с часовыми поясами, если они произойдут   -  person UninformedUser    schedule 03.10.2019


Ответы (2)


В документации по ссылке о функциях Javascript GraphDB используется несуществующая функция xsd:date. По какой-то причине это не закончилось релизом.

Некоторые технические заметки.

Значения RDF, передаваемые в качестве аргументов определяемым пользователем функциям javascript, подвергаются преобразованию типов. Экземпляры org.eclipse.rdf4j.model.IRI и org.eclipse.rdf4j.model.BNode передаются "как есть", но литералы преобразуются следующим образом:

  • если это целочисленный тип данных, например. один из (xsd:integer, xsd:long, xsd:int, xsd:byte, xsd:short, xsd:nonPositiveInteger, xsd:negativeInteger, xsd:nonNegativeInteger, xsd:positiveInteger, xsd:unsignedLong, xsd:unsignedInt, xsd:unsignedShort и xsd:unsignedByte) передается значение long

  • если это одно из: xsd:decimal, xsd:float или xsd:double переданное значение является double

  • если это одно из: xsd:dateTime, xsd:date, xsd:time, xsd:gYearMonth, xsd:gMonthDay, xsd:gYear, xsd:gMonth или xsd:gDay, переданное значение является экземпляром javax.xml.datatype.XMLGregorianCalendar

  • если это продолжительность, например. одно из: xsd:duration, xsd:dayTimeDuration или xsd:yearMonthDuration переданное значение является экземпляром javax.xml.datatype.Duration

  • наконец, для xsd:boolean это boolean

  • для всего остального метка литерала как String

В качестве альтернативы возвращаемое значение также преобразуется. Если это экземпляр org.eclipse.rdf4j.Value, преобразование не выполняется. В противном случае преобразование в литерал RDF зависит от его типа, а также от доступных в RDF4J ValueFactory as createLiteral методов, которые могут их обрабатывать, включая XMLGregorianCalendar. Поэтому, если нет определенного обработчика, строковое значение результата используется для создания литерала.

В примере из первого ответа результат jsfn:convertDate имеет тип jdk.nashorn.internal.objects.NativeDate, поэтому, когда создается литерал результата, плагин вызывает свой toString, что приводит к таким результатам, как [Date 2011-02-02T14:45:14.000Z]

Кроме того, механизм сценариев в плагине ограничен доступом только к классам, начинающимся с java.lang. (за исключением java.lang.Thread), org.eclipse.rdf4j.model. и com.ontotext.trree.sdk..

Принимая во внимание приведенные выше примечания и ограничения, функция javascript, которая преобразует xsd:dateTime в xsd:date, должна установить поля значения календаря, которые связаны со временем, в DatatypeConstants.FIELD_UNDEFINED, что на самом деле Integer.MIN_VALUE, и создать литерал через RDF4J ValueFactory:

PREFIX jsfn:<http://www.ontotext.com/js#>
INSERT DATA {
    [] jsfn:register '''
    function convertDate(value) {
        value.setTime(java.lang.Integer.MIN_VALUE, java.lang.Integer.MIN_VALUE, java.lang.Integer.MIN_VALUE);
        return org.eclipse.rdf4j.model.impl.SimpleValueFactory.getInstance().createLiteral(value);
    }
'''
}

ХТН

person Damyan Ognyanov    schedule 04.10.2019
comment
Интересный. Очевидно, что ни одну из этих деталей нельзя найти в документации, поэтому только разработчик GraphDB, такой как вы, может написать собственные функции Javascript, которые возвращают типизированные литералы или подобные вещи, помимо простых строк. - person UninformedUser; 05.10.2019

Создайте функцию javascript в GraphDB, например:

PREFIX jsfn:<http://www.ontotext.com/js#>
INSERT DATA {
    [] jsfn:register '''
    function convertDate(value) {
        return new Date(value);
    }
'''
}

Убедитесь, что функция зарегистрирована или:

PREFIX jsfn:<http://www.ontotext.com/js#>
SELECT ?s ?o {
    ?s jsfn:enum ?o
}

А затем используйте его следующим образом:

PREFIX jsfn:<http://www.ontotext.com/js#>
PREFIX xsd: <http://www.w3.org/2001/XMLSchema#>
SELECT ?s ?e { 
    VALUES (?start ?end) {("2011-02-02T14:45:14"^^xsd:dateTime "2011-02-04T14:45:13"^^xsd:dateTime)}
    BIND ( jsfn:convertDate(?start) AS ?s)
    BIND ( jsfn:convertDate(?end) AS ?e)
}

Возвращаемый результат:

[Дата 2011-02-02T14:45:14.000Z]

[Дата 2011-02-04T14:45:13.000Z]

Надеюсь это поможет.

person Sava Savov    schedule 03.10.2019
comment
ну, [Date 2011-02-02T14:45:14.000Z] не будет свиданием, верно? Насколько я понимаю, возвращаемый литерал должен быть "2011-02-02"^^xsd:date - person UninformedUser; 03.10.2019