回答箱 No.131-2: 指定した年の「成人の日」を求める

       ◆ 質問箱 No.131 質問者:  木村 芳樹  2002年02月 241号 P.22
           ◆ 質問箱 目次へ
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;
  
回答箱のプログラムがプログラム集に収録されています。


このページのTOPへ戻る