通算日数を日付に変換する

西暦1年1月1日を基準にして、通算日数(1~)を日付に変換します。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの設定

  1. 空の新規プロジェクトを作成して下さい。
  2. ページ先頭の画像を参考にして DialogBox を作成して下さい。
    キャプションとIDを次のように設定して下さい。
    キャプション ID
    西暦年月日 IDC_EDIT1
    通算日数 IDC_EDIT2
    曜日 IDC_EDIT3
    通算日数計算 IDOK
    年月日計算 IDOK2
    終了 IDCANCEL
  3. ソースプログラムをフォルダーに格納してプロジェクトに追加します。
    [デバッグ]を選択してビルドに続いて実行を行います。
    年月日の表示を確認して、通算日数計算をクリックすると1年1月1日からの通算日数と曜日が表示されます。
    通算日数に数値を設定して、年月日計算をクリックすると年月日と曜日が表示されます。

プログラムの説明

  1. このプログラムはカレンダーに関係する計算方法の理解を深めるために作成したものです。
    生年月日を入力して、曜日と生存日数を表示 と併せて参照して下さい。
    実際には「西暦1年1月1日」などは存在しません。
    詳細は カレンダの話 を参照して下さい。
    このプログラムでは32ビットの int 型を使っています。
    VCの古いバージョンでは int 型が16ビットになっていて、正しい結果が表示されないことがあるので注意して下さい。
  2. WTBL[][4] は曜日のテーブルです。
    MTBL[12] は大の月と小の月のテーブルで、累積した日数を格納しています。
    yy,mm,dd は年月日を計算する数値の領域です。
    sdate[64] は文字列を編集する作業領域です。
        char    WTBL[][4]= { "日","月","火","水","木","金","土" };
        int     MTBL[12]=  { 0,31,59,90,120,151,181,212,243,273,304,334 };
        int     yy,mm,dd,yobi,count;
        char    sdate[64];
        
  3. WM_INITDIALOG: には DialogBox の初期化のときに制御が渡されます。
    西暦年月日に仮の値として「1999/1/1」を設定しています。
            case WM_INITDIALOG:
                SetWindowText(hDlg,"西暦1年1月1日からの通算日数");
                SetDlgItemText(hDlg,IDC_EDIT1,"1999/1/1");
                break;
        
  4. 通算日数計算ボタンがクリックされたとき、曜日と通算日数を求めて表示します。
    setymd() 関数で yy,mm,dd を取得します。
    days() で通算日数を求めます。
                switch(LOWORD(wParam))
                {   case IDOK:          //西暦1年1月1日からの通算日数と曜日の計算
                        GetDlgItemText(hDlg,IDC_EDIT1,str,sizeof(str));
                        setymd(str);
                        count= days(yy,mm,dd);
                        yobi= count%7L;
                        wsprintf(str,"%d",count);
                        SetDlgItemText(hDlg,IDC_EDIT2,str);
                        SetDlgItemText(hDlg,IDC_EDIT3,WTBL[yobi]);
                        break;
        
  5. 年月日計算ボタンがクリックされたとき、曜日と年月日を求めて表示します。
    strdate() 関数で年月日を計算しています。
                    case IDOK2:         //通算日数から日付と曜日を計算
                        GetDlgItemText(hDlg,IDC_EDIT2,str,sizeof(str));
                        count= atoi(str);
                        yobi= count%7L;
                        SetDlgItemText(hDlg,IDC_EDIT1,strdate(count));
                        SetDlgItemText(hDlg,IDC_EDIT3,WTBL[yobi]);
                        break;
        
  6. 西暦1年1月1日からの通算日数を調べる関数です。
    西暦1年1月1日を指定すると「1」がリターンされます。
    uruu(yy) はうるう年の判定です。
        int  days(int yy, int mm, int dd)
        {   int     w;
            w=  (yy-1)*365L;            //年*365
            w+= (yy/4L - yy/100L + yy/400L + MTBL[mm-1] + dd);
            if (mm<3 && uruu(yy))  w--;
            return(w);
        }
        
  7. 閏(うるう)年を調べる関数です。
    うるう年の説明は カレンダの話 を参照して下さい。
        int  uruu(int year)
        {   if (year%400L==0L)  return(1);
            if (year%100L==0L)  return(0);
            if (year%4L==0L)    return(1);
            return(0);
        }
        
  8. 文字列の年月日から yy,mm,dd を求める関数です。
    年月日は '/' で区切って下さい。
        void  setymd(char str[])
        {   int     i;
    
            yy= atoi(str);
            for(i=1; i<64 && str[i]!='/'; i++);
            mm= atoi(str+i+1);
            for(i++; i<64 && str[i]!='/'; i++);
            dd= atoi(str+i+1);
        }
        
  9. 通算日数から日付を計算する関数です。
    yy/mm/dd の形式で日付をリターンします。
        char *strdate(int count)
        {   int     cw,w;
    
            cw= count;
            yy= cw/365+1;           //西暦年(1~)
            w= days(yy,1,1)-1;      //前年までの日数
            while(cw<=w)
            {   yy--;
                w= days(yy,1,1)-1;
            }
            cw-= w;
            for(mm=11; mm>0 && MTBL[mm]>=cw; mm--);
            cw-= MTBL[mm];
            mm++;                   //月(1~12)
            if (mm>2 && uruu(yy))  cw--;
            wsprintf(sdate,"%d/%d/%d",yy,mm,cw);
            return sdate;
        }
        

超初心者のプログラム入門(Win32API C++)