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の次のような点について書いてみました
何かのお役に立てば〜