日期格式化和日期数学

日期格式化

Solr 的日期字段(DatePointFieldDateRangeField 和已弃用的 TrieDateField)以毫秒精度将“日期”表示为一个时间点。所使用的格式是 XML Schema 规范 中日期时间规范表示的受限形式——ISO-8601 的受限子集。对于熟悉 Java 日期处理的用户,Solr 使用 DateTimeFormatter.ISO_INSTANT 进行格式化,并使用“宽松”进行解析。

YYYY-MM-DDThh:mm:ssZ

  • YYYY 是年份。

  • MM 是月份。

  • DD 是该月的日期。

  • hh 是 24 小时制中的小时。

  • mm 是分钟。

  • ss 是秒。

  • Z 是一个表示日期的字符串表示形式在 UTC 中的文字“Z”字符。

请注意,不能指定时区;日期的字符串表示形式始终以协调世界时 (UTC) 表示。以下是一个示例值

1972-05-20T17:33:18Z

如果需要,您可以选择包含小数秒,但会忽略超过毫秒精度的任何精度。以下是包含子秒的示例值

  • 1972-05-20T17:33:18.772Z

  • 1972-05-20T17:33:18.77Z

  • 1972-05-20T17:33:18.7Z

对于公元前 0000 年之前的日期,必须有前导的 '-',而对于公元后 9999 年之后的日期,Solr 将使用前导的 '+' 格式化日期。公元前 0000 年被视为公元前 1 年;没有公元 0 年或公元前 0 年。

可能需要转义查询

如您所见,日期格式包括分隔小时、分钟和秒的冒号字符。由于冒号是 Solr 最常见的查询解析器的特殊字符,因此有时需要转义,具体取决于您要执行的操作。

这通常是一个无效的查询:datefield:1972-05-20T17:33:18.772Z

这些是有效的查询

datefield:1972-05-20T17\:33\:18.772Z

datefield:"1972-05-20T17:33:18.772Z"

datefield:[1972-05-20T17:33:18.772Z TO *]

日期范围格式化

Solr 的 DateRangeField 支持上面描述的相同时间点日期语法(带有下面描述的日期运算),以及更多内容以表示日期范围。一类示例是截断日期,它表示以指示的精度表示的整个日期跨度。另一类使用范围语法([ TO ])。以下是一些示例

  • 2000-11 – 2000 年 11 月的整个月。

  • 1605-11-05 – 11 月 5 日。

  • 2000-11-05T13 – 同样,但对于一天中的一个小时(1300 到 1400 之前,即下午 1 点到下午 2 点)。

  • -0009 – 公元前 10 年。年份位置中的 0 是公元 0 年,也被视为公元前 1 年。

  • [2000-11-01 TO 2014-12-01] – 按天分辨率指定日期范围。

  • [2014 TO 2014-12-01] – 从 2014 年年初到 12 月 1 日结束。

  • [* TO 2014-12-01] – 从最早可表示时间到 2014-12-01 当天的结束。

限制:范围语法不支持嵌入式日期运算。如果你指定 DatePointField 支持的日期实例,并使用日期运算对其进行截断,如 NOW/DAY,你仍会得到该天的第一毫秒,而不是整天的范围。排除范围(使用 {})适用于查询,但不适用于索引范围。

日期运算

Solr 的日期字段类型还支持日期运算表达式,这使得创建相对于固定时刻的时间变得容易,包括可以使用特殊值“NOW”表示的当前时间。

日期运算语法

日期运算表达式包括在指定单位中添加一定量的时间,或按指定单位舍入当前时间。表达式可以链接,并且从左到右求值。

例如:这表示从现在起两个月的时间点

NOW+2MONTHS

这是前一天

NOW-1DAY

使用斜杠表示舍入。这表示当前小时的开始

NOW/HOUR

以下示例计算(以毫秒精度)未来六个月和三天的时刻,然后将该时间舍入到该天的开始

NOW+6MONTHS+3DAYS/DAY

请注意,虽然日期运算最常相对于 NOW 使用,但它也可以应用于任何固定的时刻

