No.131-2 |
指定した年の「成人の日」を求める |
回答者 入川 精二 |
2002年03月 242号 P.26 |
来年の成人の日を調べるには手帳を見ます。この回答は、質問の趣旨を無視しています。
それでは再来年は? 一昨年は? となると、やはりコンピュータで・・・ということです。「汎用性」を求めると、しっかりした仕掛けが必要です。
「成人の日」は1月の第2月曜日と決められていますから、「必ず1月8日から14日までの間にある」という木村さんの説明は、なるほどその通り と思って読みました。
日付は'+1'していけば次の日が求められますが、「曜日」はどうでしょうか?
神様は7日間で世界を創造されました。(旧約聖書にそう書いてあります)そこで7日目は休みの日にしました。これが日曜日です。第1日は「月曜日」です。暦の最初の日、すなわち西暦1年1月1日は月曜日です。それ以来ずっと1週間は7日でしたから、「最初の日から何日目か」で曜日は決まります。
「最初の日から何日目か」を表すのが「日付連番」です。
3月例会の2002年3月16日は730925日目になります。
「日付連番」を7で割った時の「余り」は週の第何日目かを表します。3月例会の日は7で割った余りが6です。6番目の日は「土曜日」です。
この理屈をプログラムにして、第2月曜日を求めるようにしたのが次頁のプログラムです。
やたら関数を使っていますが、中身はたいしたことはやっていません。
使っている関数の説明を一通りします。
関数名 |
説明 |
VAL(V・・) |
:「文字列」を「実数」に変換します |
DATENUM(Z・・) |
:日付(実数)から日付連番を求めます |
NUM$(X・・) or NUM$(Z・・) |
:「整数」・「実数」を「文字列」に変換します |
IVAL(V・・) |
:「文字列」の数字を「整数」に変換します |
RIGHT$(V・・,n) |
:「文字列」のn桁目から右の文字列 |
FORM$(V・・,5) |
:半角の「文字列」を全角に変換します |
MOD |
:これは「関数」には入らなくて、「演算記号」です。
計算式に+,−,*,/を使いますが、これと同じ記号です。
よく「オート機能解説書に書いてない」と質問されます。
指令リファレンスVol.1」の216頁、「計算式の書き方」の所にサラリと書いてあります。
CAL;C5MOD3=C6 のように使います。(C5を3で割った余りをC6に)
|
1 <成人の日>
2 /*********************************************************************/
3 /* V01 西暦年(4桁の数字) */
4 /* V02 年月日(8桁の数字--文字列) */
5 /* V03 成人の日の「日」(1 or 2桁の数字) */
6 /* Z02 年月日(8桁の数字--実数) */
7 /* Z03 Z02 の日付連番 */
8 /* Z04 日付連番(Z03)を7で割った余り */
9 /*********************************************************************/
10
11 $年: ACCEPT "西暦何年? (YYYY)",V01; /* 年=4桁の数字 */
12 IF ERR(0)=55 THEN GOTO $END;
13 IF LEN(V01)<4 | >4 THEN GOTO $年;
14 IF VAL(V01)<1000 THEN GOTO $年;
15 LET V02=V01+"0108"; /* 年月日=8桁の数字 */
16 LET Z02=VAL(V02);
17 $連番: LET Z03=DATENUM(Z02); /* DATENUM:日付連番を求める関数 */
18 LET Z04=Z03 MOD7; /* MOD:割り算の剰余を求める演算記号 */
19 IF Z04=1 THEN GOTO $月曜;
20 LET Z02=Z02+1;
21 GOTO $連番;
22 $月曜: LET V02=NUM$(Z02); /* NUM$:整数・実数を文字列に変換する */
23 LET V03=NUM$(IVAL(RIGHT$(V02,7)));
24 /* IVAL:文字列の数字を整数に変換 */
25 $表示: BELL;
26 MESSAGE FORM$(V01,5)+"年の成人の日は1月"+FORM$(V03,5)+"日です";
27 /* FORM$(・・,5):半角文字を全角に変換 */
28 $END: STOP;
ついで といっては何ですが、昔々「年月日を指定すると曜日を表示する」プログラムを作りました。紹介します。
1 <曜日> 【 Ver.01.01 19950721 】 曜日を求める
2 $??: CLEAR Z1,2/11 & V1,4;
3 ACCEPT "年月日は?(YYYYMMDD)",Z1; /* Z1 = YYYYMMDD */
4 $CHK1: IF ERR(0)=55 THEN STOP; /* [ESC] が押された */
5 $CHK2: IF Z1=0 THEN STOP; /* "0" が押された */
6 $CHK3: IF Z1<10101 THEN GOTO $??; /* 西暦1年1月1日以前 */
7 LET Z11=DATENUM(Z1); /* Z11 = 日付連番 */
8 $CHK4: IF Z11=0 THEN GOTO $??; /* あり得ない日付 */
9 $CHK5: IF Z1>=1000101 THEN GOTO $連番;
10 LET Z11=DATENUM(Z1+20000000)-730485; /* Z1 が 991231 以前 */
11 $連番: LET Z2=Z11 MOD7; /* Z2 = 曜日連番 */
12 LET V4=KMID$("日月火水木金土",INTG(Z2)+1,1)+"曜日";
13 $表示: LET V1=NUM$(YEAR(Z11))+"年"; /* V1 = YYYY年 */
14 LET V2=NUM$(MONTH(Z11))+"月"; /* V2 = MM月 */
15 LET V3=NUM$(DAY(Z11))+"日"; /* V3 = DD日 */
16 MESSAGE V1+V2+V3+"は "+V4+" です"; /* 日付と曜日を表示 */
17 GOTO $??;
18 STOP;
□
|
|
|