Files
Time-Series-Analysis/venv/lib/python3.11/site-packages/holidays/registry.py
2025-08-01 04:33:03 -04:00

361 lines
15 KiB
Python

# holidays
# --------
# A fast, efficient Python library for generating country, province and state
# specific sets of holidays on the fly. It aims to make determining whether a
# specific date is a holiday as fast and flexible as possible.
#
# Authors: Vacanza Team and individual contributors (see CONTRIBUTORS file)
# dr-prodigy <dr.prodigy.github@gmail.com> (c) 2017-2023
# ryanss <ryanssdev@icloud.com> (c) 2014-2017
# Website: https://github.com/vacanza/holidays
# License: MIT (see LICENSE file)
import importlib
from collections.abc import Iterable
from threading import RLock
from typing import Any, Optional, Union
from holidays.holiday_base import HolidayBase
RegistryDict = dict[str, tuple[str, ...]]
COUNTRIES: RegistryDict = {
"afghanistan": ("Afghanistan", "AF", "AFG"),
"aland_islands": ("AlandIslands", "AX", "ALA", "HolidaysAX"),
"albania": ("Albania", "AL", "ALB"),
"algeria": ("Algeria", "DZ", "DZA"),
"american_samoa": ("AmericanSamoa", "AS", "ASM", "HolidaysAS"),
"andorra": ("Andorra", "AD", "AND"),
"angola": ("Angola", "AO", "AGO"),
"anguilla": ("Anguilla", "AI", "AIA"),
"antigua_and_barbuda": ("AntiguaAndBarbuda", "AG", "ATG"),
"argentina": ("Argentina", "AR", "ARG"),
"armenia": ("Armenia", "AM", "ARM"),
"aruba": ("Aruba", "AW", "ABW"),
"australia": ("Australia", "AU", "AUS"),
"austria": ("Austria", "AT", "AUT"),
"azerbaijan": ("Azerbaijan", "AZ", "AZE"),
"bahamas": ("Bahamas", "BS", "BHS"),
"bahrain": ("Bahrain", "BH", "BAH"),
"bangladesh": ("Bangladesh", "BD", "BGD"),
"barbados": ("Barbados", "BB", "BRB"),
"belarus": ("Belarus", "BY", "BLR"),
"belgium": ("Belgium", "BE", "BEL"),
"belize": ("Belize", "BZ", "BLZ"),
"benin": ("Benin", "BJ", "BEN"),
"bermuda": ("Bermuda", "BM", "BMU"),
"bolivia": ("Bolivia", "BO", "BOL"),
"bonaire_sint_eustatius_and_saba": ("BonaireSintEustatiusAndSaba", "BQ", "BES"),
"bosnia_and_herzegovina": ("BosniaAndHerzegovina", "BA", "BIH"),
"botswana": ("Botswana", "BW", "BWA"),
"brazil": ("Brazil", "BR", "BRA"),
"british_virgin_islands": ("BritishVirginIslands", "VG", "VGB"),
"brunei": ("Brunei", "BN", "BRN"),
"bulgaria": ("Bulgaria", "BG", "BLG"),
"burkina_faso": ("BurkinaFaso", "BF", "BFA"),
"burundi": ("Burundi", "BI", "BDI"),
"cabo_verde": ("CaboVerde", "CV", "CPV"),
"cambodia": ("Cambodia", "KH", "KHM"),
"cameroon": ("Cameroon", "CM", "CMR"),
"canada": ("Canada", "CA", "CAN"),
"cayman_islands": ("CaymanIslands", "KY", "CYM"),
"central_african_republic": ("CentralAfricanRepublic", "CF", "CAF"),
"chad": ("Chad", "TD", "TCD"),
"chile": ("Chile", "CL", "CHL"),
"china": ("China", "CN", "CHN"),
"christmas_island": ("ChristmasIsland", "CX", "CXR"),
"cocos_islands": ("CocosIslands", "CC", "CCK"),
"colombia": ("Colombia", "CO", "COL"),
"congo": ("Congo", "CG", "COG"),
"cook_islands": ("CookIslands", "CK", "COK"),
"costa_rica": ("CostaRica", "CR", "CRI"),
"croatia": ("Croatia", "HR", "HRV"),
"cuba": ("Cuba", "CU", "CUB"),
"curacao": ("Curacao", "CW", "CUW"),
"cyprus": ("Cyprus", "CY", "CYP"),
"czechia": ("Czechia", "CZ", "CZE"),
"denmark": ("Denmark", "DK", "DNK"),
"djibouti": ("Djibouti", "DJ", "DJI"),
"dominica": ("Dominica", "DM", "DMA"),
"dominican_republic": ("DominicanRepublic", "DO", "DOM"),
"dr_congo": ("DRCongo", "CD", "COD"),
"ecuador": ("Ecuador", "EC", "ECU"),
"egypt": ("Egypt", "EG", "EGY"),
"jordan": ("Jordan", "JO", "JOR"),
"el_salvador": ("ElSalvador", "SV", "SLV"),
"equatorial_guinea": ("EquatorialGuinea", "GQ", "GNQ"),
"estonia": ("Estonia", "EE", "EST"),
"eswatini": ("Eswatini", "SZ", "SZW", "Swaziland"),
"ethiopia": ("Ethiopia", "ET", "ETH"),
"falkland_islands": ("FalklandIslands", "FK", "FLK"),
"faroe_islands": ("FaroeIslands", "FO", "FRO"),
"fiji": ("Fiji", "FJ", "FJI"),
"finland": ("Finland", "FI", "FIN"),
"france": ("France", "FR", "FRA"),
"french_guiana": ("FrenchGuiana", "GF", "GUF", "HolidaysGF"),
"french_polynesia": ("FrenchPolynesia", "PF", "PYF", "HolidaysPF"),
"french_southern_territories": ("FrenchSouthernTerritories", "TF", "ATF", "HolidaysTF"),
"gabon": ("Gabon", "GA", "GAB"),
"georgia": ("Georgia", "GE", "GEO"),
"germany": ("Germany", "DE", "DEU"),
"ghana": ("Ghana", "GH", "GHA"),
"gibraltar": ("Gibraltar", "GI", "GIB"),
"greece": ("Greece", "GR", "GRC"),
"greenland": ("Greenland", "GL", "GRL"),
"grenada": ("Grenada", "GD", "GRD"),
"guadeloupe": ("Guadeloupe", "GP", "GLP", "HolidaysGP"),
"guam": ("Guam", "GU", "GUM", "HolidaysGU"),
"guatemala": ("Guatemala", "GT", "GUA"),
"guernsey": ("Guernsey", "GG", "GGY"),
"guinea": ("Guinea", "GN", "GIN"),
"guyana": ("Guyana", "GY", "GUY"),
"haiti": ("Haiti", "HT", "HTI"),
"honduras": ("Honduras", "HN", "HND"),
"hongkong": ("HongKong", "HK", "HKG"),
"hungary": ("Hungary", "HU", "HUN"),
"iceland": ("Iceland", "IS", "ISL"),
"india": ("India", "IN", "IND"),
"indonesia": ("Indonesia", "ID", "IDN"),
"iran": ("Iran", "IR", "IRN"),
"ireland": ("Ireland", "IE", "IRL"),
"isle_of_man": ("IsleOfMan", "IM", "IMN"),
"israel": ("Israel", "IL", "ISR"),
"italy": ("Italy", "IT", "ITA"),
"ivory_coast": ("IvoryCoast", "CI", "CIV"),
"jamaica": ("Jamaica", "JM", "JAM"),
"japan": ("Japan", "JP", "JPN"),
"jersey": ("Jersey", "JE", "JEY"),
"kazakhstan": ("Kazakhstan", "KZ", "KAZ"),
"kenya": ("Kenya", "KE", "KEN"),
"kuwait": ("Kuwait", "KW", "KWT"),
"kyrgyzstan": ("Kyrgyzstan", "KG", "KGZ"),
"laos": ("Laos", "LA", "LAO"),
"latvia": ("Latvia", "LV", "LVA"),
"lebanon": ("Lebanon", "LB", "LBN"),
"lesotho": ("Lesotho", "LS", "LSO"),
"libya": ("Libya", "LY", "LBY"),
"liechtenstein": ("Liechtenstein", "LI", "LIE"),
"lithuania": ("Lithuania", "LT", "LTU"),
"luxembourg": ("Luxembourg", "LU", "LUX"),
"macau": ("Macau", "MO", "MAC"),
"madagascar": ("Madagascar", "MG", "MDG"),
"malawi": ("Malawi", "MW", "MWI"),
"malaysia": ("Malaysia", "MY", "MYS"),
"maldives": ("Maldives", "MV", "MDV"),
"mali": ("Mali", "ML", "MLI"),
"malta": ("Malta", "MT", "MLT"),
"marshall_islands": ("MarshallIslands", "MH", "MHL", "HolidaysMH"),
"martinique": ("Martinique", "MQ", "MTQ", "HolidaysMQ"),
"mauritania": ("Mauritania", "MR", "MRT"),
"mauritius": ("Mauritius", "MU", "MUS"),
"mayotte": ("Mayotte", "YT", "MYT", "HolidaysYT"),
"mexico": ("Mexico", "MX", "MEX"),
"micronesia": ("Micronesia", "FM", "FSM"),
"moldova": ("Moldova", "MD", "MDA"),
"monaco": ("Monaco", "MC", "MCO"),
"mongolia": ("Mongolia", "MN", "MNG"),
"montenegro": ("Montenegro", "ME", "MNE"),
"montserrat": ("Montserrat", "MS", "MSR"),
"morocco": ("Morocco", "MA", "MOR"),
"mozambique": ("Mozambique", "MZ", "MOZ"),
"namibia": ("Namibia", "NA", "NAM"),
"nauru": ("Nauru", "NR", "NRU"),
"nepal": ("Nepal", "NP", "NPL"),
"netherlands": ("Netherlands", "NL", "NLD"),
"new_caledonia": ("NewCaledonia", "NC", "NCL", "HolidaysNC"),
"new_zealand": ("NewZealand", "NZ", "NZL"),
"nicaragua": ("Nicaragua", "NI", "NIC"),
"niger": ("Niger", "NE", "NER"),
"nigeria": ("Nigeria", "NG", "NGA"),
"niue": ("Niue", "NU", "NIU"),
"norfolk_island": ("NorfolkIsland", "NF", "NFK"),
"north_macedonia": ("NorthMacedonia", "MK", "MKD"),
"northern_mariana_islands": ("NorthernMarianaIslands", "MP", "MNP", "HolidaysMP"),
"norway": ("Norway", "NO", "NOR"),
"oman": ("Oman", "OM", "OMN"),
"pakistan": ("Pakistan", "PK", "PAK"),
"palau": ("Palau", "PW", "PLW"),
"palestine": ("Palestine", "PS", "PSE"),
"panama": ("Panama", "PA", "PAN"),
"papua_new_guinea": ("PapuaNewGuinea", "PG", "PNG"),
"paraguay": ("Paraguay", "PY", "PRY"),
"peru": ("Peru", "PE", "PER"),
"philippines": ("Philippines", "PH", "PHL"),
"poland": ("Poland", "PL", "POL"),
"portugal": ("Portugal", "PT", "PRT"),
"puerto_rico": ("PuertoRico", "PR", "PRI", "HolidaysPR"),
"qatar": ("Qatar", "QA", "QAT"),
"reunion": ("Reunion", "RE", "REU", "HolidaysRE"),
"romania": ("Romania", "RO", "ROU"),
"russia": ("Russia", "RU", "RUS"),
"saint_barthelemy": ("SaintBarthelemy", "BL", "BLM", "HolidaysBL"),
"saint_kitts_and_nevis": ("SaintKittsAndNevis", "KN", "KNA"),
"saint_lucia": ("SaintLucia", "LC", "LCA"),
"saint_martin": ("SaintMartin", "MF", "MAF", "HolidaysMF"),
"saint_pierre_and_miquelon": ("SaintPierreAndMiquelon", "PM", "SPM", "HolidaysPM"),
"saint_vincent_and_the_grenadines": ("SaintVincentAndTheGrenadines", "VC", "VCT"),
"samoa": ("Samoa", "WS", "WSM"),
"san_marino": ("SanMarino", "SM", "SMR"),
"sao_tome_and_principe": ("SaoTomeAndPrincipe", "ST", "STP"),
"saudi_arabia": ("SaudiArabia", "SA", "SAU"),
"senegal": ("Senegal", "SN", "SEN"),
"serbia": ("Serbia", "RS", "SRB"),
"seychelles": ("Seychelles", "SC", "SYC"),
"sierra_leone": ("SierraLeone", "SL", "SLE"),
"singapore": ("Singapore", "SG", "SGP"),
"sint_maarten": ("SintMaarten", "SX", "SXM"),
"slovakia": ("Slovakia", "SK", "SVK"),
"slovenia": ("Slovenia", "SI", "SVN"),
"solomon_islands": ("SolomonIslands", "SB", "SLB"),
"south_africa": ("SouthAfrica", "ZA", "ZAF"),
"south_korea": ("SouthKorea", "KR", "KOR", "Korea"),
"spain": ("Spain", "ES", "ESP"),
"sri_lanka": ("SriLanka", "LK", "LKA"),
"suriname": ("Suriname", "SR", "SUR"),
"svalbard_and_jan_mayen": ("SvalbardAndJanMayen", "SJ", "SJM", "HolidaysSJ"),
"sweden": ("Sweden", "SE", "SWE"),
"switzerland": ("Switzerland", "CH", "CHE"),
"taiwan": ("Taiwan", "TW", "TWN"),
"tanzania": ("Tanzania", "TZ", "TZA"),
"thailand": ("Thailand", "TH", "THA"),
"timor_leste": ("TimorLeste", "TL", "TLS"),
"togo": ("Togo", "TG", "TGO"),
"tokelau": ("Tokelau", "TK", "TKL"),
"tonga": ("Tonga", "TO", "TON"),
"trinidad_and_tobago": ("TrinidadAndTobago", "TT", "TTO"),
"tunisia": ("Tunisia", "TN", "TUN"),
"turkey": ("Turkey", "TR", "TUR"),
"turks_and_caicos_islands": ("TurksAndCaicosIslands", "TC", "TCA"),
"tuvalu": ("Tuvalu", "TV", "TUV"),
"ukraine": ("Ukraine", "UA", "UKR"),
"united_arab_emirates": ("UnitedArabEmirates", "AE", "ARE"),
"united_kingdom": ("UnitedKingdom", "GB", "GBR", "UK"),
"united_states_minor_outlying_islands": (
"UnitedStatesMinorOutlyingIslands",
"UM",
"UMI",
"HolidaysUM",
),
"united_states_virgin_islands": ("UnitedStatesVirginIslands", "VI", "VIR", "HolidaysVI"),
"united_states": ("UnitedStates", "US", "USA"),
"uruguay": ("Uruguay", "UY", "URY"),
"uzbekistan": ("Uzbekistan", "UZ", "UZB"),
"vanuatu": ("Vanuatu", "VU", "VTU"),
"vatican_city": ("VaticanCity", "VA", "VAT"),
"venezuela": ("Venezuela", "VE", "VEN"),
"vietnam": ("Vietnam", "VN", "VNM"),
"wallis_and_futuna": ("WallisAndFutuna", "WF", "WLF", "HolidaysWF"),
"yemen": ("Yemen", "YE", "YEM"),
"zambia": ("Zambia", "ZM", "ZMB"),
"zimbabwe": ("Zimbabwe", "ZW", "ZWE"),
}
FINANCIAL: RegistryDict = {
"european_central_bank": ("EuropeanCentralBank", "XECB", "ECB", "TAR"),
"ice_futures_europe": ("ICEFuturesEurope", "IFEU"),
"ny_stock_exchange": ("NewYorkStockExchange", "XNYS", "NYSE"),
"brasil_bolsa_balcao": ("BrasilBolsaBalcao", "BVMF", "B3"),
}
# A re-entrant lock. Once a thread has acquired a re-entrant lock,
# the same thread may acquire it again without blocking.
# https://docs.python.org/3/library/threading.html#rlock-objects
IMPORT_LOCK = RLock()
class EntityLoader:
"""Country and financial holidays entities lazy loader."""
__slots__ = ("entity", "entity_name", "module_name")
def __init__(self, path: str, *args, **kwargs) -> None:
"""Set up a lazy loader."""
if args:
raise TypeError(
"This is a holidays entity loader class. "
"For entity inheritance purposes please import a class you "
"want to derive from directly: e.g., "
"`from holidays.countries import Entity` or "
"`from holidays.financial import Entity`."
)
entity_path = path.split(".")
self.entity = None
self.entity_name = entity_path[-1]
self.module_name = ".".join(entity_path[0:-1])
super().__init__(*args, **kwargs)
def __call__(self, *args, **kwargs) -> HolidayBase:
"""Create a new instance of a lazy-loaded entity."""
cls = self.get_entity()
return cls(*args, **kwargs) # type: ignore[misc, operator]
def __getattr__(self, name: str) -> Optional[Any]:
"""Return attribute of a lazy-loaded entity."""
cls = self.get_entity()
return getattr(cls, name)
def __str__(self) -> str:
"""Return lazy loader object string representation."""
return (
f"A lazy loader for {self.get_entity()}. For inheritance please "
f"use the '{self.module_name}.{self.entity_name}' class directly."
)
def get_entity(self) -> Optional[HolidayBase]:
"""Return lazy-loaded entity."""
if self.entity is None:
# Avoid deadlock due to importlib.import_module not being thread-safe by caching all
# the first imports in a dedicated thread.
with IMPORT_LOCK:
self.entity = getattr(importlib.import_module(self.module_name), self.entity_name)
return self.entity
@staticmethod
def _get_entity_codes(
container: RegistryDict,
entity_length: Union[int, Iterable[int]],
include_aliases: bool = True,
) -> Iterable[str]:
entity_length = {entity_length} if isinstance(entity_length, int) else set(entity_length)
for entities in container.values():
for entity in entities:
if len(entity) in entity_length:
yield entity
# Assuming that the alpha-2 code goes first.
if not include_aliases:
break
@staticmethod
def get_country_codes(include_aliases: bool = True) -> Iterable[str]:
"""Get supported country codes.
:param include_aliases:
Whether to include entity aliases (e.g. UK for GB).
"""
return EntityLoader._get_entity_codes(COUNTRIES, 2, include_aliases)
@staticmethod
def get_financial_codes(include_aliases: bool = True) -> Iterable[str]:
"""Get supported financial codes.
:param include_aliases:
Whether to include entity aliases(e.g. TAR for ECB, XNYS for NYSE).
"""
return EntityLoader._get_entity_codes(FINANCIAL, (3, 4), include_aliases)
@staticmethod
def load(prefix: str, scope: dict) -> None:
"""Load country or financial entities."""
entity_mapping = COUNTRIES if prefix == "countries" else FINANCIAL
for module, entities in entity_mapping.items():
scope.update(
{
entity: EntityLoader(f"holidays.{prefix}.{module}.{entity}")
for entity in entities
}
)