diff --git a/rdflib/plugins/sparql/operators.py b/rdflib/plugins/sparql/operators.py index 29bdd5c0e..3393f18ae 100644 --- a/rdflib/plugins/sparql/operators.py +++ b/rdflib/plugins/sparql/operators.py @@ -12,6 +12,7 @@ import random import uuid import hashlib +import datetime as py_datetime # naming conflict with function within this module from functools import reduce @@ -449,17 +450,17 @@ def Builtin_NOW(e, ctx): def Builtin_YEAR(e, ctx): - d = datetime(e.arg) + d = date(e.arg) return Literal(d.year) def Builtin_MONTH(e, ctx): - d = datetime(e.arg) + d = date(e.arg) return Literal(d.month) def Builtin_DAY(e, ctx): - d = datetime(e.arg) + d = date(e.arg) return Literal(d.day) @@ -998,6 +999,17 @@ def datetime(e): return e.toPython() +def date(e) -> py_datetime.date: + if not isinstance(e, Literal): + raise SPARQLError("Non-literal passed as date: %r" % e) + if e.datatype not in (XSD.date, XSD.dateTime): + raise SPARQLError("Literal with wrong datatype passed as date: %r" % e) + result = e.toPython() + if isinstance(result, py_datetime.datetime): + return result.date() + return result + + def string(s): """ Make sure the passed thing is a string literal diff --git a/test/test_sparql_operators.py b/test/test_sparql_operators.py new file mode 100644 index 000000000..b4e4dacdd --- /dev/null +++ b/test/test_sparql_operators.py @@ -0,0 +1,36 @@ +import datetime + +import nose.tools + +import rdflib +from rdflib.plugins.sparql import operators +from rdflib.plugins.sparql import sparql + + +def test_date_cast(): + now = datetime.datetime.now() + today = now.date() + + literal = rdflib.Literal(now) + result = operators.date(literal) + assert isinstance(result, datetime.date) + assert result == today + + literal = rdflib.Literal(today) + result = operators.date(literal) + assert isinstance(result, datetime.date) + assert result == today + + +def test_datetime_cast(): + now = datetime.datetime.now() + literal = rdflib.Literal(now) + result = operators.datetime(literal) + assert isinstance(result, datetime.datetime) + assert result == now + + +@nose.tools.raises(sparql.SPARQLError) +def test_datetime_cast_type_error(): + literal = rdflib.Literal("2020-01-02") + operators.date(literal)