#include long jul2jd(int year, int month, int day); void jd2jul(long jd, int* year, int* month, int* day); int main() { long jd; /* ユリウス日 */ int year, month, day; /* 年・月・日 */ int y, m, d; /* これらは返り値用 */ year = -4712; month = 1; day = 1; /* これがユリウス日 0 の日 */ printf("このテストはマシンによっては少々時間がかかります. "); printf("「:」が約 365 個印字されるまでお待ちください. "); printf("エラーメッセージが出力されなければ成功です.\n"); for (jd = 0; jd < 3652500L; jd++) { int isleap; static char days[2][13] = { { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; if (jul2jd(year, month, day) != jd) { /* jul2jd() のテスト */ printf("error: %ld\n", jd); } jd2jul(jd, &y, &m, &d); if (year != y || month != m || day != d) { /* jd2jul() のテスト */ printf("error: %ld\n", jd); } isleap = !(year % 4); /* 閏年? */ if (++day > days[isleap][month]) { /* year, month, day を翌日に変更 */ day = 1; month++; if (month == 13) { month = 1; year++; } } if (jd % 10000 == 9999) { /* 途中のメッセージ */ printf(":"); fflush(stdout); } } printf("\n"); printf("テストは完了しました. "); printf("%d 年 %02d 月 %02d 日までチェックしました.\n", y, m, d); return 0; } /****************************************************************************** 【関数名】 jul2jd() 【機 能】 ユリウス暦からユリウス日への換算。 【引 数】 年、月、日。 【注意0】 ここでいうユリウス暦とは、グレゴリウス暦への改暦の直前に実施されて いたユリウス暦をその実施以前にまでさかのぼって延長したものである。 初期には閏年の入れ方が違っていたそうだが、それには対応していない。 【注意1】 紀元前の年の呼び方は、1 年の前年を 0 年とする天文学上の規約に従う。 引数は -4712 年 1 月 1 日(ユリウス日 0 の日)以降、桁あふれが 生じる直前まで有効である。実際には -4716 年 03 月 01 日以降に対し 正しいユリウス日を返すと思うが、あまり意味がないだろう。 【注意2】 最初に 4716 を足すのは閏年か平年かを変えずに考えるべき全ての年を正 にするため。最後の 1402 は“魔法の数”。 【注意3】 Zeller の公式の変形である。 ******************************************************************************/ long jul2jd(int year, int month, int day) { year += 4716; if (month < 3) { year--; month += 12; } return 365L * year + year / 4 \ + (153 * month - 457) / 5 + day - 1402; } /****************************************************************************** 【関数名】 jd2jul() 【機 能】 ユリウス日からユリウス暦への換算。 【引 数】 ユリウス日、年・月・日を格納するアドレス。 【注意0】 ここでいうユリウス暦とは、グレゴリウス暦への改暦の直前に実施されて いたユリウス暦をその実施以前にまでさかのぼって延長したものである。 初期には閏年の入れ方が違っていたそうだが、それには対応していない。 【注意1】 紀元前の年の数え方は、紀元元年の前年を紀元 0 年とする天文学上の規約 に従う。引数のユリウス日は 0 以上、桁あふれが生じる直前まで有効で ある。実際にはもう少し前の、ユリウス日が負の日から使えると思うが、 あまり意味がないだろう。 【注意2】 最初の 1402, 最後の 4716 については jul2jd() の注意を参照のこと。 【注意3】 jul2jd() の“自然”な“逆関数”である。特別なことはしていない。 ******************************************************************************/ void jd2jul(long jd, int* year, int* month, int* day) { int y, m; /* 年、月を格納する一時変数 */ jd += 1402; y = (4 * jd - 1) / 1461; jd -= 1461L * y / 4; m = (5 * jd - 3) / 153 + 3; jd -= (153 * m - 457) / 5; if (m > 12) { m -= 12; y++; } *year = y - 4716; *month = m; *day = jd; }