Elasticsearch时区问题
发现问题
- 创建索引,配置date类型字段
- 批量插入数据,格式分别为带时区信息,不带时区信息,时间戳
- 对数据进行聚合
- 对数据进行查询,分别使用带时区信息,不带时区信息,时间戳三种格式
创建索引,配置字段类型
PUT testdate
{"mappings": {"testdate":{"properties": {"tag":{"type": "keyword"},"datetime":{"type": "date"}}}}
}
批量插入数据
POST /_bulk
{"create":{"_index":"testdate","_type":"testdate","_id":1}}
{"tag":"带时区信息","datetime":"2019-07-15T08:00:00+08:00"}
{"create":{"_index":"testdate","_type":"testdate","_id":2}}
{"tag":"不带时区信息","datetime":"2019-07-15T08:00:00"}
{"create":{"_index":"testdate","_type":"testdate","_id":3}}
{"tag":"时间戳","datetime":"1563148800000"}
对数据进行聚合操作
不带时区信息聚合
POST /testdate/testdate/_search
{"size": 0, "aggs": {"aggs_datetime": {"date_histogram": {"field": "datetime","interval": "hour"},"aggs": {"aggs_tag": {"terms": {"field": "tag","size": 10}}}}}
}
结果
不带时区信息时间显示正常, 时间戳和带时区信息时间提前8小时
{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 0,"hits": []},"aggregations": {"aggs_datetime": {"buckets": [{"key_as_string": "2019-07-15T00:00:00.000Z","key": 1563148800000,"doc_count": 2,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "带时区信息","doc_count": 1},{"key": "时间戳","doc_count": 1}]}},{"key_as_string": "2019-07-15T01:00:00.000Z","key": 1563152400000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T02:00:00.000Z","key": 1563156000000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T03:00:00.000Z","key": 1563159600000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T04:00:00.000Z","key": 1563163200000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T05:00:00.000Z","key": 1563166800000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T06:00:00.000Z","key": 1563170400000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T07:00:00.000Z","key": 1563174000000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T08:00:00.000Z","key": 1563177600000,"doc_count": 1,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "不带时区信息","doc_count": 1}]}}]}}
}
东八区
POST /testdate/testdate/_search
{"size": 0, "aggs": {"aggs_datetime": {"date_histogram": {"field": "datetime","interval": "hour","time_zone": "+08:00"},"aggs": {"aggs_tag": {"terms": {"field": "tag","size": 10}}}}}
}
结果
时间戳和带时区信息时间显示正常, 不带时区信息时间推后8小时
{"took": 3,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 0,"hits": []},"aggregations": {"aggs_datetime": {"buckets": [{"key_as_string": "2019-07-15T08:00:00.000+08:00","key": 1563148800000,"doc_count": 2,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "带时区信息","doc_count": 1},{"key": "时间戳","doc_count": 1}]}},{"key_as_string": "2019-07-15T09:00:00.000+08:00","key": 1563152400000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T10:00:00.000+08:00","key": 1563156000000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T11:00:00.000+08:00","key": 1563159600000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T12:00:00.000+08:00","key": 1563163200000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T13:00:00.000+08:00","key": 1563166800000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T14:00:00.000+08:00","key": 1563170400000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T15:00:00.000+08:00","key": 1563174000000,"doc_count": 0,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": []}},{"key_as_string": "2019-07-15T16:00:00.000+08:00","key": 1563177600000,"doc_count": 1,"aggs_tag": {"doc_count_error_upper_bound": 0,"sum_other_doc_count": 0,"buckets": [{"key": "不带时区信息","doc_count": 1}]}}]}}
}
对数据进行结构化查询
时间戳
POST /testdate/testdate/_search
{"query": {"range": {"datetime": {"gte": 1563148800000}}}
}
三条数据全部返回
{"took": 2,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 1,"hits": [{"_index": "testdate","_type": "testdate","_id": "2","_score": 1,"_source": {"tag": "不带时区信息","datetime": "2019-07-15T08:00:00"}},{"_index": "testdate","_type": "testdate","_id": "1","_score": 1,"_source": {"tag": "带时区信息","datetime": "2019-07-15T08:00:00+08:00"}},{"_index": "testdate","_type": "testdate","_id": "3","_score": 1,"_source": {"tag": "时间戳","datetime": "1563148800000"}}]}
}
不带时区
POST /testdate/testdate/_search
{"query": {"range": {"datetime": {"gte": "2019-07-15T08:00:00"}}}
}
只返回了不带时区信息的一条数据
{"took": 1,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 1,"max_score": 1,"hits": [{"_index": "testdate","_type": "testdate","_id": "2","_score": 1,"_source": {"tag": "不带时区信息","datetime": "2019-07-15T08:00:00"}}]}
}
带时区
POST /testdate/testdate/_search
{"query": {"range": {"datetime": {"gte": "2019-07-15T08:00:00+08:00"}}}
}
三条数据全部返回
{"took": 0,"timed_out": false,"_shards": {"total": 5,"successful": 5,"skipped": 0,"failed": 0},"hits": {"total": 3,"max_score": 1,"hits": [{"_index": "testdate","_type": "testdate","_id": "2","_score": 1,"_source": {"tag": "不带时区信息","datetime": "2019-07-15T08:00:00"}},{"_index": "testdate","_type": "testdate","_id": "1","_score": 1,"_source": {"tag": "带时区信息","datetime": "2019-07-15T08:00:00+08:00"}},{"_index": "testdate","_type": "testdate","_id": "3","_score": 1,"_source": {"tag": "时间戳","datetime": "1563148800000"}}]}
}
原因分析
/*** @desc : 时间戳* @author : cheng* @date : 2019-12-10 23:23*/@Testpublic void testA() throws Exception{String dateStr = "2019-07-15 08:00:00";SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 解析字符串,时区:东八区Date date = dateFormat.parse(dateStr);System.out.println(date.getTime());// 格式化日期,时区:0时区dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));System.out.println(dateFormat.format(date));}// 输出15631488000002019-07-15 00:00:00
/*** @desc : 带时区* @author : cheng* @date : 2019-12-10 23:24*/@Testpublic void testB() throws Exception{String dateStr = "2019-07-15 08:00:00+0800";SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ssZ");// 解析字符串,时区:东八区Date date = dateFormat.parse(dateStr);// 格式化日期,时区:0时区dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));System.out.println(dateFormat.format(date));}// 输出2019-07-15 00:00:00+0000
/*** @desc : 不带时区信息* @author : cheng* @date : 2019-12-10 23:23*/@Testpublic void testC() throws Exception{String dateStr = "2019-07-15 08:00:00";SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 解析字符串,时区:0时区dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));Date date = dateFormat.parse(dateStr);// 格式化日期,时区:0时区dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));System.out.println(dateFormat.format(date));}// 输出2019-07-15 08:00:00
ES日期类型使用UTC
时间戳1563148800000
时间戳本身就是UTC毫秒数, 和时区没有关系, 实际存储的就是这个值
String dateStr = "2019-07-15 08:00:00";
// 时间戳和时区无关, UTC毫秒数
System.out.println(DateUtils.parseDate(dateStr, Locale.ENGLISH, "yyyy-MM-dd HH:mm:ss").getTime());
System.out.println(DateUtils.parseDate(dateStr, Locale.US, "yyyy-MM-dd HH:mm:ss").getTime());
System.out.println(DateUtils.parseDate(dateStr, Locale.FRENCH, "yyyy-MM-dd HH:mm:ss").getTime());输出
1563148800000
1563148800000
1563148800000
不带时区信息格式2019-07-15T08:00:00
等价于2019-07-15T08:00:00+00:00, 默认就是UTC 0时区时间, 实际存储的就是这个值
带时区信息格式2019-07-15T08:00:00+08:00
东八区时间 = UTC0时区 + 8个小时
所以实际存储的值为UTC0时区 = 东八区 - 8小时 = 2019-07-15T00:00:00+00:00, 实际存储2019-07-15T00:00:00+00:00
// 本地时间为2019-07-15 08:00:00
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// 不设置时区, 默认为机器所在时区
System.out.println(sdf.format(date));// 东八区
sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
System.out.println(sdf.format(date));// 0时区 = 东八区 - 8个小时
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(date));输出
2019-07-15 08:00:00
2019-07-15 08:00:00
2019-07-15 00:00:00
总结
- 存储:es使用UTC时间存储date类型
- 查询:查询的时间会转换成UTC时间,然后进行查询操作
使用建议
- 强制:存入es的日期类型数据,必须全部带上时区信息或者使用时间戳(可视化效果差,不建议)
- 强制:使用日期聚合时,必须带上时区信息
- 强制:查询日期类型数据是,必须带上时区信息,或者时间戳(可视化效果差,不建议)
索引中的文档存在跨时区,那么索引,聚合,查询时都需要带上时区信息
索引中的文档不存在跨时区,即全在同一时区,那么索引,聚合,查询时都不需要带上时区信息
Elasticsearch时区问题相关推荐
- Elasticsearch 滞后8个小时等时区问题,一网打尽!
1.实战问题 如下都是实战环节遇到的问题: logstash谁解决过时区问题,mysql是东八区shanghai 但是这玩意读完存到es就少了8小时? 目前索引会比真正时间晚8小时,导致8点前的日志写 ...
- Elasticsearch中的date与时区问题
1 前言 本文主要讲解Elasticsearch中date类型数据的底层存储原理,以及对带时区日期字符串和不带时区的日期字符串如何在ES底层存储进行验证.对于直接存储Long类型时间戳,不作过多描述. ...
- Elasticsearch查询相关总结以及timestamp和时区问题
ES查询相关 参考:https://www.cnblogs.com/qdhxhz/p/11493677.html 如果想筛选出特定时间段的event,可以在查询语句里使用post_filter POS ...
- java反序列化时区,Jackson使用Java 8将Elasticsearch反序列化为LocalDateTime
我们在日期字段中填充了longinlasticsearch索引. 字段映射为: @Field(type = FieldType.Date) @JsonFormat(shape = JsonFormat ...
- elasticsearch docker无法挂载_使用Docker安装Graylog日志收集系统
1.创建并进入到用于存放Graylog配置文件的目录 mkdir -p /data/graylog/config && cd /data/graylog/config 2.下载Gray ...
- 平滑无损!引入Elasticsearch的系统架构实战
[文章来源]https://sourl.cn/L6WUGC 前 言 我曾经面试安踏的技术岗,当时面试官问了我一个问题:如果你想使用某个新技术但是领导不愿意,你怎么办? 对于该问题我相信大家就算没有面试 ...
- elasticsearch数据长期保存的方案
Elasticsearch的数据就存储在硬盘中.当我们的访问日志非常大时,kabana绘制图形的时候会非常缓慢.而且硬盘空间有限,不可能保存所有的日志文件.如果我们想获取站点每天的重要数据信息,比如每 ...
- ElasticSearch大数据分布式弹性搜索引擎使用
阅读目录: 背景 安装 查找.下载rpm包 .执行rpm包安装 配置elasticsearch专属账户和组 设置elasticsearch文件所有者 切换到elasticsearch专属账户测试能否成 ...
- 使用docker搭建一个elasticsearch(5.4)的基础环境
2019独角兽企业重金招聘Python工程师标准>>> docker is a cool technology! 这篇文章主要讲解的是搭建一个es的基本环境(默认docker环境已经 ...
最新文章
- CentOS 5.5 编译安装apache+php+mysql,利用CMS快速建立论坛
- win10镜像重装,快速设置之后无限重启怎么办?
- 《深入理解java虚拟机》
- 解决Layui的switch样式显示问题
- OSChina 周三乱弹 —— 孤独到都和病毒发生了感情了
- 【opencv系列06】OpenCV4.X滑动条操作
- 【Tiny4412】 Android系统的烧写
- Netty初步之hello world
- 零云九歌小组KTV点歌系统简介
- PCM复用设备和PDH设备的区别介绍
- 解决linux下QtCreator无法输入中文的情况
- python的回收机制_Python的垃圾回收机制深入分析
- bootstrap 3.0 LESS源代码浅析(一)
- 一、Java多线程基础
- 新基建 X 巡检机器人:AI赋能,从“前锋”到“统帅”
- C++11创建线程的三种方式
- [Python]更改图片底色
- ERP常用模块顾问行情对比
- 计算机卷死,一位计算机教师死了,警方在床底发现一张纸,上面写着一些特殊的符号,这... #119615-推理漫画-侦探推理-33IQ...
- 每周一看:16份文档资料,程序员软硬实力全概览,总有一个适合你