在 SPARQL 中确定日期时间的星期几

Determining Day Of Week For Datetime in SPARQL

我有一个图表,我正在尝试按星期几过滤报告。例如,我希望找到它们发生在星期二的所有实例。有没有办法将日期时间字段格式化为星期几或直接在日期时间字段上按星期几过滤?

SPARQL 没有 name-of-day 函数,但如果您的 SPARQL 端点是 Virtuoso instance, you can leverage its SQL functions. Here's a query you can run against DBpedia --

SELECT
                                   ?birthdate 
    ( bif:dayname(?birthdate)  AS  ?dayname )
WHERE
   {  <http://dbpedia.org/resource/Barack_Obama>
         <http://dbpedia.org/ontology/birthDate>  ?birthdate 
   }

-- 这将得到 Barack Obama's birthdate and day --

birthdate    dayname
1961-08-04   Friday

我想更多的是缺乏这样一个功能阻碍了你,而不是不知道如何构建你的 SPARQL FILTER?

(ObDisclaimer:OpenLink Software produces Virtuoso,并雇用了我。)

SPARQL 没有 'day of week' 函数 built-in,但是,大多数编程语言都 built-in 支持从给定的 calendar/date 对象中检索星期几。例如,使用 Java 和 RDF4J,您可以简单地检索 dateTime 文字(表示为具有 xsd:dateTime 数据类型的 Literal 对象),转换为 Java 日历对象,然后然后检索工作日:

Literal value = ... ; // the RDF4J literal value from your query result
Calendar calendar = value.calendarValue().toGregorianCalendar(); 
int weekday = calendar.get(Calendar.DAY_OF_WEEK);

此外,大多数 SPARQL 引擎都提供添加自定义函数的选项。

因此您可以只检索日期时间和 post-process 结果以获得星期几,或者您实际上可以创建一个自定义函数并将其添加到您的 SPARQL 引擎中。这是关于 how to add a custom function to SPARQL using Sesame/RDF4J.

的教程

如果您提供了一些背景知识,您还可以用标准 SPARQL 确定星期几。查询需要在您的日期和该日期的星期几之前的参考日期。

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

SELECT ?date ?dayName
WHERE {
  # Sample dates
  VALUES ?date {
    "1961-08-04"^^xsd:date
    "1986-04-03"^^xsd:date
  }
  # Compute days since a reference date
  # This works in Virtuoso, which returns the difference in days.
  # For example, Fuseki returns xsd:duration instead.
  BIND (?date - "1900-01-01"^^xsd:date AS ?days)
  # Compute modulo by 7 without a modulo operator
  BIND (floor(?days - (7 * floor(?days/7))) AS ?mod)
  VALUES (?mod ?dayName) {
         (0    "Monday") # 1900-01-01 was Monday
         (6    "Tuesday")
         (5    "Wednesday")
         (4    "Thursday")
         (3    "Friday")
         (2    "Saturday")
         (1    "Sunday")
  }
}

我使用了 Jindrich 的解决方案并尝试使用 xsd:duration 算法重构它(它遵循 SPARQL 和 XPath 规范,与 Virtuoso 不同):

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

SELECT ?date ?dayName
WHERE {
  # Sample dates
  VALUES ?date {
    "1961-08-04"^^xsd:date
    "1986-04-03"^^xsd:date
  }
  BIND (xsd:date(?date) - "1900-01-01"^^xsd:date AS ?days)
  BIND (?days - (xsd:dayTimeDuration("P7D") * floor(?days / xsd:dayTimeDuration("P7D"))) AS ?mod)
  BIND (str(?mod) AS ?modStr)
  VALUES (?modStr ?dayName) {
         ("PT0S"   "Monday") # 1900-01-01 was Monday
         ("P1D"    "Tuesday")
         ("P2D"    "Wednesday")
         ("P3D"    "Thursday")
         ("P4D"    "Friday")
         ("P5D"    "Saturday")
         ("P6D"    "Sunday")
  }
}

我 运行 在 Dydra 上的查询,我得到了样本日期(星期五和星期四)的正确结果,但没有进一步测试。

根据此 SPARQL Results Page Link,该解决方案也适用于 Virtuoso。

目前,最初的解决方案是重新工作的。 Virtuoso 按照这个 SPARQL Results Page

基本上,原来的回复:

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

SELECT ?date ?dayName
WHERE {
  # Sample dates
  VALUES ?date {
    "1961-08-04"^^xsd:date
    "1986-04-03"^^xsd:date
  }
  # Compute days since a reference date
  # This works in Virtuoso, which returns the difference in days.
  # For example, Fuseki returns xsd:duration instead.
  BIND (?date - "1900-01-01"^^xsd:date AS ?days)
  # Compute modulo by 7 without a modulo operator
  BIND (floor(?days - (7 * floor(?days/7))) AS ?mod)
  VALUES (?mod ?dayName) {
         (0    "Monday") # 1900-01-01 was Monday
         (6    "Tuesday")
         (5    "Wednesday")
         (4    "Thursday")
         (3    "Friday")
         (2    "Saturday")
         (1    "Sunday")
  }
}

# Catch occurrence of any cartesian product that can trick the human eye by adding ORDER BY CLAUSE 

ORDER BY DESC  

这是一个通过应用禁用查询优化器的 pragma 生成正确解决方案的修订版。

DEFINE sql:disable-optimizations 16
PREFIX xsd:  <http://www.w3.org/2001/XMLSchema#>

SELECT ?date ?dayName
WHERE {
  # Sample dates
  VALUES ?date {
    "1961-08-04"^^xsd:date
    "1986-04-03"^^xsd:date
  }
  BIND (xsd:date(?date) - "1900-01-01"^^xsd:date AS ?days)
  BIND (bif:mod (?days, xsd:dayTimeDuration("P7D")) AS ?mod)
  VALUES (?mod ?dayName) {
         ("PT0S"^^xsd:dayTimeDuration "Monday") # 1900-01-01 was Monday
         ("P1D"^^xsd:dayTimeDuration    "Tuesday")
         ("P2D"^^xsd:dayTimeDuration    "Wednesday")
         ("P3D"^^xsd:dayTimeDuration    "Thursday")
         ("P4D"^^xsd:dayTimeDuration    "Friday")
         ("P5D"^^xsd:dayTimeDuration    "Saturday")
         ("P6D"^^xsd:dayTimeDuration    "Sunday")
  }
}
ORDER BY DESC (?date)

SPARQL Query Results Page