ElasticSearch里面关于日期的存储方式,解决差8个小时
生活随笔
收集整理的這篇文章主要介紹了
ElasticSearch里面关于日期的存储方式,解决差8个小时
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
在ElasticSearch里面最常用的就是時(shí)間字段了,經(jīng)常會(huì)在群里看到一些小伙伴提出有關(guān)時(shí)間的問(wèn)題,為什么es查詢的時(shí)間跟我實(shí)際看到的時(shí)間差8個(gè)小時(shí)呢。如果我們了解了ElasticSearch底層的時(shí)間存儲(chǔ)方式就會(huì)比較容易的理解這個(gè)問(wèn)題。?
下面散仙先普及下時(shí)區(qū)的知識(shí),想必大家也不陌生學(xué)過(guò)地理的同學(xué)都知道全球有24個(gè)時(shí)區(qū)每個(gè)時(shí)區(qū)的跨度是經(jīng)度15度,?
相較于兩地時(shí)間表,可以顯示世界各時(shí)區(qū)時(shí)間和地名的世界時(shí)區(qū)表(World Time),就顯得精密與復(fù)雜多了,通常世界時(shí)區(qū)表的表盤上會(huì)標(biāo)示著全球24個(gè)時(shí)區(qū)的城市名稱,但究竟這24個(gè)時(shí)區(qū)是如何產(chǎn)生的?過(guò)去世界各地原本各自訂定當(dāng)?shù)貢r(shí)間,但隨著交通和電訊的發(fā)達(dá),各地交流日益頻繁,不同的地方時(shí)間,造成許多困擾,于是在西元1884年的國(guó)際會(huì)議上制定了全球性的標(biāo)準(zhǔn)時(shí),明定以英國(guó)倫敦格林威治這個(gè)地方為零度經(jīng)線的起點(diǎn)(亦稱為本初子午線),并以地球由西向東每24小時(shí)自轉(zhuǎn)一周360°,訂定每隔經(jīng)度15°,時(shí)差1小時(shí)。而每15°的經(jīng)線則稱為該時(shí)區(qū)的中央經(jīng)線,將全球劃分為24個(gè)時(shí)區(qū),其中包含23個(gè)整時(shí)區(qū)及180°經(jīng)線左右兩側(cè)的2個(gè)半時(shí)區(qū)?
就全球的時(shí)間來(lái)看,東經(jīng)的時(shí)間比西經(jīng)要早,也就是如果格林威治時(shí)間是中午12時(shí),則中央經(jīng)線15°E的時(shí)區(qū)為下午1時(shí),中央經(jīng)線30°E時(shí)區(qū)的時(shí)間為下午2時(shí);反之,中央經(jīng)線15°W的時(shí)區(qū)時(shí)間為上午11時(shí),中央經(jīng)線30°W時(shí)區(qū)的時(shí)間為上午10時(shí)。以臺(tái)灣為例,臺(tái)灣位于東經(jīng)121°,換算后與格林威治就有8小時(shí)的時(shí)差。如果兩人同時(shí)從格林威治的0°各往東、西方前進(jìn),當(dāng)他們?cè)诮?jīng)線180°時(shí),就會(huì)相差24小時(shí),所以經(jīng)線180°被定為國(guó)際換日線,由西向東通過(guò)此線時(shí)日期要減去一日,反之,若由東向西則要增加一日。?
幾個(gè)時(shí)間名詞:?
GMT:格林威治標(biāo)準(zhǔn)時(shí)間?
UTC:世界協(xié)調(diào)時(shí)間?
DST:夏日節(jié)約時(shí)間?
CST:中國(guó)標(biāo)準(zhǔn)時(shí)間?
其中GMT時(shí)間可以近似認(rèn)為和UTC時(shí)間是相等的,但從精度上來(lái)說(shuō)UTC時(shí)間更精確。其誤差值必須保持在0.9秒以內(nèi)?
CST= GMT + 8 =UTC + 8?
此外在使用Java Client聚合查詢?nèi)掌诘臅r(shí)候,需要注意時(shí)區(qū)問(wèn)題,因?yàn)槟J(rèn)的es是按照UTC標(biāo)準(zhǔn)時(shí)區(qū)算的,所以不設(shè)置的聚合統(tǒng)計(jì)結(jié)果是不正確的。?
官網(wǎng)文檔:?
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-datehistogram-aggregation.html ?
下面散仙先普及下時(shí)區(qū)的知識(shí),想必大家也不陌生學(xué)過(guò)地理的同學(xué)都知道全球有24個(gè)時(shí)區(qū)每個(gè)時(shí)區(qū)的跨度是經(jīng)度15度,?
相較于兩地時(shí)間表,可以顯示世界各時(shí)區(qū)時(shí)間和地名的世界時(shí)區(qū)表(World Time),就顯得精密與復(fù)雜多了,通常世界時(shí)區(qū)表的表盤上會(huì)標(biāo)示著全球24個(gè)時(shí)區(qū)的城市名稱,但究竟這24個(gè)時(shí)區(qū)是如何產(chǎn)生的?過(guò)去世界各地原本各自訂定當(dāng)?shù)貢r(shí)間,但隨著交通和電訊的發(fā)達(dá),各地交流日益頻繁,不同的地方時(shí)間,造成許多困擾,于是在西元1884年的國(guó)際會(huì)議上制定了全球性的標(biāo)準(zhǔn)時(shí),明定以英國(guó)倫敦格林威治這個(gè)地方為零度經(jīng)線的起點(diǎn)(亦稱為本初子午線),并以地球由西向東每24小時(shí)自轉(zhuǎn)一周360°,訂定每隔經(jīng)度15°,時(shí)差1小時(shí)。而每15°的經(jīng)線則稱為該時(shí)區(qū)的中央經(jīng)線,將全球劃分為24個(gè)時(shí)區(qū),其中包含23個(gè)整時(shí)區(qū)及180°經(jīng)線左右兩側(cè)的2個(gè)半時(shí)區(qū)?
就全球的時(shí)間來(lái)看,東經(jīng)的時(shí)間比西經(jīng)要早,也就是如果格林威治時(shí)間是中午12時(shí),則中央經(jīng)線15°E的時(shí)區(qū)為下午1時(shí),中央經(jīng)線30°E時(shí)區(qū)的時(shí)間為下午2時(shí);反之,中央經(jīng)線15°W的時(shí)區(qū)時(shí)間為上午11時(shí),中央經(jīng)線30°W時(shí)區(qū)的時(shí)間為上午10時(shí)。以臺(tái)灣為例,臺(tái)灣位于東經(jīng)121°,換算后與格林威治就有8小時(shí)的時(shí)差。如果兩人同時(shí)從格林威治的0°各往東、西方前進(jìn),當(dāng)他們?cè)诮?jīng)線180°時(shí),就會(huì)相差24小時(shí),所以經(jīng)線180°被定為國(guó)際換日線,由西向東通過(guò)此線時(shí)日期要減去一日,反之,若由東向西則要增加一日。?
幾個(gè)時(shí)間名詞:?
CST= GMT + 8 =UTC + 8?
從上面可以看出來(lái)中國(guó)的時(shí)間是等于UTC時(shí)間+8小時(shí),es默認(rèn)存儲(chǔ)時(shí)間的格式是UTC時(shí)間,如果我們查詢es然后獲取時(shí)間日期默認(rèn)的數(shù)據(jù),會(huì)發(fā)現(xiàn)跟當(dāng)前的時(shí)間差8個(gè)小時(shí),這其實(shí)是正常的,因?yàn)閑s默認(rèn)存儲(chǔ)是用的UTC時(shí)間,所以我們需要做的就是讀取long型時(shí)間戳,然后重新格式化成下面的時(shí)間戳,即可獲得正確的時(shí)間 :
yyyy-MM-dd HH:mm:ss 像差8個(gè)時(shí)區(qū)的事情,最容易見(jiàn)到的就是,我們使用logstash收集的日志,發(fā)送到es里面,然后通過(guò)head查詢就能發(fā)現(xiàn)不一致,但是如果我們用kibana查詢,就不會(huì)發(fā)現(xiàn)時(shí)區(qū)問(wèn)題,為什么? 因?yàn)閗ibana已經(jīng)處理時(shí)區(qū)問(wèn)題了,所以在kibana的頁(yè)面顯示的時(shí)間是正確的。?此外在使用Java Client聚合查詢?nèi)掌诘臅r(shí)候,需要注意時(shí)區(qū)問(wèn)題,因?yàn)槟J(rèn)的es是按照UTC標(biāo)準(zhǔn)時(shí)區(qū)算的,所以不設(shè)置的聚合統(tǒng)計(jì)結(jié)果是不正確的。?
在es的DateHistogramBuilder里面有幾個(gè)比較重要的參數(shù):
field:指定按那個(gè)字段聚合 interval:聚合的時(shí)間單位(年,季度,月,周,天,小時(shí),分鐘,秒) format:日期格式 time_zone:時(shí)區(qū)指定 offset:時(shí)間偏移量注意,默認(rèn)不設(shè)置時(shí)區(qū)參數(shù),es是安裝UTC的時(shí)間進(jìn)行查詢的,所以分組的結(jié)果可能與預(yù)期不一樣,所以我們要指定時(shí)區(qū)為Asia/Shanghai代表北京的時(shí)區(qū),這樣才能獲取正確的聚合結(jié)果?
curl方式如下:?
Java代碼如下:?
SearchRequestBuilder search = client.prepareSearch("search2017-02*").setTypes("log"); DateHistogramBuilder dateagg = AggregationBuilders.dateHistogram("dateagg"); dateagg.field("ctime");//聚合時(shí)間字段 dateagg.interval(DateHistogramInterval.DAY);//按天聚合第一天的0點(diǎn)到第二天的0點(diǎn) dateagg.timeZone("Asia/Shanghai");//指定時(shí)區(qū) dateagg.offset("+8h");//默認(rèn)都是從0點(diǎn)開(kāi)始計(jì)算一天的,通過(guò)這個(gè)offset,我們可以把第一天的6點(diǎn)到第二天的6點(diǎn)當(dāng)做一天來(lái)聚合 search.addAggregation(dateagg); Histogram hs= search.get().getAggregations().get("dateagg"); List<Histogram.Bucket> buckets = (List<Histogram.Bucket>) hs.getBuckets();//獲取結(jié)果 for(Histogram.Bucket bk:buckets){ //下面的轉(zhuǎn)化,也是因?yàn)槟J(rèn)是UTC的時(shí)間,所以我們要獲取時(shí)間戳,自己轉(zhuǎn)化 System.out.println(new DateTime(Long.parseLong(bk.getKeyAsString()+"")).toString("yyyy-MM-dd HH:mm:ss") +" "+bk.getDocCount()); } client.close(); 上面的這個(gè)例子,基本涵蓋了日期聚合核心功能,其中時(shí)區(qū)和偏移量時(shí)兩個(gè)非常有用的而且需要特別注意的參數(shù),不設(shè)置時(shí)區(qū)直接統(tǒng)計(jì)結(jié)果肯定是不準(zhǔn)確的,offset偏移量這個(gè)參數(shù),在某些時(shí)刻也是有用的,它可以自己定義一天的開(kāi)始,比如設(shè)置從第一天的3點(diǎn)到第二天的3點(diǎn)為一天,默認(rèn)都是從0點(diǎn)開(kāi)始0點(diǎn)結(jié)束算做一天的,最后一點(diǎn)需要注意的是在輸出打印時(shí)間的時(shí)候也要考慮轉(zhuǎn)化因?yàn)槟J(rèn)也是UTC的時(shí)間,所以我們直接取出時(shí)間戳,自己格式化時(shí)間即可。?官網(wǎng)文檔:?
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-datehistogram-aggregation.html ?
總結(jié)
以上是生活随笔為你收集整理的ElasticSearch里面关于日期的存储方式,解决差8个小时的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【算法】五分钟快速了解代码复杂度
- 下一篇: 【机器学习】全面归纳距离和相似度方法(7