gotin blog

Whatever gotin wanna write

Date.prototype.setMonthの私にとってややこしいこと

選択日curDateの日にちを1日に設定してから指定されたdateの月,年に設定し,カレンダテーブルを再生成しています。最初に日にちを1日に設定しているのは,日にちによっては意図した月と異なる月になってしまう可能性があるためです。たとえば1月31日を表すDateオブジェクトに対し setMonth(1)を実行する(Dateオブジェクトは1月を0として扱うため,1は2月を表す)と,2月31日ではなく,3月3日に変更されます。このようにDateオブジェクトは存在しない日時を示さないように適切に処理する機能があるのですが,カレンダの生成処理では指定した月に応じたカレンダを表示したいので,このような月のジャンプが起こらないようにしたいわけです。そのため日にちを先に1日するようにしています。

Greasemonkeyによるアプリケーション開発:第3回 Greasemonkeyによるカレンダアプリケーションの機能向上|gihyo.jp … 技術評論社

↑これってあまりにも安直な対策。しかもユーザビリティ悪い。1/31のときに一月先に移動したら、2/1ではなく(ましてや3/3でもなく)2/28(閏年なら2/29)になってほしいのが普通だと思われます。

ちゃんとした対処をするべきだと思ったんですが、説明が面倒になるかと思ってあのようにしてました。
対処するなら↓こんな感じでしょうか。

Date.prototype.addMonth = function (offset) {
  var oldDate = this.getDate();
  this.setMonth(this.getMonth() + offset);
  if (Date.limitMode && 
     oldDate != this.getDate()){
   this.addDate(-this.getDate());
  }
  return this;
};

Date.prototype.addDate = function (offset) {
  this.setDate(this.getDate() + offset);
  return this;
};

こんな↑感じのものでも書いておけば、

  Date.limitMode = true;
  alert(new Date(2007, 1-1, 31).addMonth(1));   // 2007/1/31 + 一月 #limitMode
  // 結果:Wed Feb 28 2007 00:00:00 GMT+0900 (JST)  (2007/2/28)

  Date.limitMode = false;
  alert(new Date(2007, 1-1, 31).addMonth(1));   // 2007/1/31 + 一月 #normalMode
  // 結果:Sat Mar 03 2007 00:00:00 GMT+0900 (JST)   (2007/3/3)

ってな感じに。
あいかわらずクロスブラウザを試す余力がなく、Firefox2.0.0.6 on Macでしか試してません^^;