Elasticsearch默认为UTC时间,即零时区,查询时若不指定时区,则默认以0时区查询,和我们所在的东八区差8小时。yyyy-MM-dd’T’HH:mm:ss.SSSZ,这里的Z就代表UTC时区。
查询指定时区
Es在进行日期查询/聚合时可以指定时区:
//日期范围查询
POST datatypetest/_search
{
"query": {
"range": {
"date3": {
"gte": "2018-07-05",
"lte": "now",
"time_zone": "Asia/Shanghai"//这就是东八区(北京时间/中国标准时间)
}
}
}
}
//日期聚合
GET my_index/_search?size=0
{
"aggs": {
"by_day": {
"date_histogram": {
"field": "date",
"interval": "day",
"time_zone": "Asia/Shanghai"
}
}
}
}
//Java获取系统时区id
TimeZone.getDefault().getID()
//Es Java Api日期范围查询
QueryBuilders
.rangeQuery("your date field")
.gte("your date from")
.lte("your date to")
.timeZone(TimeZone.getDefault().getID());//此处只能设置时区id
//Es Java Api日期聚合查询
AggregationBuilders
.dateHistogram("your alias")
.timeZone(DateTimeZone.getDefault());//获取系统默认时区,此处timeZone对象是joda包中的DateTimeZone
在使用Kibana时,Kibana会默认获取浏览器时区,在显示数据时根据时区做日期的格式化。但使用DevTools写DSL或者直接请求Es时默认返回的都是UTC时间,会发现时间少了8小时。
改kibana时区
kibana 默认时区是浏览器时区。可以修改,修改方式如下:
Stack Management -> Advanced Settings ->Timezone for data formatting.
Logstash
默认UTC
真实同步案例讲解一下时区处理:
- 数据源端:Mysql;
- 数据目的端:Elasticsearch;
- 同步方式:logstash,本质借助:logstash_input_jdbc 插件同步;
- 时区处理:logstash filter 环节 ruby 脚本处理。
如下只给出了中间 filter 环节的脚本:
filter {
ruby {
code => "event.set('timestamp', event.get('publish_time').time.localtime + 8*60*60)"
}
ruby {
code => "event.set('publish_time',event.get('timestamp'))"
}
mutate {
remove_field => ["timestamp"]
}
}
三行脚本含义,解释如下:
- 第一行:将 publish_time 时间加 8 小时处理,赋值给 timestamp。
publish_time 到了 logstash 已转成了 UTC 时区了。
timestamp 类似似 C 语言中的交换两个数函数中的 temp 临时变量。
- 第二行:将 timestamp 时间赋值给 publish_time。
- 第三行:删除中转字段:timestamp。
源数据Mysql 效果:
同步后 效果:
如上两个截图,对比一下区别:
- publish_time 做了时区处理,两者时间已一致,都是东 8 区。
update_time 未做时间处理,写入Elasticsearch 后由东8区时间 10:57:31 转为UTC时区时间 02:57:31,少了8小时。
ingest pipeline 预处理
步骤 1:定义预处理管道:chage_utc_to_asiash(名称自己定义即可)。
在该管道中实现了时区转换。
- 步骤 2:创建索引同时指定缺省管道:chage_utc_to_asiash。
- 步骤 3:写入数据(单条或 bulk 批量均可)
```shell
PUT _ingest/pipeline/chage_utc_to_asiash
{
“processors”: [
{
} ] }"date" : { "field" : "my_time", "target_field": "my_time", "formats" : ["yyyy-MM-dd HH:mm:ss"], "timezone" : "Asia/Shanghai" }
PUT my-index-000001 { “settings”: { “default_pipeline”: “chage_utc_to_asiash” }, “mappings”: { “properties”: { “my_time”: { “type”: “date” } } } }
PUT my-index-000001/_doc/1 { “my_time”: “2021-08-09 08:07:16” }
当写入数据后,执行检索时,kibana dev tool 返回结果如下:
```shell
"hits" : [
{
"_index" : "my-index-000001",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"my_time" : "2021-08-09T08:07:16.000+08:00"
}
}
]
最明显的特征是:多了+08:00 时区(东8区)标志。