timmy revidoval tento gist 10 months ago. Přejít na revizi
Žádné změny
timmy revidoval tento gist 10 months ago. Přejít na revizi
Žádné změny
timmy revidoval tento gist 11 months ago. Přejít na revizi
Žádné změny
timmy revidoval tento gist 11 months ago. Přejít na revizi
1 file changed, 44 insertions, 14 deletions
holiday_api_checker.py
| @@ -1,20 +1,41 @@ | |||
| 1 | 1 | import requests | |
| 2 | + | import os | |
| 3 | + | import json | |
| 2 | 4 | ||
| 3 | 5 | class HolidayAPI: | |
| 4 | - | def __init__(self, base_url): | |
| 6 | + | def __init__(self, base_url, cache_dir="cache"): | |
| 5 | 7 | """ | |
| 6 | 8 | Initialize the HolidayAPI class. | |
| 7 | 9 | :param base_url: The base URL for the API endpoint. | |
| 10 | + | :param cache_dir: Directory to store cached data. | |
| 8 | 11 | """ | |
| 9 | 12 | self.base_url = base_url | |
| 13 | + | self.cached_holidays = {} | |
| 14 | + | self.cache_dir = cache_dir | |
| 15 | + | if not os.path.exists(self.cache_dir): | |
| 16 | + | os.makedirs(self.cache_dir) | |
| 17 | + | ||
| 18 | + | def _get_cache_path(self, page, size): | |
| 19 | + | """ | |
| 20 | + | Generate the cache file path for a given page and size. | |
| 21 | + | :param page: The page number. | |
| 22 | + | :param size: The size of the page. | |
| 23 | + | :return: Path to the cache file. | |
| 24 | + | """ | |
| 25 | + | return os.path.join(self.cache_dir, f"holidays_page{page}_size{size}.json") | |
| 10 | 26 | ||
| 11 | 27 | def get_holidays(self, page=0, size=10): | |
| 12 | 28 | """ | |
| 13 | - | Fetch holiday data from the API. | |
| 29 | + | Fetch holiday data from the API or cache. | |
| 14 | 30 | :param page: The page number to fetch. | |
| 15 | 31 | :param size: The number of records per page. | |
| 16 | 32 | :return: A list of holiday data dictionaries. | |
| 17 | 33 | """ | |
| 34 | + | cache_path = self._get_cache_path(page, size) | |
| 35 | + | if os.path.exists(cache_path): | |
| 36 | + | with open(cache_path, "r", encoding="utf-8") as cache_file: | |
| 37 | + | return json.load(cache_file) | |
| 38 | + | ||
| 18 | 39 | url = f"{self.base_url}?page={page}&size={size}" | |
| 19 | 40 | headers = { | |
| 20 | 41 | 'accept': 'application/json' | |
| @@ -22,16 +43,23 @@ class HolidayAPI: | |||
| 22 | 43 | response = requests.get(url, headers=headers) | |
| 23 | 44 | ||
| 24 | 45 | if response.status_code == 200: | |
| 25 | - | return response.json() | |
| 46 | + | data = response.json() | |
| 47 | + | with open(cache_path, "w", encoding="utf-8") as cache_file: | |
| 48 | + | json.dump(data, cache_file, ensure_ascii=False, indent=4) | |
| 49 | + | return data | |
| 26 | 50 | else: | |
| 27 | 51 | response.raise_for_status() | |
| 28 | 52 | ||
| 29 | 53 | def get_holidays_by_year(self, year): | |
| 30 | 54 | """ | |
| 31 | 55 | Fetch holiday data for a specific year. | |
| 56 | + | If the data is already cached, it returns from the cache. | |
| 32 | 57 | :param year: The year for which to fetch holidays. | |
| 33 | 58 | :return: A list of holiday data dictionaries for the given year. | |
| 34 | 59 | """ | |
| 60 | + | if year in self.cached_holidays: | |
| 61 | + | return self.cached_holidays[year] | |
| 62 | + | ||
| 35 | 63 | all_holidays = [] | |
| 36 | 64 | page = 0 | |
| 37 | 65 | while True: | |
| @@ -41,7 +69,12 @@ class HolidayAPI: | |||
| 41 | 69 | all_holidays.extend(data) | |
| 42 | 70 | page += 1 | |
| 43 | 71 | ||
| 44 | - | return [holiday for holiday in all_holidays if holiday.get("year") == str(year)] | |
| 72 | + | filtered_holidays = [ | |
| 73 | + | holiday for holiday in all_holidays | |
| 74 | + | if holiday.get("year") == str(year) and holiday.get("date")[4:] != "0903" | |
| 75 | + | ] | |
| 76 | + | self.cached_holidays[year] = filtered_holidays | |
| 77 | + | return filtered_holidays | |
| 45 | 78 | ||
| 46 | 79 | def is_holiday(self, date): | |
| 47 | 80 | """ | |
| @@ -49,15 +82,13 @@ class HolidayAPI: | |||
| 49 | 82 | :param date: The date to check in YYYYMMDD format. | |
| 50 | 83 | :return: True if the date is a holiday, False otherwise. | |
| 51 | 84 | """ | |
| 52 | - | page = 0 | |
| 53 | - | while True: | |
| 54 | - | data = self.get_holidays(page=page, size=100) | |
| 55 | - | if not data: | |
| 56 | - | break | |
| 57 | - | for holiday in data: | |
| 58 | - | if holiday.get("date") == date and holiday.get("isholiday") == "是": | |
| 59 | - | return True | |
| 60 | - | page += 1 | |
| 85 | + | year = date[:4] | |
| 86 | + | if year not in self.cached_holidays: | |
| 87 | + | self.get_holidays_by_year(year) | |
| 88 | + | ||
| 89 | + | for holiday in self.cached_holidays[year]: | |
| 90 | + | if holiday.get("date") == date and holiday.get("isholiday") == "是": | |
| 91 | + | return True | |
| 61 | 92 | return False | |
| 62 | 93 | ||
| 63 | 94 | class Holiday: | |
| @@ -104,7 +135,6 @@ if __name__ == "__main__": | |||
| 104 | 135 | print(holiday) | |
| 105 | 136 | ||
| 106 | 137 | # Check if a specific date is a holiday | |
| 107 | - | # specific_date = "20250101" | |
| 108 | 138 | specific_date = "20250102" | |
| 109 | 139 | print(f"Is {specific_date} a holiday? {api.is_holiday(specific_date)}") | |
| 110 | 140 | ||
timmy revidoval tento gist 11 months ago. Přejít na revizi
1 file changed, 110 insertions
holiday_api_checker.py(vytvořil soubor)
| @@ -0,0 +1,110 @@ | |||
| 1 | + | import requests | |
| 2 | + | ||
| 3 | + | class HolidayAPI: | |
| 4 | + | def __init__(self, base_url): | |
| 5 | + | """ | |
| 6 | + | Initialize the HolidayAPI class. | |
| 7 | + | :param base_url: The base URL for the API endpoint. | |
| 8 | + | """ | |
| 9 | + | self.base_url = base_url | |
| 10 | + | ||
| 11 | + | def get_holidays(self, page=0, size=10): | |
| 12 | + | """ | |
| 13 | + | Fetch holiday data from the API. | |
| 14 | + | :param page: The page number to fetch. | |
| 15 | + | :param size: The number of records per page. | |
| 16 | + | :return: A list of holiday data dictionaries. | |
| 17 | + | """ | |
| 18 | + | url = f"{self.base_url}?page={page}&size={size}" | |
| 19 | + | headers = { | |
| 20 | + | 'accept': 'application/json' | |
| 21 | + | } | |
| 22 | + | response = requests.get(url, headers=headers) | |
| 23 | + | ||
| 24 | + | if response.status_code == 200: | |
| 25 | + | return response.json() | |
| 26 | + | else: | |
| 27 | + | response.raise_for_status() | |
| 28 | + | ||
| 29 | + | def get_holidays_by_year(self, year): | |
| 30 | + | """ | |
| 31 | + | Fetch holiday data for a specific year. | |
| 32 | + | :param year: The year for which to fetch holidays. | |
| 33 | + | :return: A list of holiday data dictionaries for the given year. | |
| 34 | + | """ | |
| 35 | + | all_holidays = [] | |
| 36 | + | page = 0 | |
| 37 | + | while True: | |
| 38 | + | data = self.get_holidays(page=page, size=100) | |
| 39 | + | if not data: | |
| 40 | + | break | |
| 41 | + | all_holidays.extend(data) | |
| 42 | + | page += 1 | |
| 43 | + | ||
| 44 | + | return [holiday for holiday in all_holidays if holiday.get("year") == str(year)] | |
| 45 | + | ||
| 46 | + | def is_holiday(self, date): | |
| 47 | + | """ | |
| 48 | + | Check if a specific date is a holiday. | |
| 49 | + | :param date: The date to check in YYYYMMDD format. | |
| 50 | + | :return: True if the date is a holiday, False otherwise. | |
| 51 | + | """ | |
| 52 | + | page = 0 | |
| 53 | + | while True: | |
| 54 | + | data = self.get_holidays(page=page, size=100) | |
| 55 | + | if not data: | |
| 56 | + | break | |
| 57 | + | for holiday in data: | |
| 58 | + | if holiday.get("date") == date and holiday.get("isholiday") == "是": | |
| 59 | + | return True | |
| 60 | + | page += 1 | |
| 61 | + | return False | |
| 62 | + | ||
| 63 | + | class Holiday: | |
| 64 | + | def __init__(self, date, year, name, isholiday, holidaycategory, description): | |
| 65 | + | """ | |
| 66 | + | Represent a single holiday entry. | |
| 67 | + | :param date: The date of the holiday in YYYYMMDD format. | |
| 68 | + | :param year: The year of the holiday. | |
| 69 | + | :param name: The name of the holiday (if any). | |
| 70 | + | :param isholiday: Whether it is a holiday ('是' or '否'). | |
| 71 | + | :param holidaycategory: The category of the holiday. | |
| 72 | + | :param description: The description of the holiday. | |
| 73 | + | """ | |
| 74 | + | self.date = date | |
| 75 | + | self.year = year | |
| 76 | + | self.name = name | |
| 77 | + | self.isholiday = isholiday | |
| 78 | + | self.holidaycategory = holidaycategory | |
| 79 | + | self.description = description | |
| 80 | + | ||
| 81 | + | def __repr__(self): | |
| 82 | + | return f"Holiday(date={self.date}, year={self.year}, name={self.name}, " \ | |
| 83 | + | f"isholiday={self.isholiday}, holidaycategory={self.holidaycategory}, " \ | |
| 84 | + | f"description={self.description})" | |
| 85 | + | ||
| 86 | + | # Example usage | |
| 87 | + | if __name__ == "__main__": | |
| 88 | + | api = HolidayAPI("https://data.ntpc.gov.tw/api/datasets/308dcd75-6434-45bc-a95f-584da4fed251/json") | |
| 89 | + | holidays_2025 = api.get_holidays_by_year(2025) | |
| 90 | + | ||
| 91 | + | holidays = [] | |
| 92 | + | for entry in holidays_2025: | |
| 93 | + | holiday = Holiday( | |
| 94 | + | date=entry.get("date"), | |
| 95 | + | year=entry.get("year"), | |
| 96 | + | name=entry.get("name"), | |
| 97 | + | isholiday=entry.get("isholiday"), | |
| 98 | + | holidaycategory=entry.get("holidaycategory"), | |
| 99 | + | description=entry.get("description") | |
| 100 | + | ) | |
| 101 | + | holidays.append(holiday) | |
| 102 | + | ||
| 103 | + | for holiday in holidays: | |
| 104 | + | print(holiday) | |
| 105 | + | ||
| 106 | + | # Check if a specific date is a holiday | |
| 107 | + | # specific_date = "20250101" | |
| 108 | + | specific_date = "20250102" | |
| 109 | + | print(f"Is {specific_date} a holiday? {api.is_holiday(specific_date)}") | |
| 110 | + | ||