jq コマンドで日付を扱うときに、出力する日付のフォーマットを変更したり、タイムゾーンを UTC から JST に変更する機会があったので備忘録。jq Manual (Dates) に載っているコマンドを参考に整理したものになります。jq のバージョンは 1.6。
前回書いた集計方法の記事も併せてどうぞ。
-
jqコマンドで集計 group by, max, sum, count
jq コマンドで集計(最大、合計、数、平均、並び替え)をする方法を紹介します。jq のバージョンは 1.6。 以前書いた ...
続きを見る
目次
- strptime() で受けて、strftime() でフォーマットする
- strptime() と strftime() で使えるフォーマット文字列
- ISO 8601 形式の場合は専用の機能が使える
- macOS の jq では、ミリ秒を perse しようとするとエラーに
- UTC から JST に変換
- strptime() のフォーマット文字列 %z に注意
strptime() で受けて、strftime() でフォーマットする
基本はこの形。日付文字列を strptime()
で perse し、strftime()
で format します。
jq -n '"2022-01-08 10:09:01 +0000" | strptime("%Y-%m-%d %H:%M:%S +0000") | strftime("%F %R")'
"2022-01-08 10:09"
strptime() と strftime() で使えるフォーマット文字列
strptime()
と strftime()
で利用できるフォーマット文字列は man
コマンドで確認ができます。
man strftime
OS のドキュメントを参照するように jq Manual (Dates) に書かれています。
Low-level jq interfaces to the C-library time functions are also provided:
jq Manual (Dates)strptime
,strftime
,strflocaltime
,mktime
,gmtime
, andlocaltime
. Refer to your host operating system's documentation for the format strings used bystrptime
andstrftime
. Note: these are not necessarily stable interfaces in jq, particularly as to their localization functionality.
上記ドキュメントの後半の Note: these are not necessarily ...
のところに書かれているように、strptime()
と strftime()
は特にローカライズ機能において、必ずしも安定したインターフェースではないとのこと。
macOS では %u
と %j
がサポートされていないようです。
jq may not support some or all of this date functionality on some systems. In particular, the
jq Manual (Dates)%u
and%j
specifiers forstrptime(fmt)
are not supported on macOS.
まとめると strptime()
と strftime()
は OS によって挙動が変わりそうなので、複数 OS で実行される処理を書く時はよく検証しましょう。
ISO 8601 形式の場合は専用の機能が使える
出力が ISO 8601 の場合は todate
という専用の機能が使えるので、シンプルに書けます。
jq -n '"2022-01-08 10:09:01 +0000" | strptime("%Y-%m-%d %H:%M:%S +0000") | todate'
"2022-01-08T10:09:01Z"
入力が ISO 8601 の場合は fromdate
。
jq -n '"2022-01-08T10:09:01Z" | fromdate | strftime("%F %X")'
"2022-01-08 10:09:01"
macOS の jq では、ミリ秒を perse しようとするとエラーに
検証に使用した macOS Big Sur の strftime には、フォーマット文字列にミリ秒が無いので、ミリ秒を含む日付文字列を perse しようとするとエラーになってしまいます。
jq -n '"2022-01-08T20:49:07.336Z" | strptime("%Y-%m-%dT%H:%M:%S") | strftime("%F %R")'
jq: error (at <unknown>): date "2022-01-08T20:49:07.336Z" does not match format "%Y-%m-%dT%H:%M:%S"
ミリ秒が不要な場合は、以下のようにミリ秒だけ切り捨てることで perse のエラーを回避することができます。
jq -n '"2022-01-08T20:49:07.336Z" | split(".")[0] | strptime("%Y-%m-%dT%H:%M:%S") | strftime("%F %R")'
"2022-01-08 20:49"
UTC から JST に変換
ドキュメントによると、jq の日付関数は UTC として時間を扱うとのこと。
jq provides some basic date handling functionality, with some high-level and low-level builtins. In all cases these builtins deal exclusively with time in UTC.
jq Manual (Dates)
UTC を JST に変換するには、以下のように、一度 mktime
で日付をタイムスタンプに変換し、9 時間後のタイムスタンプを計算してから日付フォーマットに戻します。
jq -n '"2022-01-08 10:09:01" | strptime("%F %X") | mktime + (60 * 60 * 9) | strftime("%F %X")'
"2022-01-08 19:09:01"
strflocaltime()
という便利な関数もあります。作業マシンのタイムゾーンを使ってタイムスタンプをフォーマットしてくれます。こちらのほうが短く書けます。
jq -n '"2022-01-08 10:09:01" | strptime("%F %X") | mktime | strflocaltime("%F %X")'
"2022-01-08 19:09:01"
strptime() のフォーマット文字列 %z に注意
strptime()
のフォーマット文字列に %z
を使うと、perse 時に作業マシンのタイムゾーンに変換されてしまうので気をつけて使いましょう。
jq -n '"2022-01-08 10:09:01 +0000" | strptime("%F %X %z") | strftime("%F %X %z")'
"2022-01-08 19:09:01 +0900"
上記の場合は、このように %z
を使わないようにすると想定どおりの動きになります。
jq -n '"2022-01-08 10:09:01 +0000" | strptime("%F %X +0000") | mktime | strflocaltime("%F %X %z")'
"2022-01-08 19:09:01 +0900"