相关疑难解决方法(0)

Elastic Search 和 Y10k(超过 4 位数的年份)

我在 Elastic Search 查询中发现了这个问题,但由于ES 日期格式文档链接到java.time.format.DateTimeFormatter类的API 文档,因此该问题并不是真正特定于 ES 的。

简短摘要:我们遇到了超过 9999 年的日期问题,更准确地说,是超过 4 位数字的年份。

存储在 ES 中的文档有一个日期字段,它在索引描述符中定义为格式“date”,使用 DateTimeFormatter 的模式语言对应于“yyyy-MM-dd”。我们正在获取用户输入,使用 org.apache.commons.validator.DateValidator.isValid 也使用模式“yyyy-MM-dd”验证输入,如果有效,我们会使用用户输入创建一个 ES 查询。如果用户输入诸如 20202-12-03 之类的内容,这将失败并执行 execption。搜索词可能不是故意的,但预期的行为是找不到任何东西,而不是软件咳出异常。

问题是 org.apache.commons.validator.DateValidator 在内部使用旧的 SimpleDateFormat 类来验证输入是否符合模式,并且 SimpleDateFormat 解释的“yyyy”的含义类似于:使用至少 4 位数字,但如果需要,允许更多的数字。因此,使用模式“yyyy-MM-dd”创建 SimpleDateFormat 将解析像“20202-07-14”这样的输入,并类似地格式化年超过 9999 的 Date 对象。

新的 DateTimeFormatter 类更加严格,意味着“yyyy”正好是四位数字。它将无法解析像“20202-07-14”这样的输入字符串,也无法格式化年份超过 9999 的 Temporal 对象。值得注意的是,DateTimeFormatter 本身能够处理可变长度字段。例如,常量 DateTimeFormatter.ISO_LOCAL_DATE 不等同于“yyyy-MM-dd”,但符合 ISO8601,允许超过四位数的年份,但将使用至少四位数。此常量是使用 DateTimeFormatterBuilder 以编程方式创建的,而不是使用模式字符串。

ES 不能配置为使用 DateTimeFormatter 中定义的常量,如 ISO_LOCAL_DATE,但只能使用模式字符串。ES 还知道一个预定义模式列表,文档中偶尔也会引用 ISO 标准,但他们似乎误会并忽略了有效的 ISO 日期字符串可以包含五位数年份。

我可以使用多个允许的日期模式列表配置 ES,例如“yyyy-MM-dd||yyyyy-MM-dd”。这将允许在年份中使用四位数和五位数,但对于六位数年份则失败。我可以通过添加另一个允许的模式来支持六位数的年份:“yyyy-MM-dd||yyyyy-MM-dd||yyyyyy-MM-dd”,但是它在七位数年份失败等等。

我是在监督某些事情,还是真的不可能将 ES(或使用模式字符串的 DateTimeFormatter 实例)配置为具有 ISO 标准所使用的至少四位数(但可能更多)的年份字段?

java datetime-format elasticsearch

10
推荐指数
1
解决办法
476
查看次数

标签 统计

datetime-format ×1

elasticsearch ×1

java ×1