Add Ontario holiday

testing ip
This commit is contained in:
Muhan Li 2024-10-18 13:54:00 -04:00
parent 94584e0835
commit 4776475589
8 changed files with 252 additions and 2 deletions

View File

@ -32,6 +32,14 @@ jobs:
shell: bash shell: bash
run: python crawler.py run: python crawler.py
- name: Run global scripts
shell: bash
run: |
for script in global/*/main.py; do
cd $(dirname $script)
python $(basename $script)
done
- name: Setup Haskell and Cabal - name: Setup Haskell and Cabal
uses: haskell-actions/setup@v2 uses: haskell-actions/setup@v2
with: with:
@ -44,10 +52,18 @@ jobs:
- name: Generate ICS files - name: Generate ICS files
run: cabal run run: cabal run
- name: Generate global data
shell: bash
run: |
for script in global/*/deploy.sh; do
cd $(dirname $script)
bash $(basename $script) 2>/dev/null
done
- name: Commit changes - name: Commit changes
uses: stefanzweifel/git-auto-commit-action@v5 uses: stefanzweifel/git-auto-commit-action@v5
with: with:
file_pattern: README.md docs/* data/* file_pattern: README.md data/* global/*/data/* docs/* docs/global/*/*
commit_message: update calendar data automatically commit_message: update calendar data automatically
commit_user_name: Muhan Li commit_user_name: Muhan Li
commit_user_email: 77625954+muhav@users.noreply.github.com commit_user_email: 77625954+muhav@users.noreply.github.com

View File