1972-05-20T17:33:18.772Z+6MONTHS+3DAYS/DAY

日期运算单位选项

以下单位在日期运算表达式中有效。第一列是 Solr 中日期运算表达式中使用的值。第二列是它映射到的时间单位,因为给定的时间单位有多个别名。

日期运算表达式单位 时间单位

YEAR

YEARS

MONTH

MONTHS

DAY

DAYS

DATE

HOUR

小时

HOURS

小时

MINUTE

分钟

MINUTES

分钟

SECOND

SECONDS

MILLI

毫秒

MILLIS

毫秒

MILLISECOND

毫秒

MILLISECONDS

毫秒

影响日期运算的请求参数

NOW

NOW 参数在 Solr 内部使用,以确保在分布式请求中的多个节点之间对日期数学表达式进行一致的解析。但可以指定该参数,指示 Solr 使用任意时刻(过去或未来)来覆盖所有 NOW 特殊值会影响日期数学表达式的场景。

必须指定为自纪元以来的毫秒数(长整型值)。

示例

q=solr&fq=start_date:[* TO NOW]&NOW=1384387200000

TZ

默认情况下,所有日期数学表达式都相对于 UTC 时区进行计算,但可以指定 TZ 参数来覆盖此行为,强制所有基于日期的加法和舍入相对于指定的 时区

例如,以下请求将使用范围分面来按当前月份分面,相对于 UTC“每天”

http://localhost:8983/solr/my_collection/select?q=*:*&facet.range=my_date_field&facet=true&facet.range.start=NOW/MONTH&facet.range.end=NOW/MONTH%2B1MONTH&facet.range.gap=%2B1DAY&wt=xml
<int name="2013-11-01T00:00:00Z">0</int>
<int name="2013-11-02T00:00:00Z">0</int>
<int name="2013-11-03T00:00:00Z">0</int>
<int name="2013-11-04T00:00:00Z">0</int>
<int name="2013-11-05T00:00:00Z">0</int>
<int name="2013-11-06T00:00:00Z">0</int>
<int name="2013-11-07T00:00:00Z">0</int>
...

而在本示例中,“天”将相对于指定时区进行计算 - 包括任何适用的夏令时调整

http://localhost:8983/solr/my_collection/select?q=*:*&facet.range=my_date_field&facet=true&facet.range.start=NOW/MONTH&facet.range.end=NOW/MONTH%2B1MONTH&facet.range.gap=%2B1DAY&TZ=America/Los_Angeles&wt=xml
<int name="2013-11-01T07:00:00Z">0</int>
<int name="2013-11-02T07:00:00Z">0</int>
<int name="2013-11-03T07:00:00Z">0</int>
<int name="2013-11-04T08:00:00Z">0</int>
<int name="2013-11-05T08:00:00Z">0</int>
<int name="2013-11-06T08:00:00Z">0</int>
<int name="2013-11-07T08:00:00Z">0</int>
...

更多 DateRangeField 详细信息

DateRangeField 几乎可以替代使用 DatePointField 的位置。唯一的区别是 Solr 的 XML 或 SolrJ 响应格式会将存储的数据显示为字符串,而不是日期。此字段的底层索引数据将稍大一些。与一秒及以上时间单位对齐的查询应比 TrieDateField 更快,尤其是在 UTC 中时。

顾名思义,DateRangeField 的主要目的是允许索引日期范围。要执行此操作,只需按上述格式提供字符串即可。它还支持在索引数据和查询范围之间指定 3 种不同的关系谓词

  • Intersects(默认)

  • Contains

  • Within

可以通过使用 op 本地参数参数进行查询来指定谓词,如下所示

fq={!field f=dateRange op=Contains}[2013 TO 2018]

与大多数本地参数不同,op 实际上不是由任何查询解析器(field)定义的,而是由字段类型(在本例中为 DateRangeField)定义的。在上述示例中,它将查找索引范围包含(或等于)范围 2013 到 2018 的文档。文档中的多值重叠索引范围将有效合并。

有关 DateRangeField 示例用例,请参阅 请参阅 Solr 的社区 wiki