123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- #!/usr/bin/env python3
- """Script for updating data. """
- import argparse
- import json
- import os
- import re
- import subprocess
- from datetime import datetime, timedelta, tzinfo
- from tempfile import mkstemp
- from typing import Iterator
- from zipfile import ZipFile
- from tqdm import tqdm
- from fetch import CustomJSONEncoder, fetch_holiday
- from generate_ics import generate_ics
- from filetools import workspace_path
- class ChinaTimezone(tzinfo):
- """Timezone of china."""
- def tzname(self, dt):
- return "UTC+8"
- def utcoffset(self, dt):
- return timedelta(hours=8)
- def dst(self, dt):
- return timedelta()
- def update_data(year: int) -> Iterator[str]:
- """Update and store data for a year."""
- json_filename = workspace_path(f"{year}.json")
- ics_filename = workspace_path(f"{year}.ics")
- with open(json_filename, "w", encoding="utf-8", newline="\n") as f:
- data = fetch_holiday(year)
- json.dump(
- dict(
- (
- (
- "$schema",
- "https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/schema.json",
- ),
- (
- "$id",
- f"https://raw.githubusercontent.com/NateScarlet/holiday-cn/master/{year}.json",
- ),
- *data.items(),
- )
- ),
- f,
- indent=4,
- ensure_ascii=False,
- cls=CustomJSONEncoder,
- )
- yield json_filename
- generate_ics(data["days"], ics_filename)
- yield ics_filename
- def update_main_ics(fr_year, to_year):
- all_days = []
- for year in range(fr_year, to_year + 1):
- filename = workspace_path(f"{year}.json")
- if not os.path.isfile(filename):
- continue
- with open(filename, "r", encoding="utf8") as inf:
- data = json.loads(inf.read())
- all_days.extend(data.get("days"))
- filename = workspace_path("holiday-cn.ics")
- generate_ics(
- all_days,
- filename,
- )
- return filename
- def main():
- parser = argparse.ArgumentParser()
- parser.add_argument(
- "--all",
- action="store_true",
- help="Update all years since 2007, default is this year and next year",
- )
- parser.add_argument(
- "--release",
- action="store_true",
- help="create new release if repository data is not up to date",
- )
- args = parser.parse_args()
- now = datetime.now(ChinaTimezone())
- is_release = args.release
- filenames = []
- progress = tqdm(range(2007 if args.all else now.year, now.year + 2))
- for i in progress:
- progress.set_description(f"Updating {i} data")
- filenames += list(update_data(i))
- progress.set_description("Updating holiday-cn.ics")
- filenames.append(update_main_ics(now.year - 4, now.year + 1))
- print("")
- subprocess.run(["git", "add", *filenames], check=True)
- diff = subprocess.run(
- ["git", "diff", "--stat", "--cached", "*.json", "*.ics"],
- check=True,
- stdout=subprocess.PIPE,
- encoding="utf-8",
- ).stdout
- if not diff:
- print("Already up to date.")
- return
- if not is_release:
- print("Updated repository data, skip release since not specified `--release`")
- return
- subprocess.run(
- [
- "git",
- "commit",
- "-m",
- "chore(release): update holiday data",
- "-m",
- "[skip ci]",
- ],
- check=True,
- )
- subprocess.run(["git", "push"], check=True)
- tag = now.strftime("%Y.%m.%d")
- temp_note_fd, temp_note_name = mkstemp()
- with open(temp_note_fd, "w", encoding="utf-8") as f:
- f.write(tag + "\n\n```diff\n" + diff + "\n```\n")
- os.makedirs(workspace_path("dist"), exist_ok=True)
- zip_path = workspace_path("dist", f"holiday-cn-{tag}.zip")
- pack_data(zip_path)
- subprocess.run(
- [
- "gh",
- "release",
- "create",
- "-F",
- temp_note_name,
- tag,
- f"{zip_path}#JSON数据",
- ],
- check=True,
- )
- os.unlink(temp_note_name)
- def pack_data(file):
- """Pack data json in zip file."""
- zip_file = ZipFile(file, "w")
- for i in os.listdir(workspace_path()):
- if not re.match(r"\d+\.json", i):
- continue
- zip_file.write(workspace_path(i), i)
- if __name__ == "__main__":
- main()
|