ある日付に対し、n日後の日付を算出する関数。
nの値をマイナスにすれば、n日前の日付になる。

例えば、2004/8/10 から 5日後の日付は 2004/8/15、といった具合。

<関数名>
  dayAdd —- n日後の日付を算出する

<形式>
  void dayAdd(int *year2, int *month2, int *day2, int year1, int month1, int day1, int n);

<引数>
  year2, month2, day2 (出力)n日後の日付。西暦年月日。
  year1, month1, day1 (入力)基準となる日付。西暦年月日。
  n (入力)n日後。マイナス値にすれば、n日前になる。

<関数値>
  なし。

<注意事項>
  引数として渡された日付の実在性チェックはしない。
  関数 ut2jd()ユリウス日への換算)が必要。
  関数 jd2ut()ユリウス日からの換算)が必要。

用例
  int year, month, day;
  dayAdd(&year, &month, &day, 2004, 8, 1, 11);

<関数本体>
  dayAdd.c

<説明>
  内部では、基準日をまずユリウス日に換算してから、nの値を足し、最後に西暦年月日に戻す。そんな処理を行う。

前後異なる2つの日付に対し、間の離れた日数(差)を算出する関数。

例えば、2004/8/10 から 2004/8/15 まで の日数(差)は 5日、といった具合。

前後関係はが逆になっていれば、マイナスの結果になる。
例えば、2004/8/15 から 2004/8/10 まで の日数は -5日、との計算結果。

<関数名>
  dayDiff —- 2つの日付の間の日数を算出する

<形式>
  int dayDiff(int year1, int month1, int day1, int year2, int month2, int day2);

<引数>
  year1, month1, day1 前の日付。西暦年月日。
  year2, month2, day2 後の日付。西暦年月日。

<関数値>
  日数。マイナスの値であれば、日付の前後関係が逆になっていることを示す。

<注意事項>
  引数として渡された日付の実在性チェックはしない。
  関数 ut2jd()ユリウス日への換算)が必要。

用例
  dayDiff(2003, 8, 1, 2004, 9, 11);

<関数本体>
  dayDiff.c

<説明>
  内部では、2つの日付をそれぞれ、ユリウス日に換算してから、差の算出を行う。

今度は逆の、ユリウス日を世界標準時に換算する関数。

<関数名>
  jd2ut —- ユリウス日を世界標準時に換算

<形式>
  void jd2ut(int *year, int *month, int *day, int *hour, int *min, int *sec, long j, double d);

<引数>
  year, month, day (出力)西暦年月日
  hour (出力)時 (0 〜 23)
  min (出力)分 (0 〜 59)
  sec (出力)秒 (0 〜 59)
  j (入力)ユリウス日の整数部分
  d (入力)ユリウス日の小数部分

<関数値>
  なし

用例
  int year, month, day, hour, min, sec;
  jd2ut(&year, &month, &day, &hour, &min, &sec, 2448422L, 0.5);

<関数本体>
  jd2ut.c

<説明>
  ユリウス日の起算日紀元前4713年1月1日はユリウス暦による日付で、ユリウス暦は紀元前46年にユリウス・カエサルが採用したもの。ユリウス暦は1582年10月4日まで使われ、その翌日はグレゴリオ暦の同年10月15日だった。

あまり聞かない、ユリウス日に関する関数。天文学等、専門家の間では当たり前のように使っているようだが。

詳しいことについては、ここ をみてください。

<関数名>
  ut2jd —- 世界標準時をユリウス日に換算

<形式>
  long ut2jd(double *d, int year, int month, int day, int hour, int min, int sec);

<引数>
  d (出力)1日の時間を 1 としたときの正午からの時間。ユリウス日の小数値。
  year, month, day (入力)西暦年月日
  hour (入力)時 (0 〜 23)
  min (入力)分 (0 〜 59)
  sec (入力)秒 (0 〜 59)

<関数値>
  ユリウス日の値(の整数値)

<注意事項>
  引数として渡される西暦年月日が実在するかどうか については、本関数内ではチェックしない。
  ユリウス日の整数値は関数値から、小数値は第1引数から得られる。

用例
  double d;
  ut2jd(&d, 1996, 2, 29, 12, 0, 0);

<関数本体>
  ut2jd.c

<説明>
  日常生活で時刻といえば、年・月・日・時・分・秒を使っている。しかし計算には60進法、月の大小、閏年か平年、といったものが混在している。天文学の世界では、ある決められた起算日から日付を積算していくユリウス日(ユリウス通日)という非常に便利な時の尺度がある。
  そのユリウス日の0.0日は紀元前4713年(-4712年)1月1日の正午で、翌日の正午がユリウス日1.0日である。1991年6月15日世界標準時0時のユリウス日は2448422.5日になる。
  なお、日本時間(Japanese Standard Time; JST)は世界標準時より、9時間進んでいる。

