[小ネタ] シェルスクリプトで日付 ⇔ UNIXTIME 相互変換の計算がしたい(GNU date, Python)

シェルスクリプトの中で、日付の計算をしたりタイムスタンプを出力したりという需要はそこそこあります。macOS 標準でインストールされている BSD date では機能が少ないので、GNU date をいれたり Python で補うことを考えてみました。
2018.10.31

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

TL;DR

  • シェルスクリプトで日付の計算する時には、一回 UNIXTIME を挟むと便利
  • GNU date コマンドがあればそれで一発。macOS でも brew で導入可能
  • なければ、Python でごにょごにょすればいい

シェルスクリプトで日付の計算がしたい (GNU date)

いまのご時世、例えば 10/31 の 23:00 から 5時間後 のタイムスタンプを計算しようとして、いちから正規表現で文字列を切り出して繰り上がりを計算して。。。ということはもうやりたくないです(挨拶)。

いろんなやり方があると思いますが、なるべく汎用的で手軽に、シェルスクリプトから使える方法で。。。と考えて、最初に思いついたのが GNU date を使うやり方です。-d オプションで指定すれば、望んだ時点の日付を好きなフォーマットで出力できます。

macOS に標準ではいっている date コマンドは BSD 版なのですが、brew を使って coreutils パッケージをインストールすると使えるようになります(Symlink などで置き換えなければ gdate という別コマンドになります)。

$ brew install coreutils
  :

$ gdate --version
date (GNU coreutils) 8.30
  :

実際にやってみます。まず 「10/31 の 23:00 (日本時間)」の UNIXTIME を得ます(Linux 環境などの場合は gdatedate に読み替えてください)。

gdate -d '10/31 23:00 JST' -u +%s

1540994400

次に、得られた UNIXTIME の 5時間後を計算します。

unixtime1=$(gdate -d '10/31 23:00 JST' +%s)
echo $(( $unixtime1 + 5 * 60 * 60)) # 5x60x60(秒)を加算

1541012400

これを人間が読める書式で出力します。

unixtime1=$(gdate -d '10/31 23:00 JST' +%s)
unixtime2=$(( $unixtime1 + 5 * 60 * 60))
gdate -d "@$unixtime2" "+%Y/%m/%d %T" # UNIXTIME 形式の場合は、-d で指定する際に「@」を付ける

2018/11/01 04:00:00

シェルスクリプトで日付の計算がしたい (Python)

gdate で目的は果たせるのですが、ただこれを社内展開するときに、このためにだけ「macOS のひとは、brew と coreutils インストールしてください」とは言いたくありませんでした。

代替になるもの、と考えて、思いついたのは Python を使うやり方です。

Pyhton なら macOS でも標準で導入されてますし、他の用途でも使うことが多いので大抵あるかと思いました。正直 「全部 Python で書けよ」 と自分にツッコミ入れざるを得ないのですが、せっかくなのであくまで シェルスクリプトで使う ことに拘って書いてみました。

まず日付の文字列から UNIXTIME を得ます。dateutil.parser モジュールを使ってパースしました。

str='10/31 23:00 JST'
cmd='
import dateutil.parser
print(
    dateutil.parser.parse("'"${str}"'").strftime("%s")
)'
python -c "$cmd"

1540994400

これに 5時間たすところは同じなので省略するとして、UNIXTIME から datetime オブジェクトを生成し、人間が読める書式で出力します。

unixtime1=$(python -c "$cmd")
unixtime2=$(( $unixtime1 + 5 * 60 * 60))

cmd='
import datetime
print(
    datetime.datetime.fromtimestamp('${unixtime}').strftime("%Y/%m/%d %T")
)'
python -c "$cmd"

2018/11/01 04:00:00

同じことができました!

Python 2.7.13 ならびに 3.6.5 の環境で動くことを確認しました。日付計算なんて基本的なことですし、もしかしたらもっとうまいやり方があるかも知れませんが、よければ参考にしてください。

参考