FIELD NOTES: 書を持って街へ出よう

合同会社フィールドワークス プログラマ兼代表のブログ

曜日の計算

年・月・日で指定された日付の曜日と年初からの経過日を求める関数を作成した。

年・月・日は,いづれも1はじまりの数値を与える。
wday_of_dateは,曜日に対応する数値(0:日曜日, 1:月曜日, ..., 6:土曜日)を返す。
yday_of_dateは,1月1日からの経過日(1月1日は0と数える)を返す。

(* Zellerの公式により曜日を求める。*)
let wday_of_date y m d =
  let y, m = if m <= 2 then y - 1, m + 12 else y, m in
  (y + (y / 4) - (y / 100) + (y / 400) + (13 * m + 8) / 5 + d) mod 7

(* ユリウス通日を求める。*)
let julian_day_of_date y m d =
  let y, m = if m <= 2 then y - 1, m + 12 else y, m in
  let d =
    if (y * 12 + m) * 31 + d >= (1582 * 12 + 10) * 31 + 15 then
      d + 2 - y / 100 + y / 400
    else
      d
  in
  (int_of_float (365.25 *. (float_of_int (y + 4716)))) +
  (int_of_float (30.6001 *. (float_of_int (m + 1)))) +
  (d - 1524)

(* 年初からの経過日を求める。*)
let yday_of_date y m d =
 (julian_day_of_date y m d) - (julian_day_of_date y 1 1)

通常はUnix.mktime関数を使えば曜日と経過日は求められるので,このような関数を自作する必要はないはずである。しかし実際に試してみると,1901年以前の日付で例外が発生した。

Exception: Unix.Unix_error (ERANGE, "mktime", "").

32ビットOSであれば,1901年以前の日付が扱えないのは理解できるが,64ビットOS(Mac OS X 10.6.4)での結果である。
ちなみに,2038年以降の日付は問題なく処理できる。

Unixライブラリのソースも少し調べてみたが,素直にmktime()を呼んでいるだけに見える。mktime()は,64ビットに対応していないのだろうか?また,これはMac OS X固有の問題なのだろうか?

釈然としないが,上記の関数を作成して制限をなくした(本当は,1901年以前の日付など使わないと思うのだが,ついカッとなって作ってしまった)。