今回は、指定日の n日後の日付を調べる関数を作ります。
年月日は構造体として定義し、指定日を渡したり結果を戻すのに、構造体を関数とやり取りします。
n に負の値を指定すると、過去の日付を調べることもできます。
(例) 2020年東京オリンピック開会式(2020/07/24) の 1000日前は?
2013年の立春(2013/02/04)の 209日後は? 二百十日は、台風襲来の特異日だそうです
2014年の立春(2014/02/04)の 87日後は? 八十八夜は、新茶の摘み時です
下で、作成したプログラムを使って調べることにしましょう。
【 用意する関数 】 dateYMD_t afterNday( dateYMD_t t, int n ) 機 能 : tに指定された日のn日後の日付を求め、dateYMD_t型の戻り値で返す nに負の値を指定すると、過去の日付が戻される
【 関数の処理手順 】
ymd の d に n を加算してしまい、d が当月になるまで、m を進めてその分の日数を引きます。
たとえば 2013/10/10 の 90日後なら、まず d に 90 を足す --> (2013/10/100)
・ ひと月進める --> d から10月の 31日を引き m は 11月へ(2013/11/69)
・ 11から12月へも同様 --> (2013/12/39)
・ さらに翌年の 1月へ --> (2014/01/09)
・・・ d が当月の日数内になったので、処理は終わり
N < 0 の場合は、過去の日付を求めるので上記と逆です。m を戻し日数は足し算していく処理になります。たとえば n が -90 なら 2013/10/-80 から始め、d が 1以上の有効な日付になるまで繰り返します。
なお、y がうるう年かどうかで 2月の日数が異なるため、その判定も必要です。
#include <stdio.h> typedef struct { int y; int m; int d; } dateYMD_t; // --- yがうるう年か調べる int isLeapYear( int y ) { if( y % 4 == 0 && y % 100 != 0 || y % 400 == 0 ) return 1; else return 0; } // --- 指定日tのn日後の日付を返す dateYMD_t afterNday( dateYMD_t t, int n ) { int days[][12] = { { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } , { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } }; int isleap; if( n == 0 ) return t; isleap = isLeapYear( t.y ); //うるう年判定 t.d += n; if( n > 0 ) { //将来日付 dが当月内になるまで日数を引いてはmを進める while( t.d > days[isleap][t.m-1] ) { t.d -= days[isleap][t.m-1]; if( ++t.m > 12 ) { isleap = isLeapYear( ++t.y ); t.m = 1; } } } else { //過去日付 dが正の日付になるまで日数を足してはmを戻す while( t.d <= 0 ) { t.d += days[isleap][t.m-1]; if( --t.m < 1 ) { isleap = isLeapYear( --t.y ); t.m = 12; } } } return t; } // ------------------------------------------------------ main() { dateYMD_t dlst[] = { {2020,7,24}, {2013,2,4}, {2014,2,4} }; dateYMD_t nd; int i, nlst[] = { -1000, 209, 87 }; for( i = 0; i < 3; i++ ) { nd = afterNday( dlst[i], nlst[i] ); printf( "%4d/%02d/%02d の %5d日後 ・・・ %4d/%02d/%02d\n" , dlst[i].y, dlst[i].m, dlst[i].d, nlst[i], nd.y, nd.m, nd.d ); } }
afterNday関数内では新たな構造体変数を用意せず、仮引数を書き換えたものを結果として returnします。値渡しの引数のコピーを書き換えても実引数には変更が反映されません。
呼び出し側では、戻り値を dateYMD_t型の変数に代入してから使います。構造体は = により一括で代入ができます。
2020/07/24 の -1000日後 ・・・ 2017/10/28 2020東京五輪開会式の1000日前 2013/02/04 の 209日後 ・・・ 2013/09/01 2013年の二百十日 2014/02/04 の 87日後 ・・・ 2014/05/02 2014年の八十八夜
[ ご案内 ] 構造体の要点を学習できるコース:要点講座 [構造体編]
#define DEBUG : #ifdef DEBUG DEBUGが定義されているときだけ PR_DBL2( hm, w ); #ifdef DEBUG と #endif 間の内容が有効です。 #endif