A Perfect Night For Bananafish

だがそれを語るには人生は短すぎる

その月は一体何日あるのか

今日も前世紀的プログラミング言語のマニュアルを眺めていたところ、日付を入力するようなサンプルプログラムがあった。
入力時に桁数チェックしかしていないので、このままでは2月31日とか13月99日とか、ありえない日付も入力できてしまう。

イマドキのプログラミング言語は便利機能豊富で、日付の妥当性チェックなんかで悩むこともないのだろう。
インターフェイスもよくなってるので、カレンダーから選択させて不正入力を防ぐことだってできる。でもCOBOLだし。

とりあえず、「その月が何日まであるのか」について考えてみた。
たとえばphpではズバリcal_days_in_monthという関数が指定した年とカレンダーについて、月の日数を返してくれる。でもCOBOLだし。

31日までない短い月は、「西向く侍」(二四六九士) と言われるように 2月、4月、6月、9月、11月である。
おまけに2月はうるう年かどうかで28日だったり29日だったりと厄介だ。
自前で実装するなら例えばcaseでswitchするとか、あるいは各月の日数を[31,28,31,30,31,30,31,31,30,31,30,31]とあらかじめ覚えさせて、2月は、うるう年なら1日増やすというのが簡単でいいだろう。

終了

だとつまらないので、ニシムクサムライ判定式を考えた。

⌊|7.5-month| mod 2⌋

7.5から判定したい月monthを引いた絶対値を2で割った余りの整数部分をとる。ただしmonthは1から12までの値が入るものとする。
結果は次の表のようになる。

month 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
計算結果 0 1 0 1 0 1 0 0 1 0 1 0

2月、4月、6月、9月、11月が1に、それ以外は0になるので、真偽判定にも使えるし

31-⌊|7.5-month| mod 2⌋

として、31から引いてやれば

month 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月
計算結果 31 30 31 30 31 30 31 31 30 31 30 31

その月が何日まであるのか計算できるっ!\2月はどうした/
2月だけは、うるう年判定してうまいことやってくれよ。
こんな感じで↓

#うるう年判定
def isLeapYear (year)
  if (year%4==0 and year%100!=0) or (year%400==0)
    true
  else
    false
  end
end
# その月に何日あるか
def daysInMonth(month,year)
  if month==2
    if isLeapYear(year)
      return 29
    else
      return 28
    end
  else
    return 31-((7.5-month).abs%2).truncate
  end
end

# 2009年の1月から12月までを計算してみる
for m in 1..12
  print daysInMonth(m,2009)," "
end

# 実行結果
# 31 28 31 30 31 30 31 31 30 31 30 31

なぜかruby。1月〜12月以外の月については考慮してない。

で、実際問題、
その月が何日あるかを知りたいのではなくて、その日付が妥当かどうかチェックしたいワケで。
そういうのを知りたい人はグレゴリウス13世を恨みつつ、今すぐ作業に戻ってください。


ところで、判定式はceilやabsなんか使わなくても、実は

(month-1)%7%2

でよいのです