大の月、小の月、つまりたとえば、3月は31日あるのに対し、4月は30日しかない。各月の日数、あなたなら、判ってらしゃるよね。

周りに聞いても、なかなか覚えてないひとが多いみたい。小さい頃、自分がよく教わっていたのに。

上の写真の意味はお分かりですか。
左手でも、右手でも、また、左端から数えても、右端から数えても、全く同じだが、山は大の月、谷は小の月(あるいは2月)を示すのだ。

たとえば、写真の通り、左手の右端から数えていこう。1月、2月、…、7月、と数えていき、左端の山に止まる。つぎの8月はもう1回、左端の山を使う。8月、9月、…、12月。どう? 大の月、小の月、これで生涯忘れないでしょ。ひとによっては、8月はもう片方の握り拳を使うらしいが、原理は皆同じ。

<関数名>
daysOfMonth —- 西暦年と月から、その月の日数を算出

<形式>
int daysOfMonth(int year, int month);

<引数>
year, month 西暦年月

<関数値>
その月の日数。たとえば、1月であれば31、4月であれば30。

<注意事項>
閏年にも対応している
引数の月の値が1〜12以外であれば、1月とみなす。

用例
daysOfMonth(2004, 2);

<関数本体>
daysOfMonth.c

<説明>
閏年の判定法が判れば、あとは簡単に理解できるはず。

閏年かどうか、常識問題として、あなたは判ってらしゃる?

4年一回、ということのようだが、正確には違う。世の中、天才プログラマと呼ばれた人たちでさえ、良く間違う。といっても、プログラマって案外常識のないひとが多い。

2000年問題やら、エクセルのバグやら、閏年にまつわるエピソードがいくらでもありそう。

さて、正しい知識とはこんなもの。下記の条件のうち、いずれかを満たす西暦年が閏年となる。
  条件1: 4で割り切れて100で割り切れない年
  条件2: 400で割り切れる年

早い話、1900, 2100年は平年だが、その間のほかの年については、4年おきと理解して正しい。いま生きているわれわれが生存している間、4年1回と思ってまず間違いない。

<関数名>
  leapYear —- 西暦年について閏年かどうかを判定

<形式>
  int leapYear(int year);

<引数>
  year 西暦年

<関数値>
  閏年であれば 1、平年(非閏年)であれば 0。

用例
  leapYear(2004);

<関数本体>
  leapYear.c

<説明>
  4の倍数でしかも100の倍数でない年、または400の倍数の年は閏年。
  1900年や2100は閏年ではない! 曜日までも自動表示と豪語するオートマチック機械時計は世界中数多くあるけど、1900年や2100年の曜日を正しく表示できるものはあるのだろうか。壊れてて、100%の確率で迎えられそうもない2100年のために、そのような時計をつくるのだろうか。とっても知りたい。
  閏年はなぜ必要なのだろうか。天文学によれば、地球が太陽を1周するのに、
    365.2422日 = 365日5時間48分46秒
  かかる。1年を365日とすると4年に約1日ずれてくる。閏年を作らねばならないわけだ。

Bフレッツの開通を記念して、数年前までに集めた、C言語プログラム(関数)を順次公開するね。

既にどこかで、多くの方々に見られていたものかもしれない。
ただ、サポート等は一切できないと思う。ご質問にお答えすることもままならないかもしれない。ご容赦を。

さて、1本目、曜日を正しく計算してくれる関数の公開。

染色体の異常に起因するダウン症患者、知的発達が遅れるといいながら、西暦と月日を尋ねれば瞬時に曜日を言い当ててしまう、ということが簡単にできるらしい。

しかし、一般のわれわれには、曜日の計算はなかなかできない。が、ツェラー公式 が判れば、スマートに計算できるはず。

<関数名>
  dayOfWeek —- 西暦年月日からその曜日を算出

<形式>
  int dayOfWeek(int year, int month, int day);

<引数>
  year, month, day 西暦年月日

<関数値>
  各曜日に対応する 0 〜 6 の値
     0: 日、1: 月、2: 火、3: 水、4: 木、5: 金、6: 土

<注意事項>
  引数として渡される西暦年月日が実在するかどうか については、本関数内ではチェックしない。
  1582年10月15日以降の日についてのみ正しく算出する。

用例
  dayOfWeek(2004, 8, 14);

<関数本体>
  dayOfWeek.c

<説明>
  ツェラー (Zeller) の公式 による計算法。
  現在使われているグレゴリオ暦の初日は1582年10月15日(金曜)である。本関数はその日以降の曜日を正しく算出。
  ちなみに、1582年10月15日(金曜)の前日はなんと、ユリウス暦1582年10月4日(木曜)。時間の空白があったわけだね(笑)。また、曜日だけは連続していて、休むことの大切さ、そこにもしみじみ感じる。