天天看點

日志服務資料加工最佳實踐: 日期時間處理場景1:Unix時間戳、日期時間字元串和日期時間對象的互相轉換場景2: 了解時區的概念場景3: 了解日期時間和Unix時間戳的應用場景場景4: 使用dt_add做靈活的日期偏移進一步參考

日志服務資料加工最佳實踐: 日期時間處理場景1:Unix時間戳、日期時間字元串和日期時間對象的互相轉換場景2: 了解時區的概念場景3: 了解日期時間和Unix時間戳的應用場景場景4: 使用dt_add做靈活的日期偏移進一步參考

場景1:Unix時間戳、日期時間字元串和日期時間對象的互相轉換

LOG DSL文法中的日期時間處理主要涉及三種資料類型:Unix時間戳、日期時間字元串和日期時間對象。它們的互相轉換方式如下圖:

日志服務資料加工最佳實踐: 日期時間處理場景1:Unix時間戳、日期時間字元串和日期時間對象的互相轉換場景2: 了解時區的概念場景3: 了解日期時間和Unix時間戳的應用場景場景4: 使用dt_add做靈活的日期偏移進一步參考

子場景1:日期時間對象和Unix時間戳的互相轉換

1)日期時間對象轉為Unix時間戳

  • dt_parsetimestamp

    智能轉換函數,可以将日期時間對象或日期時間字元串轉化為Unix時間戳。
  • dt_totimestamp

    ,隻支援将日期時間對象轉化為Unix時間戳。

2)Unix時間戳轉為日期時間對象

  • dt_parse

    智能轉換函數,可以将Unix時間戳或日期時間字元串轉化為日期時間對象
  • dt_fromtimestamp

    ,隻支援将Unix時間戳轉化為日期時間對象。

子場景2:日期時間對象和日期時間字元串的互相轉換

1)日期時間對象轉為日期時間字元串

  • dt_str

    智能轉換函數,可以将日期時間對象、Unix時間戳和日期時間字元串轉化為制定格式的日期時間字元串。
  • dt_strftime

    ,隻支援将日期時間對象轉化為日期時間字元串。

2)日期時間字元串轉為日期時間對象

  • dt_parse

    智能轉換函數,可以将日期時間字元串或Unix時間戳轉化為日期時間對象。
  • dt_strptime

    ,隻支援将日期時間字元串轉化為日期時間對象。

子場景3:日期時間字元串和Unix時間戳的互相轉換

1)日期時間字元串轉為Unix時間戳

  • dt_parsetimestamp

    智能轉換函數,可以将日期時間字元串或日期時間對象轉化為Unix時間戳。

2)Unix時間戳轉為日期時間字元串

  • dt_str

    智能轉換函數,可以将Unix時間戳、日期時間對象和日期時間字元串轉化為制定格式的日期時間字元串。
  • dt_strftimestamp

    ,隻支援将Unix時間戳轉化為日期時間字元串。

子場景4: 了解dt_parse等智能轉換函數的應用場景

上述的轉化過程中,大多數轉化都有兩種方式,一種使用智能轉換函數,另一種使用該轉換的專用函數。以

dt_parse

為代表的智能轉換函數(參考

日期時間函數

)可以接受Unix時間戳、日期時間對象以及日期時間字元串等不同類型的參數,實作智能轉換,例如:

原始日志1

time1: 1562741899
time2: 2019-07-10 06:58:19           

LOG DSL編排

