Linuxコマンド - date
概要
昨日の日付を取得する
拡張されたdateコマンドGNU dateが使用可能な場合
Linuxでは、拡張されたGNU dateコマンドが使用できるので、過去の日付を簡単に取得できる。
-d '<N> days ago'オプションで、N日前の日付を取得できる。
date -d '1 days ago'
date 2007年 6月 2日 土曜日 23:05:20 JST # そのまま実行すると現在の日時が表示される date -d '1 days ago' 2007年 6月 1日 金曜日 23:05:31 JST # 1日前を指定すると、現在日時から24時間前の日時が表示される
GNU dateが使用できない場合
一時的に環境変数TZを変更した上で、dateコマンドを実行する。
古いUNIX系OSでは、GNU dateが使用できない場合が多いため、一時的にタイムゾーンを変更してdateコマンドを実行することで、
過去の日付を取得することができる。
TZ=JST+15 date
echo $TZ JST-9 # デフォルトのタイムゾーン date Sun Feb 7 00:10:15 2021 # dateコマンドをそのまま実行すると現在の日付となる
TZ=JST+15 date Sat Feb 6 00:10:15 2021 # 環境変数TZを変更して、dateコマンドを実行すると昨日の日付となる
echo $TZ JST-9 # 実行後もタイムゾーンは標準のままである
一時的に変数を設定
コマンド実行時に、TZ=JST+15 date +%m/%d/%Yのように同一行で変数の設定を行うことにより、
そのコマンドに対してのみ、有効になるよう変数を設定することができる。
この場合、;(セミコロン)で区切ってはいけない。
- (セミコロン)で区切る場合は、( TZ=JST+15; date +%m/%d/%Y )のように()で囲む必要がある。
明日の日付を取得する
拡張されたdateコマンドGNU dateが使用可能な場合
Linuxでは、拡張されたGNU dateコマンドが使用できるため、昨日の日付と同様に、未来の日付を簡単に取得できる。
-d 'N days' オプションで N 日後の日付を取得できる。
date -d '1 days'
GNU dateが使用できない場合
GNU dateコマンドが使用できない場合も、昨日の日付取得と同様に、環境変数TZを一時的に変更することにより取得できる。
一時的に環境変数TZを変更した上で、dateコマンドを実行する。
TZ=JST-33 date
先月の月を取得する
このセクションでは、GNU dateコマンドが使用可能な環境を前提とする。
先月の月は、dateコマンドの-dオプションに'1 months ago'を指定して、現在より1ヶ月前の日付を求めることで取得できる。
date '+%m' 02 # 現在の月は2月 date -d '1 months ago' '+%m' 01 # 先月の月は1月
しかし、この方法には大きな落とし穴がある。
上記の実行結果の通り、前月の月が取得できているように見えるが、例えば、2021年3月31日にこのコマンドを実行した場合、
3月の前の月なので2月を期待するが、実行結果は3月(03)となる。
date -d '2021-03-31 1 months ago' '+%m' 03 # 2021年3月31日に実行したことにするため、-dオプションにその日付を指定して、さらにその1ヶ月前の日付を取得する
表示形式を変更して実行すると、2021年3月31日の'1 months ago'は2021年2月31日となるが、2月31日は存在しないため、
2021年2月28日にあふれた3日分を加算した日付が、コマンドの実行結果となる。
date -d '2021-03-31 1 months ago' '+%F' 2021-03-03
正確に先月の月を取得するには、当月の1日から1ヶ月前の日付を求めればよい。
当月の1日を明示的に指定した上で、さらに、'1 months ago'を指定する。
date -d "`date '+%Y-%m-01'` 1 months ago" '+%m' 05 # 当日の日付から先月の月を取得 date -d "2021-03-01 1 months ago" '+%m' 02 # 2021年3月31日に実行した場合と同等のコマンドを実行しても、正常に前の月が取得できているのが確認できる
また、先月の月を求めるだけの場合、単純に今月の月から-1減算すればよい。
date '+%-m' 2 # 現在は2月 last_month=$(expr $(date '+%-m') - 1); [ $last_month -eq 0 ] && last_month=12 echo $last_month 1
日付のフォーマットを指定する
+を先頭に付け、日時の各情報を表す記号でフォーマットを指定する。
date '+フォーマット'
フォーマットの指定には、年、月、日、時、分を表す特殊な書式を使用する。
取得する情報 | 書式 |
---|---|
1970/01/01 00:00:00 からの経過秒 | %s |
年(西暦4桁) | %Y |
年(西暦下2桁) | %y |
月(01~12) | %m |
月(Jan~Dec) | %b |
月(January~December) | %B |
日(01~31) | %d |
日( 1~31) ※空白含む2桁 |
%e |
曜日(Sun~Sat) | %a |
曜日(Sunday~Saturday) | %A |
曜日(0~6) ※0は日曜日 |
%w |
時(00~23) | %H |
時(01~12) | %I |
時( 0~23) ※空白を含む2桁 |
%k |
時( 1~12) ※空白を含む2桁 |
%l |
分(00~59) | %M |
秒(00~59) | %S |
AM/PM | %p |
am/pm | %P |
改行 | %n |
フォーマットを指定して日時を表示するには、下表に示すように、パラメータを指定してdateコマンドを実行する。
フォーマット | コマンド |
---|---|
yyyy/mm/dd | date '+%Y/%m/%d' |
yyyy/mm/dd (Sun..Sat) | date '+%Y/%m/%d(%a)' |
yy/mm/dd | date '+%y/%m/%d' |
yyyy-mm-dd | date '+%F' |
mm/dd/yy | date '+%D' |
hh:mm (24時間制) | date '+%R' |
hh:mm:ss (24時間制) | date '+%T' |
hh:mm:ss AM/PM (12時間制) | date '+%r' |
以下に、dateコマンドの実行例を示す。
なお、実行した日時は2020年9月11日午前1時18分頃である。
date '+%Y/%m/%d' 2020/09/11 date '+%Y/%m/%d(%a)' 2020/09/11(Sun) date '+%y/%m/%d' 20/09/11 date '+%F' 2020-09-11 date '+%D' 20/11/05 date '+%R' 01:18 date '+%T' 01:18:01 date '+%r' 01:18:06 AM date '+%Y/%m/%d%n%r' 2020/09/11 01:18:27 AM # %nを使用することで、出力に改行を含めることができる
日付取得の応用
このセクションでは、GNU dateコマンドが使用可能であることを前提とする。
過去・未来の日付を求める
現在日時から指定した時間分の過去・未来の日時を求める。
現在日時から10秒前の日時を求める。
date -d '10 seconds ago'
現在日時から10秒後の日時を求める。
date -d '10 seconds'
現在日時から10分前の日時を求める。
date -d '10 minutes ago'
現在日時から10分後の日時を求める。
date -d '10 minutes'
現在日時から10時間前の日時を求める。
date -d '10 hours ago'
現在日時から10時間後の日時を求める。
date -d '10 hours'
現在日時から10日前の日時を求める。
date -d '10 days ago'
現在日時から10日後の日時を求める。
date -d '10 days'
現在日時から10ヶ月前の日時を求める。
date -d '10 months ago'
現在日時から10ヶ月後の日時を求める。
date -d '10 months'
現在日時から10年前の日時を求める。
date -d '10 years ago'
現在日時から10年後の日時を求める。
date -d '10 years'
上記のコマンドはそれぞれフォーマットを指定して実行することも可能である。
date -d '12 hours ago' '+%Y-%m-%d [%H:%M:%S]'
dateコマンドで表示される日時を現在日時ではなく、以下のように、指定した日時でdateコマンドを実行することも可能である。
# 現在日時を、2021/01/01 12:13:14としてコマンドを実行する date -d '2021/01/01 12:13:14' # フォーマットの指定も可能 # dateコマンドに日時を指定すると、現在日時ではなく指定した日時で結果が表示される。 date -d '2021/01/01 12:13:14' '+%Y %m %d - %H %M %S'
特定の日時から指定した時間分の過去・未来の日時を求めることも可能である。
date -d '2021/01/01 12:13:14 1 months ago' # フォーマットの指定も可能 date -d '2021/01/01 12:13:14 1 months ago' '+%Y %m %d - %H %M %S'
日付の比較を行う
ログファイル等から取得した日付において、タイムスタンプを比較する場合は、以下のように記述する。
#!/usr/bin/env sh
# 1970-01-01 00:00:00からの経過秒に変換する
DATE_1=`date -d "$1" '+%s'`
DATE_2=`date -d "$2" '+%s'`
# 2つの日付を表示しておく
echo "DATE 1: $1"
echo "DATE 2: $2"
# 2つの日付を比較し、結果を表示する
if [ $DATE_1 -eq $DATE_2 ]; then
echo "指定された2つの日付は同一日時です。"
elif [ $DATE_1 -gt $DATE_2 ]; then
echo "DATE 1 の方が新しい日付です。"
elif [ $DATE_1 -lt $DATE_2 ]; then
echo "DATE 2 の方が新しい日付です。"
fi
exit 0
上記の実行結果は、以下の通りである。
./xxx.sh "2021/01/01 00:00:00" "2021/01/01 00:00:00" # 出力 DATE 1: 2021/01/01 00:00:00 DATE 2: 2021/01/01 00:00:00 指定された2つの日付は同一日時です。
./xxx.sh "2021/01/01 00:00:01" "2021/01/01 00:00:00" # 出力 DATE 1: 2021/01/01 00:00:01 DATE 2: 2021/01/01 00:00:00 DATE 1 の方が新しい日付です。
./xxx.sh "2021/01/01 00:00:00" "2021/01/01 00:00:01" # 出力 DATE 1: 2021/01/01 00:00:00 DATE 2: 2021/01/01 00:00:01 DATE 2 の方が新しい日付です。
日付は、date
コマンドのフォーマット'+%s'
を使用することにより、1970-01-01 00:00:00からの経過を秒に変換する。
これにより、日付の比較を単純な数値の比較とすることができる。
つまり、秒に変換することで、新しい日付の方が大きい数値ということになる。
また、フォーマット'+%s'
を使用したdate
コマンドの実行結果は、以下の通りである。
date -d '2021/01/01 00:00:00' '+%s' 1609426800 date -d '2021/01/01 00:00:01' '+%s' 1609426801
UTCシリアル値を一般的な日付フォーマットに変換する
UTC時刻のシリアル値は、dateコマンドのフォーマットに%sを指定することで求められる。
以下の例では、シリアル値から通常の日付を求めている。
#!/usr/bin/env sh
echo "$1" | grep -E '^([0-9]{10}|[0-9]{13})$' >/dev/null 2>&1 || exit 1
echo "$1" | awk '{
print utcserial2date($1)
}
function utcserial2date(serial, msec)
{
if(length(serial) == 13)
{
msec = substr(serial, 11)
serial = substr(serial, 0, 10)
return strftime("%Y-%m-%d %H:%M:%S", serial) ":" msec
}
return strftime("%Y-%m-%d %H:%M:%S", serial)
}'
exit 0
上記のシェルスクリプトにおいて、コマンドライン引数にシリアル値を指定すると、yyyy-MM-dd hh:mm:ss形式で出力される。
./utcserial2date.sh `date '+%s'` 2020-05-12 01:55:09
通常のシリアル値に、ミリ秒が付加された13桁のシリアル値にも対応する。
./utcserial2date.sh `date '+%s999'` 2020-05-12 01:55:29:999
シリアル値から変換する。
date '+%s' | awk '{print strftime("%Y-%m-%d %H:%M:%S", $1)}'
また、dateコマンドの部分をecho "1273597263"等とすることにより、任意のシリアル値を変換できる。