はじめに
来月1日を取得する処理で単純なようで、バグが発生したので、その際に調べたことをメモする。
誤った方法
コマンド
date '+%Y%m01' -d "1 months"
##説明
・オプション d "1 months"
システム日付の1ヵ月後を指定する。
・オプション '+フォーマット'
%Y:年(西暦4桁)、%m:月(01~12)にてYYYYMMを取得し、DD部分に01を付加する。
正しい方法
コマンド
date '+%Y%m01' -d "`date '+%Y-%m-01'` 1 months"
説明
・ 逆引用符date '+%Y-%m-01'
システム日付のYYYYMMを取得し、DD部分に01を付加する。つまり当月の1日の日付を作る。
・オプション d "date '+%Y-%m-01'
1 months"
当月の1日の1ヵ月後を指定する。
・オプション '+フォーマット'
%Y:年(西暦4桁)、%m:月(01~12)にてYYYYMMを取得し、DD部分に01を付加する。
問題になった箇所
現象
シェルの中で来月1日を取得する部分で、2015年1月29日の処理が上手く動きませんでした。
※現象を再現するために、オプションdに日付を付けた形で1ヵ月後を取っています。
$ date '+%Y%m01' -d '2015-01-27 1 months'
20150201
$ date '+%Y%m01' -d '2015-01-28 1 months'
20150201
$ date '+%Y%m01' -d '2015-01-29 1 months'
20150301
$ date '+%Y%m01' -d '2015-01-30 1 months'
20150301
$ date '+%Y%m01' -d '2015-01-31 1 months'
20150301
$ date '+%Y%m01' -d '2015-02-01 1 months'
20150301
$
説明
オプションdにて1 monthsを実施した際に、dateコマンドは2015年1月29日⇒2015年2月29日と解釈するようです。ただ、2015年の2月は28日までなので、溢れた1日分を2月28日に加算して2015年3月1日とするようです。信じられない話です。。。
検証
ということは、誤った方法だと翌月が前月より少ない日数の月で上手く行かなくなると思われます。
〔2015年1月〕
$ date '+%Y%m%d' -d '2015-01-27 1 months'
20150227
$ date '+%Y%m%d' -d '2015-01-28 1 months'
20150228
$ date '+%Y%m%d' -d '2015-01-29 1 months'
20150301 ★
$ date '+%Y%m%d' -d '2015-01-30 1 months'
20150302 ★
$ date '+%Y%m%d' -d '2015-01-31 1 months'
20150303 ★
$ date '+%Y%m%d' -d '2015-02-01 1 months'
20150301
$
〔2015年5月〕
$ date '+%Y%m%d' -d '2015-05-29 1 months'
20150629
$ date '+%Y%m%d' -d '2015-05-30 1 months'
20150630
$ date '+%Y%m%d' -d '2015-05-31 1 months'
20150701 ★
$ date '+%Y%m%d' -d '2015-06-01 1 months'
20150701
$
〔2015年8月〕
$ date '+%Y%m%d' -d '2015-08-30 1 months'
20150930
$ date '+%Y%m%d' -d '2015-08-31 1 months'
20151001 ★
$ date '+%Y%m%d' -d '2015-09-01 1 months'
20151001
$
〔2015年10月〕
$ date '+%Y%m%d' -d '2015-10-30 1 months'
20151130
$ date '+%Y%m%d' -d '2015-10-31 1 months'
20151201 ★
$ date '+%Y%m%d' -d '2015-11-01 1 months'
20151201
$
参考
$ cal 2015
2015
1月 2月 3月
日 月 火 水 木 金 土 日 月 火 水 木 金 土 日 月 火 水 木 金 土
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5 6 7
4 5 6 7 8 9 10 8 9 10 11 12 13 14 8 9 10 11 12 13 14
11 12 13 14 15 16 17 15 16 17 18 19 20 21 15 16 17 18 19 20 21
18 19 20 21 22 23 24 22 23 24 25 26 27 28 22 23 24 25 26 27 28
25 26 27 28 29 30 31 29 30 31
4月 5月 6月
日 月 火 水 木 金 土 日 月 火 水 木 金 土 日 月 火 水 木 金 土
1 2 3 4 1 2 1 2 3 4 5 6
5 6 7 8 9 10 11 3 4 5 6 7 8 9 7 8 9 10 11 12 13
12 13 14 15 16 17 18 10 11 12 13 14 15 16 14 15 16 17 18 19 20
19 20 21 22 23 24 25 17 18 19 20 21 22 23 21 22 23 24 25 26 27
26 27 28 29 30 24 25 26 27 28 29 30 28 29 30
31
7月 8月 9月
日 月 火 水 木 金 土 日 月 火 水 木 金 土 日 月 火 水 木 金 土
1 2 3 4 1 1 2 3 4 5
5 6 7 8 9 10 11 2 3 4 5 6 7 8 6 7 8 9 10 11 12
12 13 14 15 16 17 18 9 10 11 12 13 14 15 13 14 15 16 17 18 19
19 20 21 22 23 24 25 16 17 18 19 20 21 22 20 21 22 23 24 25 26
26 27 28 29 30 31 23 24 25 26 27 28 29 27 28 29 30
30 31
10月 11月 12月
日 月 火 水 木 金 土 日 月 火 水 木 金 土 日 月 火 水 木 金 土
1 2 3 1 2 3 4 5 6 7 1 2 3 4 5
4 5 6 7 8 9 10 8 9 10 11 12 13 14 6 7 8 9 10 11 12
11 12 13 14 15 16 17 15 16 17 18 19 20 21 13 14 15 16 17 18 19
18 19 20 21 22 23 24 22 23 24 25 26 27 28 20 21 22 23 24 25 26
25 26 27 28 29 30 31 29 30 27 28 29 30 31