マイコン宇宙講座-万年カレンダー
年月を指定すると、その月のカレンダーを表示します。万年カレンダーを計算で作成していくには、まず、その月の最初の日の曜日番号とユリウス日を求め、そこから、その月の日数まで+1日ずつしていきます。ユリウス日から日を求めるにはサブルーチンjdateを呼びます。曜日によって日を表示する位置も求めておきます。このプログラムで求める曜日番号は次のとおりです。
曜日番号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
曜日 | 日曜日 | 月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日 |
曜日番号 = (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