Bashシェルスクリプトで2つの日付の間の日数を求める方法

2023-05-08Bash

はじめに

つい先日、今年の 1 月 1 日から今日まででどのぐらいの日数が経過した日を算出したいと思いました。

例えば 1 月 1 日から 1 月 10 日までの間の日数は 9 日 になります。

シェルスクリプトで 2 つの日付の間の日数を算出する方法を紹介したいと思います。

ちなみに間の全日付を一覧表示したい場合の方法については、過去のエントリをご参考ください。

検証環境

$ uname -moi
x86_64 x86_64 GNU/Linux

$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)

シェルスクリプトで日付から UnixTime(Unix 時間)を取得する

2 つの日付の間の時間を算出するには UnixTime を利用します。

すなわち協定世界時 (UTC) での 1970 年 1 月 1 日午前 0 時 0 分 0 秒から形式的な経過秒数(すなわち、実質的な経過秒数から、その間に挿入された閏秒を引き、削除された閏秒を加えたもの)として表される。

GMT と UTC の違いがよくわかっていないですが、とりあえず「地球上の任意の場所における 1970 年 1 月 1 日午前 0 時 0 分 0 秒からの秒数」です。

開始日、終了日を受け取り、その間の秒数を算出する

UnixTime を使って、任意の開始日、終了日の秒数を求めてみます。

# 年月日の文字列を用意
BEGIN="2021-01-01"
END="2021-01-02"

# UnitTimeを算出する
BEGIN_UT="$(date -d ${BEGIN} +%s)"
END_UT="$(date -d ${END} +%s)"

# 間の秒数を出力
echo "$((END_UT - BEGIN_UT))"

実行結果は以下のようになります。

86400

1 月 1 日から 1 月 2 日までの間の日数は 1 日 です。
1 日を時間に直すと 24 時間 。 24 時間を分に直すと 1440 分 。 これは秒数でいうと 86400 秒 になります。

算出結果と一致しますね。

開始日、終了日を受け取り、その間の日数を算出する

先程のスクリプトを活用できます。

秒数は算出できてるので、 それを と変換するだけです。

BEGIN="2021-01-01"
END="2021-01-02"

BEGIN_UT="$(date -d ${BEGIN} +%s)"
END_UT="$(date -d ${END} +%s)"

# 間の時間を出力
echo "$(((END_UT - BEGIN_UT) / (60 * 60 * 24)))"

実行結果は以下のようになります。

1

1 月 1 日から今日までの日数を算出する

BEGIN="2021-01-01"
END="$(date +%Y-%m-%d)"

BEGIN_UT="$(date -d ${BEGIN} +%s)"
END_UT="$(date -d ${END} +%s)"

# 間の時間を出力
echo "$(((END_UT - BEGIN_UT) / (60 * 60 * 24)))"

実行結果は以下のようになります。

59

スクリプト化

汎用化して、スクリプト化すると以下のようにできます。

スクリプト名 - date_diff.sh

#!/usr/bin/env bash

BEGIN="${1}"
END="${2}"

BEGIN_UT="$(date -d ${BEGIN} +%s)"
END_UT="$(date -d ${END} +%s)"

# 間の時間を出力
echo "$(((END_UT - BEGIN_UT) / (60 * 60 * 24)))"

実行系

$ ./date_diff.sh "2021-01-01" "2021-03-01"
59

ひとこと

ダブルクオーテーション、カッコが多く複雑に見えますが、実際は単純なことをしています。

2023-05-08Bash