またもや、改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用までから。
JavaScriptの日時処理は少し面倒だという印象があります。上で紹介した本を読んでも、ES2015でもそれは変わってないらしく、例えばフォーマットによる日時を付与した関数なんてものも用意されてないらしいです。
その点ではMoment.jsというライブラリ(参考:Moment.jsを使う – Qiita)がよさげではあるのですが、今回は素のJavaScriptを使った加減算について。
というのもやり方は簡単で、DateオブジェクトのgetXxxxxメソッドとsetXxxxxメソッドを使えばいいだけだそう。実は、本をよむまで、getとつくメソッドがあるのは知ってたけど、setとつくメソッドがあるのは知らなかった。
使い方としては以下。
day = new Date(2016,10,6,22,30); // 2016年11月6日22時30分をセット console.log(day.toLocaleString()); //=> 2016/11/6 22:30:00 day.setMonth( day.getMonth() + 1); // 1ヶ月後に変更 console.log(day.toLocaleString()); //=> 2016/12/6 22:30:00 day.setDate( day.getDate() - 7); // 7日前に変更 console.log(day.toLocaleString()); //=> 2016/11/29 22:30:00
見て分かるように、月をまたいでもちゃんと計算される(それにしてもなぜ、月だけ0始まりにしたのだろうか。最初間違えて、『new Date(2016,11,6,22,30);』として12月6日になって混乱した)。
これを応用したら、指定の日付の月末日を取得することができる。
day = new Date(2016,10,6,22,30); // 2016年11月6日22時30分をセット day.setMonth( day.getMonth() + 1); // 1ヶ月後に変更 day.setDate(0); // 0日目(前月の最終日)をセット console.log(day.toLocaleString()); // 2016/11/30 22:30:00
ちなみに、setXxxxメソッドの戻り値は、Dateオブジェクトではなくて1970 年 1 月 1 日 00:00:00 からのミリ秒数。Dateオブジェクトだったらメソッドチェーンが利用できたので少し面倒。まあ、目的は変更後の日付を返すのではなく、自分自身の日付を変更するということだから仕方ないか。
まあ、やろうと思えば下記のようにできなくはない。
day = new Date(2016,10,6,22,30); // 2016年11月6日22時30分をセット day = new Date(new Date(day.setMonth(day.getMonth()+1)).setDate(0)); // 1ヶ月後に変更したうえでその返り値のDateオブジェクトを取得し、さらにその月の0日目を取得したうえで、その返り値のDateオブジェクトを作成する console.log(day.toLocaleString()); //=> 2016/11/30 22:30:00
いや、これはメソッドチェーンとは言わないか。
というよりよくよく考えたら、Dateオブジェクトを新しく生成すればいいだけでした(調べて気づいた)。
day = new Date(2016,10,6,22,30); // 2016年11月6日22時30分をセット day = new Date( day.getFullYear(), day.getMonth() + 1, 0, day.getHours(), day.getMinutes() ); console.log(day.toLocaleString()); //=> 2016/11/30 22:30:00
なお、日付通しの計算については、getTimeメソッドを利用して数値化したうえで、1単位をミリ秒数で表した数で割らなきゃいけないそうです。
var dat1 = new Date(2016,11,6,12,34,56); // 2016年11月6日12時34分56秒をセット var dat2 = new Date(2001,0,1,0,0,0); // 2001年1月1日0時0分0秒をセット var diffDays = (dat1.getTime() - dat2.getTime()) / (1000 * 60 * 60 * 24); console.log('21世紀になってから' + ~~diffDays + '日がたちました'); //=> '21世紀になってから5818日がたちました' var diffSeconds = (dat1.getTime() - dat2.getTime()) / (1000); console.log('21世紀になってから' + ~~diffSeconds + '秒がたちました'); //=> '21世紀になってから502720496秒がたちました'
なんで標準でこれぐらいの計算が簡単にできるメソッドが用意されていないのだろうか……。ES2015では追加されるんじゃないかと期待していたのだけど……。
コメント
言語仕様が肥大するからです。プログラマーが書ける材料だけを用意するのが、本来の方法論です。
Java は、これを誤ったようです。