user4432964
user4432964

Reputation:

Remove time from datetime in spaqrl

I am writing a query in SPARQL and I want to compare the date value without the time. Currently, I am getting a datetime value such as 2014-08-14T13:00:00Z. However, I want to do a filter on the date such as

FILTER (?date = "2014-08-15"^^xsd:dateTime)

I am new to SPARQL, so I need some help. Thanks.

EDITED


Thanks for the response guys. My apologies for the xsd:dateTime

FILTER (?date = "2014-08-15"^^xsd:date)

I have decided to try the following although I wanted a much 'prettier' solution.

FILTER (?date >= "2014-08-15T00:00:00Z"^^xsd:dateTime && ?date <= "2014-08-15T24:00:00Z"^^xsd:dateTime)

Upvotes: 3

Views: 1395

Answers (2)

Joshua Taylor
Joshua Taylor

Reputation: 85813

You can do this, but not exactly the way your question asks. The literal forms for dateTimes have to have all the fields (except the timezone), so "2014-08-15"^^xsd:dateTime isn't actually a legal dateTime. See the definition for more about the date time format.

That said, it's easy enough to pull out the year, month, and day from a datetime and put them back together into a date that you can compare with other dates:

prefix xsd: <http://www.w3.org/2001/XMLSchema#>

select ?dt ?date where {
  values ?dt { "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime }

  bind(xsd:date(concat(str(year(?dt)),"-",
                       str(month(?dt)),"-",
                       str(day(?dt))))
       as ?date)
}
--------------------------------------------------------------------------
| dt                                            | date                   |
==========================================================================
| "2011-01-10T14:45:13.815-05:00"^^xsd:dateTime | "2011-01-10"^^xsd:date |
--------------------------------------------------------------------------

If you want to include the timezone, you can do that too; they're permitted in xsd:dates.

If you wanted to filter without creating the new date, you could also do something like

filter (year(?dt) = 2015 &&
        month(?dt) = 01 &&
        day(?dt) = 10)

That might be a fairly clean solution.

A note about your filter, though. You can filter the value of a variable against a constant like you did, but that often (but not always) suggests an easier way. For instance, instead of:

select ?s where {
  ?s a ?o .
  filter ( ?o = <something> )
}

you'd usually just use the value in place, or use values to specify the value of a variable:

select ?s where {
  ?s a <something> .
}
select ?s where {
  values ?o { <something> }
  ?s a ?o .
}

Upvotes: 3

scotthenninger
scotthenninger

Reputation: 4001

You could try a simple cast to xsd:date, but the SPARQL engine will likely retain the time. So it becomes a matter of parsing. One way is to just use SUBSTR, as the number of characters is known:

FILTER (xsd:date(SUBSTR(str(?date), 0, 11)) = "2014-08-15"^^xsd:date)

Another is to build the date from datetime format:

FILTER (xsd:date(CONCAT(str(YEAR(?date)), "-", str(MONTH(?date)), "-", str(DAY(?date)))) = "2014-08-15"^^xsd:date)

Perhaps not as convenient given that CONCAT requires string conversion, but the general idea is to build the string from the datetime value and cast to xsd:date.

Upvotes: 1

Related Questions