マイコン宇宙講座-万年カレンダー

年月を指定すると、その月のカレンダーを表示します。万年カレンダーを計算で作成していくには、まず、その月の最初の日の曜日番号とユリウス日を求め、そこから、その月の日数まで+1日ずつしていきます。ユリウス日から日を求めるにはサブルーチンjdateを呼びます。曜日によって日を表示する位置も求めておきます。このプログラムで求める曜日番号は次のとおりです。

曜日番号0123456
曜日日曜日月曜日火曜日水曜日木曜日金曜日土曜日

曜日番号 = (MJD – 4 / 7)R
Rはカッコの中のあまりを求めることを意味します。

メインルーチンについて

N-BASICで書かれたコードをPythonで書き直すにあたって、その月の1日目が日曜日だと初週の日付の表示位置がズレて表示されてしまうということがあったため、処理的に少し修正したものを掲載してあります。なお、N-BASICで書かれたコードが同じ現象を起こすかは未確認です。ちなみにGNU Fortranによるコードではループの部分を除いて、同じようにコードを記述しても発生しません。以下はGNU Fortranのコードを一部抜粋したものです。N-BASICとほぼ同じ書き方です。

    t = month
    i = 0
    do
        n = (jd - 4.0d0) / 7.0d0
        no = 7.0d0 * (n - int(n))

        call Jdate(jd, year, month, day)

        if (month /= t) then
            exit
        end if

        if (int(no + 0.1) == 0) then
            write(*, fmt='(a)', advance='no') tab(7)
        end if

        if (i == 0) then
            write(*, fmt='(a)', advance='no') tab(int(no + 0.1) * 3 + 7)
        end if

        if (int(no + 0.1) == 6) then
            write(*, '(i3)') int(day)
        else
            write(*, fmt='(i3)', advance='no') int(day)
        end if

        i = i + 1
        jd = jd + 1.0d0
    end do

メインルーチン m24.py

# m24.py
# マイコン宇宙講座
# 2-4 万年カレンダープログラム
import lib


print()
std = input('DATE ? ')
dy = float(std)
dt = 90000.0

jd, yy, mm, dd, hh, ms, ss = lib.mjd(dy, dt)

print()
print('%4d 年%2d 月' % (yy, mm))
print(lib.tab(7) + ' SU MO TU WE TH FR SA')

f = mm
i = 0
while i < 31: 
    n = (jd - 4.0) / 7.0
    no = 7 * (n - int(n))
    no = int(no + 0.1)

    yy, mm, dd = lib.jdate(jd, lib.T)

    if mm != f:
        break

    if no == 0:
        print(lib.tab(7), end='')
        print('%3d' % (dd), end='')
    else:                   
        if i == 0:
            print(lib.tab(no * 3 + 7), end='')

        if no == 6:
            print('%3d' % (dd))
        else:
            print('%3d' % (dd), end='')

    i += 1 
    jd += 1

print()
print()

例題 2022年5月のカレンダーを表示させてみよう。

DATE ? 20220501

2022 年 5 月
        SU MO TU WE TH FR SA
         1  2  3  4  5  6  7
         8  9 10 11 12 13 14
        15 16 17 18 19 20 21
        22 23 24 25 26 27 28
        29 30 31

PHPで再現

N-BASICでの流れをPHPのgoto文を使って再現してあります。ただ、N-BASICで実行したときに同じになるかどうかは未確認です。

<?php
// 万年カレンダープログラム
require "./lib.php";

echo "\n";
echo "DATE ? ";
$std = trim(fgets(STDIN));
$dy = $std;
$dt = 90000;

list($jd, $yy, $mm) = mjd($dy, $dt);

echo "\n";
echo sprintf("%4d 年%2d 月\n", $yy, $mm);
echo tab(7) . " SU MO TU WE TH FR SA\n";
$f = $mm;
$i = 0;

L260:
$n = ($jd - 4.0) / 7.0;
$no = 7 * ($n - intval($n));
$no = intval($no + 0.1);

list($yy, $mm, $dd) = jdate($jd, $t);

if ($mm != $f) {
	goto L370;
}
if ($no == 0) {
	echo tab(7);
}
	
if ($i == 0) {
	echo tab($no * 3 + 7);
}
if ($no == 6) {
	echo sprintf("%3d\n", $dd);
       goto L350;
}

echo sprintf("%3d", $dd);

L350:
$i++;
if ($i < 31) {
    $jd++;
    goto L260;
}

L370:
echo "\n\n\n";
DATE ? 20220501

2022 年 5 月
        SU MO TU WE TH FR SA
                1  2  3  4  5  6  7
         8  9 10 11 12 13 14
        15 16 17 18 19 20 21
        22 23 24 25 26 27 28
        29 30 31