JavaScriptのsetMonthについて
JavaScriptで日付(主に月)の加算・減算をしたい人必見!!!
やり方をググると、色々なページで解説がありますね。
そして、殆どがsetMonthを使ってますね!
https://msdn.microsoft.com/ja-jp/library/tst8h9zw(v=vs.94).aspx
setMonth メソッド (Date) (JavaScript)
Date オブジェクトの日付の月の部分を現地時刻で設定します。構文
dateObj. setMonth(numMonth[, dateVal])
パラメーター
dateObj必須。任意の Date オブジェクトを指定します。numMonth必須。設定する月を表す数値を指定します。1 月の値は 0 で、2 月以降の値はそれに続く連続した数字です。dateVal省略可能です。設定する月の日付と等しい数値を指定します。この値を省略した場合は、getDate メソッドにより返される値が使用されます。
解説
世界協定時刻 (UTC) を使用して月の値を設定するには、setUTCMonth メソッドを使用します。
numMonth に 11 を超える値 (1 月は 0) または負数を指定すると、値に応じて格納されている年の値が変更されます。たとえば、日付が "Jan 5, 1996" と格納されている場合に setMonth(14) メソッドを呼び出すと、日付は "Mar 5, 1997" に変更されます。
setFullYear メソッドを使用すると、年、月、および日を設定できます。
上記の説明を見ると行けそうな気がします。
しかし、、、コレちょっと危険なんです!!
1月末日に+1ヵ月して2月末日を出そうとした場合、期待通りにいかないはずです!
var date = new Date('2015/1/31'); date.setMonth(date.getMonth()+1);
こう書いて正解っぽく見えますが、、、、
結果は【2015/3/3】になってしまいます。
おそらくですが、
2月31日(あり得ない) - 2月28日(現実) = 3日
2月28日(現実) + 3日(あまった日数) = 2015/3/3(結果)
このような計算が行われていると思われます。
今回は加算でしたが、減算でも起こり得ます(検証済み)。
じゃあ何故このようなことになってしまったのか。。。
ヒントはwikiにありました。
JavaScriptという言葉は狭義にはMozillaが仕様を策定し実装しているスクリプト言語を指す。このスクリプト言語はEcmaインターナショナルでECMAScript (ECMA-262) として標準化されており、多くのWebブラウザー等はこの標準化されたECMAScriptを実装している。
https://ja.wikipedia.org/wiki/JavaScript
上記の文にあるECMAScriptのリファレンスを読んでみると。。。。。
15.9.5.38 Date.prototype.setMonth (month [, date ] )
If date is not specified, this behaves as if date were specified with the value getDate().
Let t be the result of LocalTime(this time value).
Let m be ToNumber(month).
If date is not specified, then let dt be DateFromTime(t); otherwise, let dt be ToNumber(date).
Let newDate be MakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t)).
Let u be TimeClip(UTC(newDate)).
Set the PrimitiveValue internal property of this Date object to u.
Return u.
The length property of the setMonth method is 2.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5.38
ちゃんと書いてるっぽいですね?(英語がイマイチ。。。orz
きっと知らずに使っている方はいっぱいいらっしゃいます。
みなさん気をつけてくだせぇ!!!
ライブラリを使って解決したり、日付を月初でやったりと、
対策もたくさんあります!
一番良いのは何かを考えながら実装するのも楽しいですね!