dateコマンドで日付を計算する

dateコマンドで日付を計算する

ログのファイル名に日付を入れたい、3日前の日付が知りたい、今月の月末を求めたい。

そのたびにdateコマンドの書式をブラウザで調べ直していました

毎回おなじ検索をしているのが馬鹿らしくなったので、使う頻度の高い順に並べ直したのがこの記事です。

検証環境はUbuntu 22.04・GNU coreutils 8.32で、載せている出力はすべて手元で実行した結果をそのまま貼っています。

macOS標準のdateはBSD版でオプションが違うため、以下はGNU版の話として読んでください。

書式指定はプラス記号から始める

dateは引数なしで実行すると、人間向けの長い表記を返します。

プラス記号で始まる引数は、書式指定として扱われる決まりです。

$ date "+%Y-%m-%d"
2026-08-03

$ date "+%Y/%m/%d %H:%M:%S"
2026/08/03 09:57:35

$ date "+%Y%m%d_%H%M%S"
20260803_095748

ファイル名に使うなら、区切りはアンダースコアが無難。

コロンはWindowsのファイル名に使えないので、時刻をそのまま入れると共有したときに困ります。

決まった形が欲しいだけなら、大文字のIオプションのほうが短くて楽。

$ date -I
2026-08-03

$ date -Iseconds
2026-08-03T09:57:48+09:00

相対日付はdオプションに英語で渡す

小文字のdオプションは、3日前や来週の金曜といった指定を受け取ります。

$ date -d "3 days ago" "+%Y-%m-%d"
2026-07-31

$ date -d "+1 month" "+%Y-%m-%d"
2026-09-03

$ date -d "next friday" "+%Y-%m-%d (%a)"
2026-08-07 (Fri)

$ date -d "2026-08-03 +45 days" "+%Y-%m-%d"
2026-09-17

便利なのは、基準日を先に書いてそこから足し引きできるところ。

今日を基準にしない計算も、これだけで一行に収まります

なお、綴りを間違えると素直に落ちてくれる仕様です。

$ date -d "1 munth" "+%Y-%m-%d"
date: invalid date ‘1 munth’

スクリプトの中で使うときは、この終了ステータスを握りつぶさないようにしておくのが安全です。

月末だけは素直に足し算できない

ここが今回いちばん書きたかったところ。

$ date -d "2026-01-31 +1 month" "+%Y-%m-%d"
2026-03-03

2月28日でも2月末でもなく、3月3日が返ってきます。

1月31日の1か月後はいったん「2月31日」と解釈され、それが3月3日へ繰り上がるためです。

引き算でも同じことが起こります。

$ date -d "2026-03-31 -1 month" "+%Y-%m-%d"
2026-03-03

3月31日の1か月前を聞いたのに、返ってきたのは同じ月の3日。

なので月末は、翌月1日の前日として求めます。

$ date -d "$(date +%Y-%m-01) +1 month -1 day" "+%Y-%m-%d"
2026-08-31

月初は日数のブレが無いので、いったん1日に寄せてから動かすのが定石です。

差分を出すときはエポック秒に直す

パーセントsで、1970年1月1日からの経過秒数が取れます。

$ date +%s
1785718655

$ date -d "2026-08-03 09:00:00" +%s
1785715200

$ date -d @1754179200 "+%Y-%m-%d %H:%M:%S"
2025-08-03 09:00:00

アットマークを付けると、その数値をエポック秒として解釈してくれます。

2つの日付が何日離れているかは、いったん秒に直して引くのがいちばん確実。

$ a=$(date -d "2026-08-03" +%s)
$ b=$(date -d "2026-12-31" +%s)
$ echo $(( (b-a)/86400 ))
150

カレンダーを数えなくても、うるう年をまたぐ日数が一発で出ます

端数が出るとすれば夏時間のある地域をまたいだときなので、日本時間だけを扱うぶんには気にしなくて大丈夫。

タイムゾーンはTZを前に置く

コマンドの前にTZを書くと、その実行のあいだだけタイムゾーンを差し替えられます。

$ TZ=UTC date "+%Y-%m-%d %H:%M %Z"
2026-08-03 00:57 UTC

$ TZ=Asia/Tokyo date "+%Y-%m-%d %H:%M %Z"
2026-08-03 09:57 JST

$ TZ=America/New_York date "+%Y-%m-%d %H:%M %Z"
2026-08-02 20:57 EDT

サーバー全体の設定に触らずに済むのが利点です。

逆に注意したいのが、曖昧な書式を渡すと黙って米国式で解釈されること。

$ date -d "08/03/2026" "+%Y-%m-%d"
2026-08-03

8月3日なのか3月8日なのかは、書いた本人にしか分かりません。

入力する日付はハイフン区切りのYYYY-MM-DDに統一しておくと、この手の事故が起きなくなります。

最後に

覚えることは3つだけでした。

書式はプラス記号、相対日付はdオプション、差分はエポック秒。

そして月末だけは足し算せず、翌月1日から1日引く

定期実行のログに日付を埋め込む話は、こちらでも触れています。

crontabの書き方|5つのフィールドと3つの落とし穴を整理

取り出した日付を桁そろえで出力したいときは、printf の書式指定が相棒になります。

printf入門|echoとの違いと書式で出力をそろえる基本

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA