概述
- es中date类型字段, 底层写入转换规则:
- 如果写入的时间字段没有时区偏移量标识,elasticsearch 就会默认它为UTC时间,即0时区时间,并且转为(epoch time millisecond)毫秒值保存
- es中的date类型字段有映射属性format
- format 用来指定该字段时间日期的格式
- 未指定时默认为"format": "strict_date_optional_time||epoch_millis", 其中
strict_date_optional_time
格式对应的java中的时间日期格式为:yyyy-MM-dd'T'HH:mm:ss.SSSZ
或yyyy-MM-dd
。这个也是最常见的时间日期格式, 其中时区偏移量标识为Z
Z
在某些日期格式下, 在具体的某一日期值后面出现时表示该时间为格林威治时,就是本初子午线所在地的时间- 本初子午线, 即0度经线,亦称格林威治子午线或格林尼治子午线
- 所以写入es的时候需要带上时区偏移量, 以这种形式写入, 例如:
"time":"2024-09-04T12:03:10.158 0800"
- 在kibana的discover中去查看数据时 , kibana会根据浏览器时区给创时间字段再加上时区偏移量的值
- 案例
- 比如我有这样一条记录, 可以看到这个文档中时间字段值为"@timestamp" : "2024-08-02T11:38:53.953Z", 这里Z就是指定的0时区
- elasticsearch由java语言编写,里面使用的java中的时间日期格式类如下
DateTimeFormatter (Java Platform SE 8 ) (oracle.com)
- 所有字母“A”到“Z”和“a”到“z”都保留为模式字母。定义了以下模式字母
- 其中关于时区的有以下几个字母
不同字母表示时区的用法
以下列举了几种不同字母表示时区的用法, 演示为主, 代码执行时最好将案例时间2024-05-18换成您这边执行的当天日期,这样比较容易在discover中去查看, 如果您这边用默认format, 直接看总结就行
时区用大写V表示
- 时区可以是zone-id,例如
America/Los_Angeles
,Asia/Shanghai
等,也可以是Z以及 00:00的时区偏移量的形式
# 时区用V表示时,需要用两个大V,我这里时区用|隔开下,原版打算用[]包裹,但是[]应该也是保留内容
DELETE date_format_time_zone_big_v_test
PUT date_format_time_zone_big_v_test
{
"mappings": {
"properties": {
"@timestamp":{
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|VV"
}
}
}
}
PUT date_format_time_zone_big_v_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-18T16:00:00|Z","message": "UTC时间16点整"}
{"create":{}}
{"@timestamp": "2024-05-19T00:00:00| 08:00","message": "东八区时间0点整"}
{"create":{}}
{"@timestamp": "2024-05-19T00:00:00|Asia/Shanghai","message": "上海时区0点整"}
- 有哪些可用的zone-id,可以在这里找到 https://blog.csdn.net/weixin_34392435/article/details/86028719 https://docs.oracle.com/javase/8/docs/api/java/time/ZoneId.html 最好可以直接到源码中去找, 我这里条件有限,仅部分演示
- 在discover中创建索引模式, 可以看到表示的是同一个时间
时区用小写z表示
- 时区用小写z表示时
- 时区需要写zone-name
- 下面整理了部分zone-name到对应zone-id的对应关系 https://24time.hnymr.com/abbr
- UTC是标准时间参照,像GMT(格林威治时间)、ET(美国东部时间)、PST(太平洋时间)、CST(北京时间)等等都是具体的时区时间。
- GMT能和UTC直接转换,仅仅是因为碰巧GMT是0时区时间,数值上刚好和UTC是相等的(不需要精确到秒的情况下,二者可以视为相等),看起来一样,但是概念含义上请务必区分开来哈。
- 测试如下
# 时区用z表示即zone-name, 与具体时间用|隔开
DELETE date_format_time_zone_small_z_test
PUT date_format_time_zone_small_z_test
{
"mappings": {
"properties": {
"@timestamp":{
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|z"
}
}
}
}
# UTC和GMT是同一个时区,AWST是澳大利亚时区,因为CST不支持中国标准时的缩写也是古巴或者中部标准时的缩写,所以这边用其他东8区的时区来代替
PUT date_format_time_zone_small_z_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-20T16:00:00|UTC","timestamp": "2024-05-20T16:00:00","message": "UTC时间16点整"}
{"create":{}}
{"@timestamp": "2024-05-20T16:00:00|GMT","timestamp": "2024-05-20T16:00:00","message": "GMT时间16点整"}
{"create":{}}
{"@timestamp": "2024-05-21T00:00:00|AWST","timestamp": "2024-05-21T00:00:00","message": "东八区/澳大利亚时区0点整"}
- 到discover中可以看到,是同一时间点的
时区用大写O表示
- 即
localized zone-offset
=zone-name
offset
- 例如:
GMT 8; GMT 08:00; UTC-08:00;
- 但是这里测试发现只有
GMT
可以用,其他时区缩写都解析不了
- 例如:
- offset格式为 H或者 H:MM
- 测试如下
DELETE date_format_time_zone_big_o_test
PUT date_format_time_zone_big_o_test
{
"mappings": {
"properties": {
"@timestamp":{
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|O"
},
"#timestamp":{
"type": "keyword"
}
}
}
}
# 这里测试了, 好像只有GMT可以用, 其他都解析不出来
PUT date_format_time_zone_big_o_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00|GMT 8","#timestamp": "2024-05-27T16:00:00|GMT 8","message": "比GMT时区快8小时的时区的16点,即北京时间16点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00|GMT 08:00","#timestamp": "2024-05-27T16:00:00|GMT 08:00","message": "比GMT时区快8小时的时区的16点,即北京时间16点"}
{"create":{}}
{"@timestamp": "2024-05-27T08:00:00|GMT 0","#timestamp": "2024-05-27T08:00:00|GMT 0","message": "GMT时区的8点"}
- 到discover中可以看到,是同一时间点的
时区用大写X表示
- 即
zone-offset 'Z' for zero
- 即相较于0时区的时间偏移量
- 示例值:
Z
;-08
;-0830
;-08:30
;-083015
;-08:30:15
; - 测试如下, 测试发现好像部分格式还是不支持不支持带冒号:以及最多支持4位数字
DELETE date_format_time_zone_big_x_test
PUT date_format_time_zone_big_x_test
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|X"
},
"#timestamp": {
"type": "keyword"
}
}
}
}
# 案例上支持很多形式, 但是实测只有这几种可以用
PUT date_format_time_zone_big_x_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-27T08:00:00|Z","#timestamp": "2024-05-27T08:00:00|Z","message": "0时区8点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 08","#timestamp": "2024-05-27T16:00:00| 08","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 0800","#timestamp": "2024-05-27T16:00:00| 0800","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
- 到discover中可以看到,是同一时间点的
时区用小写x表示
- 相较于0时区的偏移量
- 即
0000; -08; -0830; -08:30; -083015; -08:30:15;
- 测试如下, 实际还是最多只支持4位时区偏移量
DELETE date_format_time_zone_small_x_test
PUT date_format_time_zone_small_x_test
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|x"
},
"#timestamp": {
"type": "keyword"
}
}
}
}
PUT date_format_time_zone_small_x_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 08","#timestamp": "2024-05-27T16:00:00| 08","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 0800","#timestamp": "2024-05-27T16:00:00| 0800","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 08:00","#timestamp": "2024-05-27T16:00:00| 08:00","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
- 到discover中可以看到,是同一时间点的
时区用大写Z表示
- 相较于0时区的偏移量
- 即
0000; -0800; -08:00;
- 相比x只支持4位偏移量,2位8位都不支持,冒号:也不支持
- 测试如下
DELETE date_format_time_zone_big_z_test
PUT date_format_time_zone_big_z_test
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss|Z"
},
"#timestamp": {
"type": "keyword"
}
}
}
}
PUT date_format_time_zone_big_z_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-27T08:00:00| 0000","#timestamp": "2024-05-27T16:00:00| 0000","message": "0时区8点"}
{"create":{}}
{"@timestamp": "2024-05-27T16:00:00| 0800","#timestamp": "2024-05-27T16:00:00| 0800","message": "相较于0时区多8小时的所在地区的16点,即上海时间16点"}
- 到discover中可以看到,是同一时间点的
总结
- 不标注时区就默认0时区
- 标注时区,最终也会转换为0时区的毫秒值存储
- date类型默认format为strict_date_optional_time||epoch_millis
- strict_date_optional_time为日期必须至少包含年份和时间(由
T
分隔)的日期字符串。示例:yyyy-MM-dd'T'HH:mm:ss.SSSZ
或yyyy-MM-dd
。
DELETE date_format_strict_date_optional_time_test
PUT date_format_strict_date_optional_time_test
{
"mappings": {
"properties": {
"@timestamp": {
"type": "date",
"format": "strict_date_optional_time"
},
"#timestamp": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
}
}
}
}
PUT date_format_strict_date_optional_time_test/_bulk?refresh
{"create":{}}
{"@timestamp": "2024-05-27T08:00:00.000 0000","#timestamp": "2024-05-27T08:00:00.00 0000","message": "0时区8点"}
其他说明:
date类型有其他字段映射参数locale, 这个表示的是对应地区的语言, 比如将星期六理解为Saturday, 用来解析时间字段文本的,和时区无关
文章由牛朝阳本人撰写, 如转载或改编请标注来源
文档内容勘误, 请评论区留言, 欢迎大佬们协助改进指正