e_set("time3", dt_parse(v("time1"), tz="Asia/Shanghai"))
e_set("time4", dt_parse(v("time2"), tz="Asia/Shanghai")           

編排後日志

time1: 1562741899
time2: 2019-07-10 06:58:19
time3: 2019-07-10 06:58:19+08:00
time4: 2019-07-10 06:58:19+08:00           

但是有一些場景下,智能轉換函數就無法滿足使用者的需求。如對于使用者自定義的特殊日期格式,

dt_parse

等智能轉換函數無法自動解析日志,此時需要使用

dt_strptime

來進行指定格式的解析。如下:

原始日志2

time1: 2019-07-10 06:58:19
time2: 2019/07/10 06-58-19           

e_set("time3", dt_parsetimestamp(v("time1")))
e_set("time4", dt_parsetimestamp(dt_strptime(v("time2"), fmt="%Y/%m/%d %H-%M-%S")))           

time1: 2019-07-10 06:58:19
time2: 2019/07/10 06-58-19
time3: 1562741899
time4: 1562741899           

結論

  • 智能轉換函數可以對不同類型的參數進行自動轉換,是以預設推薦使用智能轉換函數。
  • 智能轉換函數也有缺點,對于一些特殊的使用者自定義日期格式,智能轉換函數無法自動解析,需要使用

    dt_strptime

    來進行解析。

場景2: 了解時區的概念

子場景1: 了解時間字元串的含義

LOG DSL文法中的日期時間字元串主要分為兩種形式:

  • 帶有時區資訊的日期時間字元串,如

    2019-06-02 18:41:26+08:00

  • 不帶時區資訊的日期施時間字元串,如

    2019-06-02 10:41:26

帶有時區資訊的日期時間字元串通過在日期時間後添加額外的時差資訊來表達時區:

  • 2019-06-02 18:41:26+08:00

    表示該時間是

    東8區

    時區下的

    2019-06-02 18:41:26

  • 2019-06-02 18:41:26-07:00

    西7區

    2019-06-02 18:41:26

對于不帶有時區資訊的日期時間字元串,如果時區資訊不同,該時間字元串表達的時間也不同。如果沒有傳遞時區參數,預設為UTC時區下的時間。以

2019-06-02 18:41:26

為例:

  • 預設情況下是UTC時區下的時間,即該時間字元串表達的時間是UTC時區下的時間,等價于

    2019-06-02 18:41:26+00:00

  • 如果交代了時區是東8區,該時間字元串表達的時間是東8區下的時間,等價于

    2019-06-02 18:41:26+08:00

子場景2: 将日期時間轉化為Unix時間戳

不帶時區資訊的日期時間

對于不帶時區資訊的日期時間字元串(如'2019-06-02 18:41:26'),将給定日期時間轉化為Unix時間戳,需要指定該日期時間是哪個時區下的時間,不同的時區轉化得到的Unix時間戳的值是不一樣的。

原始日志

{ 'time': '2019-06-02 18:41:26''}           

e_set("Shanghai_timestamp", dt_parsetimestamp(v("time"), tz="Asia/Shanghai"))
e_set("Los_Angeles_timestamp", dt_parsetimestamp(v("time"), tz="America/Los_Angeles"))
e_set("UTC_timestamp", dt_parsetimestamp(v("time")))           
  • 指定tz="Asia/Shanghai"表示

    time

    字段所表達的時間是上海所在時區對應的時間。
  • 如果不指定時區,預設将給定日期時間當做UTC時區下的日期時間。
  • 時區參數

    tz=時區字元串

    中所有可選時區字元串的值參考 所有時區清單 。可使用

    Ctrl + F

    搜尋目标時區字元串。

加工後日志

{
  'Shanghai_timestamp': '1559472086',
  'Los_Angeles_timestamp': '1559526086',
  'UTC_timestamp': '1559500886'
}           

帶有時區資訊的日期時間

對于帶有時區資訊的日期時間字元串(如'2019-06-02 18:41:26+08:00'),則無須指定時區參數。

{ 'China_time': '2019-06-02 18:41:26+08:00',
  'America_time': '2019-06-02 3:41:26-07:00',
  'UTC_time': '2019-06-02 10:41:26+00:00'
}           

e_set("timestamp1", dt_parsetimestamp(v("China_time")))
e_set("timestamp2", dt_parsetimestamp(v("America_time")))
e_set("timestamp3", dt_parsetimestamp(v("UTC_time")))           

{
  "timestamp1": "1559472086",
  "timestamp2": "1559472086",
  "timestamp3": "1559472086"
}           

子場景3: 不同時區下的日期時間互相轉換

對于不帶時區資訊的日期時間字元串(如'2019-06-02 18:41:26'),可以通過Unix時間戳為媒介,實作不同時區下的日期時間的互相轉換。

加工需求

  • 将洛杉矶時區下的日期時間轉換為上海時區下的日期時間

#已知time字段的值的時間是洛杉矶時間
{'time': '2019-06-04 2:41:26'}           

e_set("timestamp", dt_parsetimestamp(v("time"), tz="America/Los_Angeles"))
e_set("Shanghai_time", dt_parse(v("timestamp"), tz="Asia/Shanghai"))           

{
  'time': '2019-06-04 2:41:26',
  'Shanghai_time': '2019-06-04 17:41:26+08:00'
}           

對于帶有時區資訊的日期時間字元串(如'2019-06-02 18:41:26+08:00''),可直接通過

dt_astimezone

實作不同時區下的日期時間的互相轉換。

{'time': '2019-06-04 2:41:26+08:00'}           

e_set("new_time", dt_astimezone(v("time"), tz="America/Los_Angeles"))           

{
  'time': '2019-06-04 2:41:26+08:00',
  'new_time': '2019-06-03 11:41:26-07:00'
}           

場景3: 了解日期時間和Unix時間戳的應用場景

LOG DSL編排中涉及到的日期時間主要有兩種形式

Unix時間戳

日期時間(字元串或對象)

日期時間

日期時間形式主要是為了便于展示以及提升使用者可讀性等。

unix_time: 1562741899
date_time: 2019-07-10 06:58:19           

Unix時間戳

Unix時間戳是從1970年1月1日(UTC/GMT的午夜)開始所經過的秒數,它的主要應用場景有:

1. 表示系統時間

  • 如日志事件中表示日志産生時間的元字段

    __time__

    ,表示日志接收時間的字段

    __receieve_time__

    等,這些字段的值都使用Unix時間戳來表示對應的系統時間。
__source__:  1.2.3.4
__tag__:__receive_time__:  1562741899
__topic__: 
__time__: 1562731122           

2. 便于時間相關的計算。

  • 由于Unix時間戳是從1970年1月1日開始所經過的秒數,是以在很多場景下便于直接進行日期時間相關的計算。
time1: 1562741899
time2: 1562731122           
e_set("time3", op_sub(v("time1"), v("time2")))           
time1: 1562741899
time2: 1562731122
time_diff: 10777           

場景4: 使用dt_add做靈活的日期偏移

dt_add

函數支援在特定時間粒度上修改(增加、減少、覆寫)日期時間的值。

dt_add

的參數如下

dt_add(字段名, dt1=None, dt2=None, year(s)=None, month(s)=None, day(s)=None, hour(s)=None, minute(s)=None, second(s)=None, microsecond(s)=None, weeks(s)=None, weekday=None)           

子場景1:了解year(s),month(s)差別

  • year(s)

    ,

    month(s)

    day(s)

    等參數的後面都帶有

    (s)

    ,表示這些參數可以有兩種形式,即

    year

    years

    month

    months

    等。
  • year

    years

    為例,如果參數傳遞的是

    year

    ,表示在年份粒度上覆寫為year參數的值;如果傳遞的是

    years

    ,表示在年份粒度上增加years參數的值。(可參考下面的例子)

"time1": "2019-06-04 2:41:26"           

LOG DSL編排1

e_set("time2", dt_add(v("time1"), year=2018))           

"time1": "2019-06-04 2:41:26"
"time2": "2018-06-04 02:41:26"           

LOG DSL編排2

e_set("time2", dt_add(v("time1"), years=2018))           

"time1": "2019-06-04 2:41:26"
"time2": "4037-06-04 02:41:26"           

子場景2:了解weekday參數用法

  • weekday參數通常和dt_MO,dt_TU等參數一起使用,表示特定星期幾的偏移。具體可參考 dt_MO

#2019-06-04是周二

"time1": "2019-06-04 2:41:26"           

#time1的下一個星期一對應的日期
e_set("nex_Monday", dt_add(v("time1"), weekday=dt_MO(1)))

#time1的上一個星期二對應的日期
e_set("previous_Tuesday", dt_add(v("time1"), weekday=dt_TU(op_neg(1))))

#time1的下下一個星期六對應的日期
e_set("nex_next_Saturday", dt_add(v("time1"), weekday=dt_SA(2)))

#time1的上上一個星期日對應的日期
e_set("previous_previous_Sunday", dt_add(v("time1"), weekday=dt_SU(op_neg(2))))           

"time1": "2019-06-04 2:41:26",
"next_Monday": "2019-06-10 02:41:26",
"previous_Tuesday": "2019-06-04 2:41:26",
"next_next_Saturday": "2019-06-15 02:41:26",
"previous_previous_Sunday": "2019-05-26 02:41:26"           
  • 需要注意的是,如果

    time1

    對應的日期是周二,那麼它的上一個周二和下一個周二都是

    time1

    本身。

進一步參考

歡迎掃碼加入官方釘釘群獲得實時更新與阿裡雲工程師的及時直接的支援:

日志服務資料加工最佳實踐: 日期時間處理場景1:Unix時間戳、日期時間字元串和日期時間對象的互相轉換場景2: 了解時區的概念場景3: 了解日期時間和Unix時間戳的應用場景場景4: 使用dt_add做靈活的日期偏移進一步參考