通算日数を日付に変換する
西暦1年1月1日を基準にして、通算日数(1〜)を日付に変換します。
前田稔(Maeda Minoru)の超初心者のプログラム入門
プロジェクトの設定
- 空の新規プロジェクトを作成して下さい。
- ページ先頭の画像を参考にして DialogBox を作成して下さい。
キャプションとIDを次のように設定して下さい。
キャプション | ID |
西暦年月日 | IDC_EDIT1 |
通算日数 | IDC_EDIT2 |
曜日 | IDC_EDIT3 |
通算日数計算 | IDOK |
年月日計算 | IDOK2 |
終了 | IDCANCEL |
- ソースプログラムをフォルダに格納してプロジェクトに追加します。
[デバッグ]を選択してビルドに続いて実行を行います。
年月日の表示を確認して、通算日数計算をクリックすると1年1月1日からの通算日数と曜日が表示されます。
通算日数に数値を設定して、年月日計算をクリックすると年月日と曜日が表示されます。
プログラムの説明
- このプログラムはカレンダーに関係する計算方法の理解を深めるために作成したものです。
生年月日を入力して、曜日と生存日数を表示 と併せて参照して下さい。
実際には「西暦1年1月1日」などは存在しません。
詳細は カレンダの話 を参照して下さい。
このプログラムでは32ビットの int 型を使っています。
VCの古いバージョンでは int 型が16ビットになっていて、正しい結果が表示されないことがあるので注意して下さい。
- 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];
|
- WM_INITDIALOG: には DialogBox の初期化のときに制御が渡されます。
西暦年月日に仮の値として「1999/1/1」を設定しています。
case WM_INITDIALOG:
SetWindowText(hDlg,"西暦1年1月1日からの通算日数");
SetDlgItemText(hDlg,IDC_EDIT1,"1999/1/1");
break;
|
- 通算日数計算ボタンがクリックされたとき、曜日と通算日数を求めて表示します。
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;
|
- 年月日計算ボタンがクリックされたとき、曜日と年月日を求めて表示します。
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;
|
- 西暦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);
}
|
- 閏(うるう)年を調べる関数です。
うるう年の説明は カレンダの話 を参照して下さい。
int uruu(int year)
{ if (year%400L==0L) return(1);
if (year%100L==0L) return(0);
if (year%4L==0L) return(1);
return(0);
}
|
- 文字列の年月日から 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);
}
|
- 通算日数から日付を計算する関数です。
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;
}
|
全ソースコード
超初心者の方のために全ソースコードを掲載します。 (^_^;)
/************************************************/
/*★ 西暦1年1月1日からの通算日数 前田 稔 ★*/
/************************************************/
#include <windows.h>
#include "resource.h"
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];
// 関数のプロトタイプ宣言
LRESULT CALLBACK DialogProc( HWND, UINT, WPARAM, LPARAM );
//★ 文字列の日付(1999/1/1)から、年月日を数値に変換
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);
}
//★ 閏年を調べる関数
int uruu(int year)
{ if (year%400L==0L) return(1);
if (year%100L==0L) return(0);
if (year%4L==0L) return(1);
return(0);
}
//★ 西暦1年1月1日からの通算日数を調べる関数
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);
}
//★ 西暦1年1月1日からの通算日数(1〜)で日付を計算
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;
}
//★ Windows MAIN 関数
int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE, LPSTR, int )
{
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),NULL,(DLGPROC)DialogProc);
return TRUE;
}
//★ Dialog Box の CALLBACK 関数
LRESULT CALLBACK DialogProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam)
{ char str[64];
switch(msg)
{
case WM_INITDIALOG:
SetWindowText(hDlg,"西暦1年1月1日からの通算日数");
SetDlgItemText(hDlg,IDC_EDIT1,"1999/1/1");
break;
case WM_COMMAND:
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;
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;
case IDCANCEL:
PostQuitMessage(0);
return TRUE;
}
break;
case WM_CLOSE:
EndDialog(hDlg, TRUE);
return TRUE;
break;
}
return FALSE;
}
前田稔(Maeda Minoru)の超初心者の Windows(C言語)
前田稔(Maeda Minoru)の超初心者の C#(Frame Work)