Java 时间迁移指南
编辑Java 时间迁移指南
编辑在 7.0 版本中,Elasticsearch 将日期相关的解析、格式化和计算从 joda time 切换到了 java time。本指南旨在帮助您确定您的集群是否受到影响,如果受到影响,则帮助您为升级做好准备。
转换日期格式
编辑要升级到 Elasticsearch 8,您需要将任何 joda-time 日期格式转换为其 java-time 等效格式。
受影响的功能
编辑切换到 java time 仅影响自定义 date
和 date_nanos
格式。
这些格式通常用于
如果您不使用自定义日期格式,则可以跳过本指南的其余部分。大多数自定义日期格式都是兼容的。但是,有几个需要更新。
要查看您的日期格式是否受到影响,请使用 弃用信息 API 或 Kibana 升级助手。
不兼容的日期格式
编辑应迁移包含以下 joda-time 字面量的自定义日期格式。
-
Y
(年代年份) -
替换为
y
。示例:
YYYY-MM-dd
应变为yyyy-MM-dd
。在 java time 中,
Y
用于基于周的年份。在y
的位置使用Y
可能会导致年份计算中出现一位的误差。对于模式
YYYY-ww
和日期2019-01-01T00:00:00.000Z
将给出2019-01
。对于模式YYYY-ww
和日期2018-12-31T00:00:00.000Z
将给出2019-01
(违反直觉),因为 2019 年该周的日期有超过 4 天。 -
y
(年份) -
替换为
u
。示例:
yyyy-MM-dd
应变为uuuu-MM-dd
。在 java time 中,
y
用于年代年份。u
可以包含非正值,而y
不能。y
还可以与年代字段关联。 -
C
(年代世纪) -
java time 中不支持年代世纪。没有替换项。相反,我们建议您预处理输入。
-
x
(周年份) -
替换为
Y
。在 java time 中,
x
表示 时区偏移量。未能正确将
x
(周年份)转换为Y
可能会导致数据丢失。 -
Z
(时区偏移量/ID) -
替换为多个
X
。Z
在 java time 中具有相似的含义。但是,java time 需要不同数量的字面量来解析不同的形式。考虑迁移到
X
,这样您可以更好地控制时间的解析方式。例如,joda-time 格式YYYY-MM-dd'T'hh:mm:ssZZ
接受以下日期2010-01-01T01:02:03Z 2010-01-01T01:02:03+01 2010-01-01T01:02:03+01:02 2010-01-01T01:02:03+01:02:03
在 java time 中,您不能使用单个格式解析所有这些日期。相反,您必须指定 3 种单独的格式
2010-01-01T01:02:03Z 2010-01-01T01:02:03+01 both parsed with yyyy-MM-dd'T'hh:mm:ssX 2010-01-01T01:02:03+01:02 yyyy-MM-dd'T'hh:mm:ssXXX 2010-01-01T01:02:03+01:02:03 yyyy-MM-dd'T'hh:mm:ssXXXXX
然后必须使用
||
分隔这些格式yyyy-MM-dd'T'hh:mm:ssX||yyyy-MM-dd'T'hh:mm:ssXXX||yyyy-MM-dd'T'hh:mm:ssXXXXX
如果您期望模式出现在没有冒号 (
:
) 的情况下,则同样适用:例如,YYYY-MM-dd'T'hh:mm:ssZ
格式接受以下日期形式2010-01-01T01:02:03Z 2010-01-01T01:02:03+01 2010-01-01T01:02:03+0102 2010-01-01T01:02:03+010203
要接受 java time 中的所有这些形式,您必须使用
||
分隔符yyyy-MM-dd'T'hh:mm:ssX||yyyy-MM-dd'T'hh:mm:ssXX||yyyy-MM-dd'T'hh:mm:ssXXXX
-
d
(天) -
在 java time 中,
d
仍然被解释为“天”,但灵活性较差。例如,joda-time 日期格式
YYYY-MM-dd
接受2010-01-01
或2010-01-1
。在 java time 中,您必须使用
||
分隔符来指定每种格式yyyy-MM-dd||yyyy-MM-d
在 java time 中,
d
也不接受超过 2 位数字。要接受超过两位数字的天数,您必须在 java-time 日期格式中包含文本字面量。例如,要解析2010-01-00001
,您必须使用以下 java-time 日期格式yyyy-MM-'000'dd
-
e
(星期几的名称) -
在 java time 中,
e
仍然被解释为“星期几的名称”,但不解析短文本或全文形式。例如,joda-time 日期格式
EEE YYYY-MM
接受Wed 2020-01
和Wednesday 2020-01
。要在 java time 中接受这两种日期,您必须使用
||
分隔符指定每种格式cccc yyyy-MM||ccc yyyy-MM
joda-time 字面量
E
被解释为“星期几”。java-time 字面量c
被解释为“本地化的星期几”。E
不接受全文的星期格式,例如Wednesday
。 -
EEEE
和类似的文本形式 -
对全文形式的支持取决于 Java 开发工具包 (JDK) 提供的区域设置数据和其他实现细节。我们建议您在升级之前仔细测试包含这些模式的格式。
-
z
(时区文本) -
在 java time 中,当给定 UTC 时区时,
z
会为 Zulu 输出 Z。
使用您的数据进行测试
编辑我们强烈建议您在生产环境中部署之前,使用真实数据测试任何日期格式更改。
更新索引映射
编辑要在索引映射中更新 joda-time 日期格式,您必须创建一个具有更新映射的新索引,并将您的数据重新索引到该索引。
以下 my-index-000001
索引包含 datetime
字段的映射,这是一个带有自定义 joda-time 日期格式的 date
字段。
resp = client.indices.get_mapping( index="my-index-000001", ) print(resp)
response = client.indices.get_mapping( index: 'my-index-000001' ) puts response
const response = await client.indices.getMapping({ index: "my-index-000001", }); console.log(response);
GET my-index-000001/_mapping
{ "my-index-000001" : { "mappings" : { "properties" : { "datetime": { "type": "date", "format": "yyyy/MM/dd HH:mm:ss||yyyy/MM/dd||epoch_millis" } } } } }
要更改 datetime
字段的日期格式,请创建一个单独的索引,其中包含更新的映射和日期格式。
例如,以下 my-index-000002
索引将 datetime
字段的日期格式更改为 uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis
。
response = client.indices.create( index: 'my-index-000002', body: { mappings: { properties: { datetime: { type: 'date', format: 'uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis' } } } } ) puts response
PUT my-index-000002 { "mappings": { "properties": { "datetime": { "type": "date", "format": "uuuu/MM/dd HH:mm:ss||uuuu/MM/dd||epoch_millis" } } } }
接下来,将数据从旧索引重新索引到新索引。
以下 重新索引 API 请求将数据从 my-index-000001
重新索引到 my-index-000002
。
response = client.reindex( body: { source: { index: 'my-index-000001' }, dest: { index: 'my-index-000002' } } ) puts response
POST _reindex { "source": { "index": "my-index-000001" }, "dest": { "index": "my-index-000002" } }
如果您使用索引别名,请更新它们以指向新索引。
POST /_aliases { "actions" : [ { "remove" : { "index" : "my-index-000001", "alias" : "my-index" } }, { "add" : { "index" : "my-index-000002", "alias" : "my-index" } } ] }