@ -33,6 +33,14 @@ jobs:
shell: bash shell: bash
run: python crawler.py run: python crawler.py
- name: Run global scripts
shell: bash
run: |
for script in global/*/main.py; do
cd $(dirname $script)
python $(basename $script)
done
parser: parser:
name: Parser Dry Run name: Parser Dry Run
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -0,0 +1,12 @@
// Ontario Public Holidays in 2022
// I hope ChatGPT gets the dates correct
元旦_New_Year's_Day;2022.1.3;2022.1.1-2022.1.3
家庭日_Family_Day;2022.2.21;2022.2.19-2022.2.21
耶稣受难日_Good_Friday;2022.4.15;2022.4.15-2022.4.17
维多利亚日_Victoria_Day;2022.5.23;2022.5.21-2022.5.23
国庆节_Canada_Day;2022.7.1;2022.7.1-2022.7.3
劳动节_Labour_Day;2022.9.5;2022.9.3-2022.9.5
感恩节_Thanksgiving;2022.10.10;2022.10.8-2022.10.10
圣诞节_Christmas_Day;2022.12.26;2022.12.24-2022.12.27
节礼日_Boxing_Day;2022.12.27;

View File

@ -0,0 +1,12 @@
// Ontario Public Holidays in 2023
// I hope ChatGPT gets the dates correct
元旦_New_Year's_Day;2023.1.2;2022.12.31-2023.1.2
家庭日_Family_Day;2023.2.20;2023.2.18-2023.2.20
耶稣受难日_Good_Friday;2023.4.7;2023.4.7-2023.4.9
维多利亚日_Victoria_Day;2023.5.22;2023.5.20-2023.5.22
国庆节_Canada_Day;2023.7.3;2023.7.1-2023.7.3
劳动节_Labour_Day;2023.9.4;2023.9.2-2023.9.4
感恩节_Thanksgiving;2023.10.9;2023.10.7-2023.10.9
圣诞节_Christmas_Day;2023.12.25;2023.12.23-2023.12.26
节礼日_Boxing_Day;2023.12.26;

View File

@ -0,0 +1,12 @@
// Ontario Public Holidays in 2024
// I hope ChatGPT gets the dates correct
元旦_New_Year's_Day;2024.1.1;2023.12.30-2024.1.1
家庭日_Family_Day;2024.2.19;2024.2.17-2024.2.19
耶稣受难日_Good_Friday;2024.3.29;2024.3.29-2024.3.31
维多利亚日_Victoria_Day;2024.5.20;2024.5.18-2024.5.20
国庆节_Canada_Day;2024.7.1;2024.6.29-2024.7.1
劳动节_Labour_Day;2024.9.2;2024.8.31-2024.9.2
感恩节_Thanksgiving;2024.10.14;2024.10.12-2024.10.14
圣诞节_Christmas_Day;2024.12.25;2024.12.25-2024.12.26
节礼日_Boxing_Day;2024.12.26;

23
global/ca_on/deploy.sh Normal file
View File

@ -0,0 +1,23 @@
# To make it simple, copy the parser script
# to the current directory, and I only need
# to modify the titles of the output files.
mkdir docs
mkdir -p ../../docs/global/ca_on
cp -r ../../parser.cabal .
cp -r ../../parser .
sed -i \
-e 's/Chinese Holidays/Ontario Statutory Holidays/' \
-e 's/titleStatus status/"加拿大安大略省公共假日"/' \
-e 's/name ++ show status/unwords name_en/' \
-e 's/show status/name_cn ++ " "/' \
-e 's/0xa95511fe/0xca4ada04;name_cn:name_en=splitOn "_" name/' \
-e 's/import/import Data.List.Split (splitOn);import/' \
./parser/Main/Output.hs
cabal build
cabal run
mv docs/rest.ics ../../docs/global/ca_on/main.ics
mv docs/work.ics ../../docs/global/ca_on/rest.ics

166
global/ca_on/main.py Normal file
View File

@ -0,0 +1,166 @@
"""
Generate the public holidays in Ontario for the next year
Thanks to ChatGPT and Copilot for the code
"""
import datetime
from dateutil.easter import easter
class Holiday:
"""节假日"""
def __init__(self, name_cn, name_en, date):
self.name_cn = name_cn
self.name_en = name_en
self.date = date
self.long_weekend_dates = None
def __str__(self):
"""格式化 debug 输出"""
return f"{self.name_cn}: {self.format_date(self.date)}"
@staticmethod
def format_date(date):
"""格式化日期为 data.txt 的格式"""
return date.strftime('%Y.%-m.%-d')
def get_holidays(year: int) -> list[Holiday]:
"""获取给定年份的节假日"""
holidays = [
# 固定假日
# 元旦 (1月1日)
Holiday("元旦", "New Year's Day", datetime.date(year, 1, 1)),
# 劳动节 (5月1日)
Holiday("国庆节", "Canada Day", datetime.date(year, 7, 1)),
# 圣诞节 (12月25日)
Holiday("圣诞节", "Christmas Day", datetime.date(year, 12, 25)),
# 节礼日 (12月26日)
Holiday("节礼日", "Boxing Day", datetime.date(year, 12, 26)),
# 变动假日
# 耶稣受难日复活节前2天
Holiday("耶稣受难日", "Good Friday", easter(year) - datetime.timedelta(days=2)),
# 维多利亚日5月最后一个周一
Holiday("维多利亚日", "Victoria Day", get_last_monday(datetime.date(year, 5, 25))),
# 劳动节9月的第一个周一
Holiday("劳动节", "Labour Day", get_first_monday(datetime.date(year, 9, 1))),
# 感恩节10月的第二个周一
Holiday("感恩节", "Thanksgiving", get_second_monday(datetime.date(year, 10, 1))),
# 家庭日2月的第三个周一
Holiday("家庭日", "Family Day", get_third_monday(datetime.date(year, 2, 1))),
]
# 处理假日如果落在周末的情况
adjust_for_weekends(holidays)
connect_long_weekends(holidays)
return holidays
def get_first_monday(date):
"""获取给定日期所在月的第一个星期一"""
while date.weekday() != 0:
date += datetime.timedelta(days=1)
return date
def get_second_monday(date):
"""获取给定日期所在月的第二个星期一"""
first_monday = get_first_monday(date)
return first_monday + datetime.timedelta(days=7)
def get_third_monday(date):
"""获取给定日期所在月的第三个星期一"""
first_monday = get_first_monday(date)
return first_monday + datetime.timedelta(days=14)
def get_last_monday(date):
"""获取给定日期所在月的最后一个星期一"""
while date.weekday() != 0:
date -= datetime.timedelta(days=1)
return date
def adjust_for_weekends(holidays: list[Holiday]):
"""如果假日落在周末,将假日顺延到下一个工作日,特殊处理圣诞节和节礼日"""
boxing_day_delta = 0
for holiday in holidays:
# 特殊处理圣诞节和节礼日
if holiday.name_cn == "圣诞节" and holiday.date.weekday() == 5:
# 圣诞节在周六, 节礼日在周日
holiday.date += datetime.timedelta(days=2)
boxing_day_delta = 2
elif holiday.name_cn == "圣诞节" and holiday.date.weekday() == 6:
# 圣诞节在周日, 节礼日在周一
holiday.date += datetime.timedelta(days=1)
boxing_day_delta = 1
elif holiday.name_cn == "节礼日" and holiday.date.weekday() == 5:
# 节礼日在周六
holiday.date += datetime.timedelta(days=2)
elif holiday.name_cn == "节礼日":
holiday.date += datetime.timedelta(days=boxing_day_delta)
else:
# 其他假期处理
if holiday.date.weekday() == 5: # 如果是假日落在周六
holiday.date += datetime.timedelta(days=2)
elif holiday.date.weekday() == 6: # 如果是假日落在周日
holiday.date += datetime.timedelta(days=1)
def connect_long_weekends(holidays: list[Holiday]):
"""将连续的假期连接起来"""
boxing_day = next(h.date for h in holidays if h.name_cn == "节礼日")
for holiday in holidays:
dates = [holiday.date]
if holiday.name_cn == "节礼日":
continue
if holiday.name_cn == "圣诞节":
dates.append(boxing_day)
long_weekend_start = holiday.date
while is_weekend(prev_day := long_weekend_start - datetime.timedelta(days=1), dates):
long_weekend_start = prev_day
long_weekend_end = holiday.date
while is_weekend(next_day := long_weekend_end + datetime.timedelta(days=1), dates):
long_weekend_end = next_day
holiday.long_weekend_dates = (
Holiday.format_date(long_weekend_start),
Holiday.format_date(long_weekend_end),
)
def is_weekend(date, extra_holidays=None):
"""判断给定日期是否是周末或者公共假日"""
return date.weekday() >= 5 or (extra_holidays and date in extra_holidays)
def main(year=None):
"""生成下一年的节假日数据"""
next_year = year if year else datetime.datetime.now().year + 1
print(f"Generating Ontario holidays for {next_year}")
holidays = get_holidays(next_year)
holidays.sort(key=lambda x: x.date)
data = (f"// Ontario Public Holidays in {next_year}\n"
f"// I hope ChatGPT gets the dates correct\n\n")
for holiday in holidays:
print(holiday)
title = f"{holiday.name_cn} {holiday.name_en}".replace(' ', '_')
data += (f"{title};{Holiday.format_date(holiday.date)};"
f"{f'{d[0]}-{d[1]}' if (d := holiday.long_weekend_dates) else ''}\n") # pylint: disable=unsubscriptable-object
with open(f"./data/{next_year}.txt", "w", encoding='utf-8') as f:
f.write(data)
if __name__ == '__main__':
main()

View File

@ -1 +1,2 @@
requests~=2.28.1 requests~=2.32.3
python-dateutil~=2.9.0