timmy a révisé ce gist 10 months ago. Aller à la révision
Aucun changement
timmy a révisé ce gist 10 months ago. Aller à la révision
Aucun changement
timmy a révisé ce gist 11 months ago. Aller à la révision
Aucun changement
timmy a révisé ce gist 11 months ago. Aller à la révision
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 a révisé ce gist 11 months ago. Aller à la révision
1 file changed, 110 insertions
holiday_api_checker.py(fichier créé)
| @@ -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 | + | ||