2005 6 7 8 9 10 11 12
2006 1 2 3 4 5 6 7 8 9 10 11 12
2007 1 2 3 4 5 6 7 8 9 10 11 12
2008 1 2 3 4 5 6 7 8 9 10 11 12
2009 1 2 3 4 5 6 7 8 9 10 11 12
2010 1 2 3 4 5 6 7 8 9 10 11 12
2011 1 2 3 4 5 6 7 8 9 10 11 12
2012 1 2 3 4 5 6 7 8 9 10 11 12
2013 1 2 3 4 5 6 7 8 9 10 11 12
2014 1 2 3 4 5 6 7 8 9 10 11 12
2015 1 2 3 4 5 6 7 8 9 10 11 12
2016 1 2 3 4 5 6 7 8 9 10 11 12
2017 1 2 3 4 5 6 7 8 9 10

ホーム

2012年07月18日

http://jarp.does.notwork.org/diary/201207b.html#201207141

いや、チラッは考えたと思うんですよ、マジで。

ただ、new Date(2013, 1, 29)みたいなのの結果がどうなるか
わかんないなーと思ったと思うんですよ、そのとき。

よく覚えてないんですけど。

というわけで、悔しいからECMAScriptのドキュ読みました。
new Date(2013, 1, 29)みたいなのが処理系依存だったら、
まだ自分のやり方が間違ってないって言い張れますしねw

http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf

このドキュメントがまたむつかしくてですね。どうにか読み解いた
結果、ポイントとなるのは以下の文章:

  15.9.1.12 MakeDay (year, month, date)
  ...
  7. Find a value t such that YearFromTime(t) == ym
     and MonthFromTime(t) == mn and DateFromTime(t) == 1;
     but if this is not possible (because some argument
     is out of range), return NaN.
  ...

訳すと:

  次のような条件を満たす値tを見つける。すなわち、

    YearFromTime(t) == ym

  かつ

    MonthFromTime(t) == mn

  かつ

    DateFromTime(t) == 1

  ただし、このような条件を満たす値が見つけられない場合は
  (一部の引数が範囲を超えているなどの理由で)、NaNを返す。

このMakeDayというのは規格上の存在なんですけど、これを
もとにnew Date(year, month, date)が規定されてます。

さらに、このMakeDayというのがNaNを返すと、Date.prototype.getDate()
もNaNを返すと規定されています(15.9.5.14)。

というわけで:

  function isLeapYear(year) {
    var date = new Date(year, 1 , 29).getDate();
    return !isNaN(date) && date == 29;
  }

というのがECMAScript的にも正当で、自分のはダラダラ長い
だけのダメコードだったというオチw

本家Permlink


2012年07月12日

閏年判定というのはバグりやすいことで有名で、Wikipediaの
閏年の項目でもわざわざ触れられている。

http://ja.wikipedia.org/wiki/%E9%96%8F%E5%B9%B4

そのWikipediaには、親切なことに判定コードまで紹介されている:

  year%4 == 0 && year%100 != 0 || year%400 == 0

おそらく、閏年判定のプログラムを書けといわれたら、ほとんどの
人がこれと似たようなコードを書くだろう。

しかし、自分は、違うやり方で書きたかった。どこかのコードを
コピペするか、仕様を読んで自分で書き上げるか、どっちにしても
バグりやすいと思ったから。

そこで思いついたのが下のコード:

function isLeapYear(year) {
  var first = new Date(year, 0, 1);
  var ms = first.getTime();
  ms += 60 * 60 * 24 * 59 * 1000;
  var date = new Date(ms + 10000);
  return date.getDate() == 29;
}

つまり、与えられた年の1月1日から59日後の日付を求めて、
それが29日ならば閏年ということだ。

言語組み込みの閏年判定ルーチンを再利用しているといっても
いい。

Rubyのように閏年判定メソッドが用意されていれば(Date#leap?)、
もちろんそれを使えばいい。しかし、残念ながら、JavaScript
にはそれがない。

--

ところで、一部のプログラマの間では、コピペが禁止されている
という。

もし、コピペが禁止されていたら、Wikipediaからコピペしては
いけいということになる。そして、自分でタイプして、バグる
わけだ。

あるいは、Wikipediaからコピペしたコードと、自分が書き
上げた59日足すコードとを見比べてみてもいい。自分は59日の
ほうがバグりにくいと感じるが、はじめて見る人は面食らうだろう。

結局、コピペしたかどうかではなく、きちんとテストしたか、
DRYを保てているか確かめたかということが大切ということ。

--

ところで、この関数、Twitterでつぶやいてみたんだが、全然
反応がない。最初Rubyで書いて、次にJavaScriptで書いた。
でも、どちらにも反応はない。

まぁ、自分が思うほど珍しくないということなんだろう。

ソーシャルコーディングというのは、このように冷酷でもある。

本家Permlink


Copyright © 1905 tko at jitu.org

バカが征く on Rails