dateコマンドで『年月』を取得するときに気をつけたいこと。

以下は「YYYY-mm-dd」形式で与えられた引数から、その日付が所属する月を表示するスクリプト

#!/usr/bin/env bash
ARG=$1

YM=$(date "+%Y-%m" -d "${ARG}")
echo ${YM}

exit 0

ファイル名を「get-ym.sh」として、下記のように使う。

$ sh get-ym.sh '2018-07-31'
2018-07

これは特に問題ではない。このスクリプトに2行足して、先月の年月を取得するように改変する。

#!/usr/bin/env bash
ARG=$1

YM=$(date "+%Y-%m" -d "${ARG}")
echo ${YM}

LAST_YM=$(date "+%Y-%m" -d "${ARG} 1 month ago")
echo ${LAST_YM}

exit 0

実行してみると、なぜか先ほどの結果と同じ「2018-07」になってしまう。

$ sh get-ym.sh '2018-07-31'
2018-07
2018-07

期待する結果としては2018-06だ。dateコマンドは正確に1ヶ月前を取得するわけではなく、30日前を取得するようだ。

正しい結果を得るためには一工夫して、まずは月初を求めてから年月を求めるのが良い。

#!/usr/bin/env bash
ARG=$1

YM=$(date "+%Y-%m" -d "${ARG}")
echo ${YM}

## ${ARG}を使って月初を取り、その結果から先月を取得する
LAST_YM=$(date "+%Y-%m" -d "$(date "+%Y-%m-1" -d "${ARG}") 1 month ago")
echo ${LAST_YM}

exit 0

実行してみると、期待した「2018-06」となる。

$ sh get-ym.sh '2018-07-31'
2018-07
2018-06