ハマログ

株式会社イーツー・インフォの社員ブログ

GNU dateで環境変数に持つ日時文字列の操作

背景など

shellで日付の操作を行いたいと思いました
その利用例はこんな感じです
まず環境変数に日時を表す文字列を持っておきます
その環境変数の値から先月を求めたり、月末日を求めたり
なんて操作をしたいなと思いました

環境変数に日時を表す文字列を持つことを念頭に置いて
日付の操作を行う方法を考えてみたいと思います

なお念のためのお約束です
この記事のご利用は自由ですが、ご自身の責任でお願いします

確認している環境

ここではGNU の dateコマンドを扱います
試している環境やバージョンはこんな感じです

$ cat /etc/redhat-release
CentOS release 6.3 (Final)
$ date --version
date (GNU coreutils) 8.4
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by David MacKenzie.
$ sh --version
GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

GNU と BSD の dateコマンドでは次のwikipediaにもあるように
動作に多くの違いがあります

date (UNIX)
http://ja.wikipedia.org/wiki/Date_%28UNIX%29

日時を環境変数へ持たせる

まずは日時を環境変数へ持たせましょう

$ export MYSYSDT=$(date "+%F %T")
$ echo $MYSYSDT
2013-09-28 11:18:59

日時の書式を変える

これを希望の書式に変更したいと思います
環境変数の日時をYYYYMM形式にしてみましょう

$ echo $MYSYSDT
2013-09-28 11:18:59
$ export MYSYSDT_YM=$(date -d "${MYSYSDT}" "+%Y%m")
$ echo $MYSYSDT_YM
201309

dateコマンドが認識する書式を実験

さてここでdateコマンドがどのような書式の文字列を
日時として認識してくれるか実験してみましょう

まずは日付のみから

$ date -d "2091-12-11" "+%yx%mx%d %Hx%Mx%S"
91x12x11 00x00x00
$ date -d "2092/12/11" "+%yx%mx%d %Hx%Mx%S"
92x12x11 00x00x00
$ date -d "20931211" "+%yx%mx%d %Hx%Mx%S"
93x12x11 00x00x00

いずれも日時として認識してもらえました

続いて日時で実験

$ date -d "2091-12-11 22:44:55" "+%yx%mx%d %Hx%Mx%S"
91x12x11 22x44x55
$ date -d "2092/12/11 22:44:55" "+%yx%mx%d %Hx%Mx%S"
92x12x11 22x44x55
$ date -d "20931211224455" "+%yx%mx%d %Hx%Mx%S"
date: invalid date `20931211224455'

最後の区切り文字無しでの羅列は、さすがに認識して貰えませんでした

という訳で時間まで含めて環境変数に持ち、
dateコマンドで使うことを考えると
YYYY-MM-DD HH:MM:SS形式が手軽そうに思いました

YYYY-MM-DDだと %F でdateコマンドから取り出せますが
YYYY/MM/DDだと %Y/%m/%d となり煩雑だからです

前月、翌月を求める

date コマンドで前月、翌月を求めてみます

前月を求める場合は “1 month ago” のように指定します
翌月の場合は “1 month” となります

$ echo $MYSYSDT
2013-09-28 11:18:59
$ MYSYSDT_1MAGO=$(date -d "${MYSYSDT} 1 month ago" "+%F %T")
$ echo $MYSYSDT_1MAGO
2013-08-28 11:18:59
$ MYSYSDT_1M=$(date -d "${MYSYSDT} 1 month" "+%F %T")
$ echo $MYSYSDT_1M
2013-10-28 11:18:59

さてここで疑問に思いました
例えば3月31日の前月を求めるとどうなるんだろう

$ export MYSYSDT="2013-03-31 23:59:59"
$ echo $MYSYSDT
2013-03-31 23:59:59
$ MYSYSDT_1MAGO=$(date -d "${MYSYSDT} 1 month ago" "+%F %T")
$ echo $MYSYSDT_1MAGO
2013-03-03 23:59:59

エラーにはなりませんが3月3日となりました
あまり使い勝手のいい日ではないかと思います
前月、翌月などを求める場合は、一旦ついたちにしてから求めたほうが良さそうです
“2013-03-31”のうち先頭7文字を取り出し、それに”-01″を連結してついたちにします

$ echo $MYSYSDT
2013-03-31 23:59:59
$ MYSYSDT_1MAGO=$(date -d "${MYSYSDT:0:7}-01 1 month ago" "+%F %T")
$ echo $MYSYSDT_1MAGO
2013-02-01 00:00:00

日付と時刻は捨ててしまいますが、使い勝手のいい日ではないでしょうか

月末日を求める

dateコマンドには豊富なオプションがあるので
月末日を求めるオプションもないかなと探しましたが
みつけられませんでした

そこで翌月を求める方法を応用して
翌月ついたちから、1日前に戻る方法で末日を求めてみましょう

$ export MYSYSDT="2013-02-01 23:59:59"
$ echo $MYSYSDT
2013-02-01 23:59:59
$ MYSYSDT_LASTDAY=$(date -d "$(date -d "${MYSYSDT:0:7}-01 1 month" "+%F %T") 1 day ago" "+%F %T")
$ echo $MYSYSDT_LASTDAY
2013-02-28 00:00:00
$ export MYSYSDT="2012-02-01 23:59:59"
$ MYSYSDT_LASTDAY=$(date -d "$(date -d "${MYSYSDT:0:7}-01 1 month" "+%F %T") 1 day ago" "+%F %T")
$ echo $MYSYSDT_LASTDAY
2012-02-29 00:00:00

いいようですね


GNU dateの次のような点について書いてみました

  • 前月、翌月を求める
  • 日時を環境変数へ持たせる
  • 日時の書式を変える
  • dateコマンドが認識する書式を実験
  • 月末日を求める

  • 何かのお役に立てば〜

    BSDdateGNUshellUNIX日付日時

      桑原 光昭   2013年9月28日


    関連記事

    Ajaxで$.postのForm送信にserialize(シリアライズ)を使用する

    こんにちは。S.Iです。 先日、試行錯誤したAjaxでPOSTメソッドでForm…

    PHPとGmail APIでメールを取得する

    はじめに システムのエラー通知をGmailに送ったあと、PHPのプログラムでメー…

    Google Apps Scriptで、Googleドキュメントのバックアップ

    こんにちは、かねこです。 はじめに 弊社では、Googleドライブを利用して、一…


    ← 前の投稿

    次の投稿 →