Linuxコマンド - date

提供:MochiuWiki : SUSE, EC, PCB
ナビゲーションに移動 検索に移動

概要


昨日の日付を取得する

拡張された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"等とすることにより、任意のシリアル値を変換できる。