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

Bash

はじめに

つい先日、今年の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

ひとこと

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

Bash