[Python] 指定した年の13日の金曜日がある月を返すプログラム 前編

私たちホラー映画好きにとってそわそわしてしまう日が年に何回かあります。
その中のひとつが「13日の金曜日」です。
今回は、年を指定したらその年の13日の金曜日を含む月を返すプログラムを作ってみます。

# 13日の金曜日がある月を見つける
どの月に13日の金曜日（以下「13金」）が含まれるかは、その年の任意の日付の曜日と、その年が閏年かどうかの2点が定まることで求めることができます。
例として、元日が月曜日で閏年である2024年の13金は9月と12月にあるのに対して、同じく元日が月曜日でも閏年ではない2018年の13金は4月と7月にあります。
| 閏年か | 元日の曜日 | 13金がある月 |
|:-:|:-:|:-:|
|True|日曜日|1月、4月、7月|
|True   |月曜日|9月、12月|
|True   |火曜日|6月|
|True   |水曜日|3月、11月|
|True   |木曜日|2月、8月|
|True   |金曜日|5月|
|True   |土曜日|10月|
|False|日曜日|1月、10月|
|False   |月曜日|4月、7月|
|False   |火曜日|9月、12月|
|False   |水曜日|6月|
|False   |木曜日|2月、3月、11月|
|False   |金曜日|8月|
|False   |土曜日|5月|

## コード全体
```python:get_fridays_the_13th.py
import calendar
import datetime

# 対象の年を問い、変数yearに整数として格納する
print("What year?")
year = int(input())

# 閏年かどうか判定する
is_leap = calendar.isleap(year)
# 対象年の元日の曜日を求める
dt = datetime.datetime(year,1,1)
weekday = dt.strftime('%A')

print("Friday the 13th appears on", end = ' ')
# 閏年の場合の判定
if is_leap is True:
    if weekday == 'Sunday':
        print("January, April and July.")
    elif weekday == 'Monday':
        print("September and December.")
    elif weekday == 'Tuesday':
        print("June only.")
    elif weekday == 'Wednesday':
        print("March and November.")
    elif weekday == 'Thursday':
        print("February and August.")
    elif weekday == 'Friday':
        print("May only.")
    elif weekday == 'Saturday':
        print("October only.")

# 閏年ではない場合の判定
if is_leap is False:
    if weekday == 'Sunday':
        print("January and October.")
    elif weekday == 'Monday':
        print("April and July.")
    elif weekday == 'Tuesday':
        print("September and December.")
    elif weekday == 'Wednesday':
        print("June only.")
    elif weekday == 'Thursday':
        print("February, March and November.")
    elif weekday == 'Friday':
        print("August only.")
    elif weekday == 'Saturday':
        print("May only.")

```

## 各パート説明
```python:get_fridays_the_13th.py 1/3
import calendar
import datetime

# 対象の年を問い、変数yearに整数として格納する
print("What year?")
year = int(input())
```
閏年の判定をするために calendar モジュールをインポートします。
日付の計算をするために datetime モジュールをインポートします。
input変数の戻り値は数値であっても文字列型 (str) になるので整数型 (int) に変換します。

```python:get_fridays_the_13th.py 2/3
# 閏年かどうか判定する
is_leap = calendar.isleap(year)
# 対象年の元日の曜日を求める
dt = datetime.datetime(year,1,1)
weekday = dt.strftime('%A')
```
上述の表にしたがって、閏年かどうか（2通り） × 元日の曜日（7通り）の計14通りの回答を用意します。
strftime で与えられた日付の曜日を返します。
'%A'は曜日のフルネームを英語で返します（'Sunday'や'Monday'など）。結果を変数 weekday に格納します。
```python:get_fridays_the_13th.py 3/3
print("Friday the 13th appears on", end = ' ')
# 閏年の場合の判定
if is_leap is True:
    if weekday == 'Sunday':
        print("January, April and July.")
    elif weekday == 'Monday':
        print("September and December.")
    elif weekday == 'Tuesday':
        print("June only.")
    elif weekday == 'Wednesday':
        print("March and November.")
    elif weekday == 'Thursday':
        print("February and August.")
    elif weekday == 'Friday':
        print("May only.")
    elif weekday == 'Saturday':
        print("October only.")

# 閏年ではない場合の判定
if is_leap is False:
    if weekday == 'Sunday':
        print("January and October.")
    elif weekday == 'Monday':
        print("April and July.")
    elif weekday == 'Tuesday':
        print("September and December.")
    elif weekday == 'Wednesday':
        print("June only.")
    elif weekday == 'Thursday':
        print("February, March and November.")
    elif weekday == 'Friday':
        print("August only.")
    elif weekday == 'Saturday':
        print("May only.")
```
変数 weekday に格納された曜日名（'Monday'など）に応じて、あらかじめ調べてある13金のある月名を表示します。

と、がんばってコードを書いてみたものの、このコードには問題があります。
+ 閏年の場合とかそうでない場合とか結局人力で結果を用意している。
+ ある皇帝が「俺の名前の月を追加する」などと言い出して月の数が増えた場合（減った場合も）に使えないコードになってしまう。
+ 曜日の増減があった場合も同様。

人力で準備するところを極力排除し、かつカレンダーに変更があった場合にも対応できるようにしたいと思います。
後編につづく。