小ネタ
UTC
そもそもSplunkの_time
は UNIX時間なので気楽にだせるはず。
今の時刻を確認してみる
| makeresults
| eval time=strftime(_time,"%F %T %Z")
_time | time |
---|---|
2019/12/07 09:23:48 | 2019-12-07 09:23:48 JST |
日本標準時@wikipediaになっていますね。
UTCに変更してみる
| makeresults
| eval time_suffix=strftime(_time,"%:::z")
| eval time_suffix_mod=time_suffix * -1
| eval unix_time=relative_time(_time,(time_suffix_mod."h"))
| eval unix_time=strftime(utc_time, "%F %T.%3N")
_time | time_suffix | time_suffix_mod | utc_time |
---|---|---|---|
2019/12/07 09:40:26 | +09 | -9 | 2019-12-07 00:40:26.000 |
%z
をつけるとバレてしまうので、この形。
プラスマイナス変換に-1
を掛けるのも、知ってしまえば当然だけど、最初はcase
で作ってた・・・・
追記(R2.7.24)
Splunk>Answersで、昔やったよな〜と思いつつ回答した。。
このページを見返したところ、上記クエリーは"-01"のように、アメリカあたりの時刻帯だと上手く動かないことが判明
| makeresults
| eval time=strftime(_time,"%FT%T %:::z")
| eval offset = substr(time,21,23)
| eval time_args = if( -1 * offset >= 0, "+".substr(offset,2,3), printf("%03d",-1 * offset))
| eval GMT = ceil(relative_time(_time,time_args."h"))
| convert ctime(GMT)
やっぱり、±判定が必要らしい。
printf()
で"-01"
といった文字列を作っている。%03
なのに注目。
relative_time()
はミリセコンド以下を切りすてるので、必要な場合は別途くっつける必要がある。今回はじゃまな.000000
を削除するためceil()
している。
time format
Common Time Format Variables@Splunk>Docs
覚え切らないので、基本は %F %T
か %c
props.confで変える
I want to set a different time zone from the time@Splunk Answer
ふと見てたらこんなやつを見つけた。
TZ(Time Formatだと%z
)の値を上書きするオプションがTZ_ALIAS
TZ_ALIAS= 00:00=JST
が回答。なので
TZ_ALIAS= 00:00=UTC
にしてしまえば、多分UTC
1970年より前でも欲しい
| makeresults
| eval time=-31553280
| appendpipe
[eval time=0]
| makecontinuous time span=-31553280
| eval date=strftime(time,"%F %T")
| head 1970
| rex field=date "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) (?<hour>\d{2}):(?<min>\d{2}):(?<sec>\d{2})"
| eval leap_year=if(year % 400 =0 OR (year % 4 =0 AND year % 100 !=0),"Leap", "NOTLeap")
| eval mod_day=sec + 60 * min + pow(60,2) * hour + 24 * pow(60,2) * (tonumber(day)-1)
| eval date=strftime(time-mod_day,"%F %T")
| eval mod_3month=if(leap_year=="NOTLeap",mod_day+24*pow(60,2)*59,mod_day+24*pow(60,2)*60)
| eval mod_2month=mod_day+24*pow(60,2)*31
| eval date=case(month="03",strftime(time-mod_3month,"%F %T"),month="02",strftime(time-mod_2month,"%F %T"),true(),date)
| appendpipe
[eval time=0, date=strftime(time,"%F %T")
| head 1]
| table date time
| sort 0 - time
2020年問題もあるなか、今回1970年より前の年を出してみたくなり作ってみた。
strptime
が使えないのでこんな感じ。
Microsoftの閏年判定も組み込んでいろいろ調整をして作ってみた。
JSTは一回修正して-9時間してはみたもののバグが多すぎるので、この形にした。
UNIX data represents different points in time as signed integers, traditionally of 32 bits, by encoding the UNIX timestamp. Because it uses 32 bits, UNIX time can only cover approximately 136 years in total. In other words, the maximum representable time for UNIX time is 19 January 2038 and the minimum representable time is 13 December 1901.
Date & timeTimes that occurred before 1970 (the epoch time) have a negative value. When the counter passes the maximum date, the counter will ‘run out’ and time will ‘wrap around’ and be stored as a negative number (13 December 1901). This is referred to as the UNIX millennium bug.
splunk answerでなんとかならないのかと質問したら、このコメントが帰ってきた。でも負けない。
epochの限界
| makeresults
| eval time=-62167252739
| eval _time=time
| eval time_text=strftime(_time,"%c %::z")
-62167252739
がepochの限界っぽい。
ターミナルでdate -r -62167252739
で確認したら 0000年 1月 1日 土曜日 00時00分00秒 LMT
が帰ってきた。
Splunkの時間について
| makeresults
| eval time=-62167252739
| appendpipe
[eval time=0]
| eval date=strftime(time,"%F %T")
| makecontinuous span=31536000 time
| eval date=strftime(time,"%F %T")
| rex field=date "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) (?<hour>\d{2}):(?<min>\d{2}):(?<sec>\d{2})"
| dedup year
| eval mod_date=strftime(time,"%j")
| eval time=if(day="01",time,time - (mod_date -1) * 24 * 60 * 60)
| eval date=strftime(time,"%F %T")
strftime()
は使えるから始めの時間から逆算で作ってみた。
1887-01-01 00:00:00 -2619249539
までは普通に動いていたけどそこからがおかしくなった。
1970前でもUTCが欲しいver2
| makeresults count=2
| streamstats count
| eval time=if(count=1,0,-62167252739)
| makecontinuous time span=31536000
| eval time = time - (time % (24 * 60 * 60))- (9 * 60 * 60)
| sort 100 - time
| eval date=strftime(time,"%F %T")
| rex field=date "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) (?<hour>\d{2}):(?<min>\d{2}):(?<sec>\d{2})"
| dedup year
| eval mod_date=strftime(time,"%j")
| eval time=if(day="01",time,time - (mod_date -1) * 24 * 60 * 60)
| eval date=strftime(time,"%F %T")
| sort 83 - date
| table date day hour min mod_date month sec time year
| append [| makeresults count=2
| streamstats count
| eval time=if(count=1,0,-62167252739)
| makecontinuous span=31536000 time
| eval date=strftime(time,"%F %T")
| rex field=date "(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2}) (?<hour>\d{2}):(?<min>\d{2}):(?<sec>\d{2})"
| dedup year
| eval mod_date=strftime(time,"%j")
| eval time=if(day="01",time,time - (mod_date -1) * 24 * 60 * 60)
| eval date=strftime(time,"%F %T")]
| sort date
| where sec="00"
| table date time
結論ありきで作ってみたらこんな感じ。内部的にはめちゃくちゃだと思う。
まとめ
一応動的に現在の環境の変数から導きだしているので、たまたまSplunk環境が日本時間じゃなかったとしても使えるはず。
12/9 props.confで変える を追加
12/26 1970年より前でも欲しい を追加
2/8 epochの限界、1970前でもUTCが欲しいver2 を追加
7/24/2020 追記 を追加