Extracting the day and month by casting to xsd:dateTime
SPARQL 1.1 has a day
function that returns the day of a dateTime.
17.4.5.4 day
xsd:integer DAY (xsd:dateTime arg)
Returns the day part of arg as an integer.
This function corresponds to fn:day-from-dateTime.
day("2011-01-10T14:45:13.815-05:00"^^xsd:dateTime) => 10
You can use xsd:dateTime
as a function to convert xsd:date
s into dateTimes
to which you can apply this function. As an example:
prefix xsd: <http://www.w3.org/2001/XMLSchema#>
select ?month ?day where {
# Provide some values for ?date. Note that
# we can use xsd:date *and* xsd:dateTime here,
# as both can be cast to xsd:dateTime.
values ?date {
"2011-01-02"^^xsd:date
"2012-10-11"^^xsd:date
"2013-12-30T14:45:13.815-05:00"^^xsd:dateTime
}
# Cast to a xsd:dateTime and extract the day and month.
bind( day(xsd:dateTime(?date)) as ?day )
bind( month(xsd:dateTime(?date)) as ?month )
}
---------------
| month | day |
===============
| 01 | 02 |
| 10 | 11 |
| 12 | 30 |
---------------
Why DBpedia does strange things
The easiest way to find out why you get seven as the length sometimes is to ask for values where the length is seven and see what you get. E.g., look at the results of
SELECT ?person ?birth WHERE {
?person dbpedia-owl:birthDate ?birth .
bind( strlen(str(?birth)) as ?blen )
filter( ?blen < 10 )
}
LIMIT 25
Person Birth
-----------------------------------------------------------------------------------------
Alyson_No%C3%ABl "--12-03"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
Corneille_(singer) "--03-24"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
Count_Karl_Sigmund_von_Hohenwart "--02-12"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
David_Lewis_(politician) "--06-23"^^<http://www.w3.org/2001/XMLSchema#gMonthDay>
… …
There are values that aren't xsd:dateTimes
or xsd:date
s, but rather xsd:gMonthDay
s. These don't have a year specified, so the the strings aren't as long as those for xsd:date
s. This is another reason that shows why you should cast to xsd:date
s (or check the datatype, etc., since you can't cast from an xsd:gMonthDay
to a xsd:dateTime
).
As was pointed out in the comments, your query isn't actually legal. You shouldn't be able to select non-grouped variables, so perhaps what's happening is that when you've done
SELECT ?name, ?bmonth, ?bstring, ?len1, ?len2 WHERE {
?person foaf:name ?name .
?person dbo:birthDate ?birth .
BIND (str(?birth) AS ?bstring)
BIND (strlen(?bstring) AS ?len1)
BIND (substr(?bstring, 6,2) AS ?bmonth)
BIND (strlen(?bstring) AS ?len2)
FILTER ( ?bmonth = '12' )
}
GROUP BY ?person
ORDER BY ?len1
LIMIT 50
you're getting some DBpedia specific behavior. E.g., perhaps you're grouping by the person, and then the select is doing an implicit sample
and maybe some of these persons have multiple values for their birth date. (I'm not certain about this, it's just a possibility that occurs to me. DBpedia is doing maintainence at the moment, so I can't check what data's there, and even if I could, this is behavior not defined by the standard. I suggest that you check your queries at sparql.org's query validator and get legal SPARQL first. Only then can we tell if you if it's returning what it ought to.)