#  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)

from datetime import date
from typing import Optional

from holidays.calendars.custom import _CustomCalendar
from holidays.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV

BIRTH_OF_GURU_RINPOCHE = "BIRTH_OF_GURU_RINPOCHE"
BLESSED_RAINY_DAY = "BLESSED_RAINY_DAY"
BUDDHA_FIRST_SERMON = "BUDDHA_FIRST_SERMON"
BUDDHA_PARINIRVANA = "BUDDHA_PARINIRVANA"
DAY_OF_OFFERING = "DAY_OF_OFFERING"
DEATH_OF_ZHABDRUNG = "DEATH_OF_ZHABDRUNG"
DESCENDING_DAY_OF_LORD_BUDDHA = "DESCENDING_DAY_OF_LORD_BUDDHA"
LOSAR = "LOSAR"
THIMPHU_DRUBCHEN = "THIMPHU_DRUBCHEN"
THIMPHU_TSHECHU = "THIMPHU_TSHECHU"
WINTER_SOLSTICE = "WINTER_SOLSTICE"


class _TibetanLunisolar:
    """Tibetan lunisolar calendar.

    Dates calculation is based on the Tibetan lunisolar calendar,
    which is sourced from <https://github.com/wp-plugins/bhutanese-calendar>.
    """

    BIRTH_OF_GURU_RINPOCHE_DATES = {
        1970: (JUN, 14),
        1971: (JUL, 3),
        1972: (JUN, 21),
        1973: (JUL, 10),
        1974: (JUN, 29),
        1977: (JUN, 26),
        1978: (JUN, 16),
        1979: (JUL, 5),
        1980: (JUN, 23),
        1981: (JUL, 11),
        1982: (JUN, 30),
        1983: (JUN, 20),
        1984: (JUL, 8),
        1986: (JUN, 17),
        1987: (JUL, 6),
        1988: (JUN, 24),
        1989: (JUN, 13),
        1990: (JUL, 2),
        1991: (JUN, 21),
        1992: (JUL, 9),
        1993: (JUN, 29),
        1996: (JUN, 26),
        1997: (JUN, 15),
        1998: (JUL, 4),
        1999: (JUN, 23),
        2000: (JUL, 11),
        2001: (JUN, 30),
        2002: (JUN, 20),
        2003: (JUL, 9),
        2005: (JUN, 17),
        2006: (JUL, 6),
        2007: (JUN, 25),
        2008: (JUL, 12),
        2009: (JUL, 2),
        2010: (JUN, 21),
        2011: (JUL, 10),
        2012: (JUN, 29),
        2013: (JUN, 18),
        2014: (JUL, 7),
        2015: (JUN, 26),
        2016: (JUN, 15),
        2017: (JUL, 3),
        2018: (JUN, 23),
        2019: (JUL, 11),
        2020: (JUN, 30),
        2021: (JUN, 20),
        2022: (JUL, 9),
        2023: (JUN, 28),
        2024: (JUN, 16),
        2025: (JUL, 5),
        2026: (JUN, 24),
        2028: (JUL, 1),
        2029: (JUN, 21),
        2030: (JUL, 10),
        2031: (JUN, 30),
        2032: (JUN, 18),
        2033: (JUL, 7),
        2034: (JUN, 26),
        2035: (JUN, 15),
        2036: (JUL, 3),
        2037: (JUN, 22),
        2038: (JUL, 11),
        2039: (JUL, 1),
        2040: (JUN, 20),
        2041: (JUL, 8),
        2042: (JUN, 28),
        2043: (JUN, 17),
        2044: (JUL, 4),
        2045: (JUN, 24),
        2046: (JUL, 13),
        2047: (JUL, 2),
        2048: (JUN, 21),
        2049: (JUL, 10),
        2050: (JUN, 29),
        2051: (JUN, 18),
        2052: (JUL, 6),
        2053: (JUN, 25),
        2054: (JUN, 15),
        2055: (JUL, 4),
        2057: (JUL, 11),
        2058: (JUL, 1),
        2059: (JUN, 20),
        2060: (JUL, 8),
        2061: (JUN, 27),
        2062: (JUN, 16),
        2063: (JUL, 5),
        2064: (JUN, 24),
        2065: (JUL, 13),
        2066: (JUL, 2),
        2067: (JUN, 22),
        2068: (JUL, 10),
        2069: (JUN, 29),
        2070: (JUN, 18),
        2071: (JUL, 7),
        2072: (JUN, 25),
        2073: (JUN, 15),
        2074: (JUL, 4),
        2075: (JUN, 23),
        2076: (JUL, 11),
        2077: (JUN, 30),
        2078: (JUN, 20),
        2079: (JUL, 8),
        2081: (JUN, 16),
        2082: (JUL, 5),
        2083: (JUN, 25),
        2084: (JUL, 13),
        2085: (JUL, 2),
        2086: (JUN, 21),
        2087: (JUL, 10),
        2088: (JUN, 28),
        2089: (JUN, 17),
        2090: (JUL, 6),
        2091: (JUN, 26),
        2092: (JUN, 15),
        2093: (JUL, 4),
        2094: (JUN, 23),
        2095: (JUL, 12),
        2096: (JUN, 30),
        2097: (JUN, 19),
        2098: (JUL, 8),
        2099: (JUN, 27),
    }

    BLESSED_RAINY_DAY_DATES = {
        1970: (SEP, 23),
        1971: (SEP, 23),
        1972: (SEP, 23),
        1973: (SEP, 23),
        1974: (SEP, 23),
        1975: (SEP, 23),
        1976: (SEP, 23),
        1977: (SEP, 23),
        1978: (SEP, 23),
        1979: (SEP, 23),
        1980: (SEP, 23),
        1981: (SEP, 23),
        1982: (SEP, 23),
        1983: (SEP, 23),
        1984: (SEP, 23),
        1985: (SEP, 23),
        1986: (SEP, 23),
        1987: (SEP, 23),
        1988: (SEP, 23),
        1989: (SEP, 23),
        1990: (SEP, 23),
        1991: (SEP, 23),
        1992: (SEP, 23),
        1993: (SEP, 23),
        1994: (SEP, 23),
        1995: (SEP, 23),
        1996: (SEP, 23),
        1997: (SEP, 23),
        1998: (SEP, 23),
        1999: (SEP, 23),
        2000: (SEP, 22),
        2001: (SEP, 23),
        2002: (SEP, 23),
        2003: (SEP, 23),
        2004: (SEP, 22),
        2005: (SEP, 23),
        2006: (SEP, 23),
        2007: (SEP, 23),
        2008: (SEP, 22),
        2009: (SEP, 23),
        2010: (SEP, 23),
        2011: (SEP, 23),
        2012: (SEP, 22),
        2013: (SEP, 23),
        2014: (SEP, 23),
        2015: (SEP, 22),
        2016: (SEP, 23),
        2017: (SEP, 23),
        2018: (SEP, 23),
        2019: (SEP, 24),
        2020: (SEP, 23),
        2021: (SEP, 23),
        2022: (SEP, 23),
        2023: (SEP, 24),
        2024: (SEP, 23),
        2025: (SEP, 23),
        2026: (SEP, 23),
        2027: (SEP, 23),
        2028: (SEP, 22),
        2029: (SEP, 22),
        2030: (SEP, 23),
        2031: (SEP, 23),
        2032: (SEP, 22),
        2033: (SEP, 22),
        2034: (SEP, 23),
        2035: (SEP, 23),
        2036: (SEP, 22),
        2037: (SEP, 22),
        2038: (SEP, 23),
        2039: (SEP, 23),
        2040: (SEP, 22),
        2041: (SEP, 22),
        2042: (SEP, 23),
        2043: (SEP, 23),
        2044: (SEP, 22),
        2045: (SEP, 22),
        2046: (SEP, 23),
        2047: (SEP, 23),
        2048: (SEP, 22),
        2049: (SEP, 22),
        2050: (SEP, 23),
        2051: (SEP, 23),
        2052: (SEP, 22),
    }

    BUDDHA_FIRST_SERMON_DATES = {
        1970: (JUL, 7),
        1971: (JUL, 26),
        1972: (JUL, 14),
        1973: (AUG, 2),
        1974: (JUL, 23),
        1975: (JUL, 12),
        1976: (JUL, 30),
        1977: (JUL, 20),
        1978: (JUL, 9),
        1979: (JUL, 28),
        1980: (JUL, 16),
        1981: (AUG, 4),
        1982: (JUL, 24),
        1983: (JUL, 14),
        1984: (AUG, 1),
        1985: (JUL, 21),
        1986: (JUL, 11),
        1987: (JUL, 30),
        1988: (JUL, 18),
        1989: (JUL, 7),
        1990: (JUL, 25),
        1991: (JUL, 15),
        1992: (AUG, 2),
        1993: (JUL, 23),
        1994: (JUL, 12),
        1995: (JUL, 31),
        1996: (JUL, 19),
        1997: (JUL, 8),
        1998: (JUL, 27),
        1999: (JUL, 16),
        2000: (AUG, 3),
        2001: (JUL, 24),
        2002: (JUL, 14),
        2003: (AUG, 2),
        2004: (JUL, 21),
        2005: (JUL, 10),
        2006: (JUL, 29),
        2007: (JUL, 18),
        2008: (AUG, 5),
        2009: (JUL, 25),
        2010: (JUL, 15),
        2011: (AUG, 3),
        2012: (JUL, 23),
        2013: (JUL, 12),
        2014: (JUL, 31),
        2015: (JUL, 20),
        2016: (JUL, 8),
        2017: (JUL, 27),
        2018: (JUL, 16),
        2019: (AUG, 4),
        2020: (JUL, 24),
        2021: (JUL, 14),
        2022: (AUG, 1),
        2023: (JUL, 21),
        2024: (JUL, 10),
        2025: (JUL, 28),
        2026: (JUL, 18),
        2027: (AUG, 6),
        2028: (JUL, 25),
        2029: (JUL, 15),
        2030: (AUG, 3),
        2031: (JUL, 23),
        2032: (JUL, 11),
        2033: (JUL, 30),
        2034: (JUL, 19),
        2035: (JUL, 9),
        2036: (JUL, 27),
        2037: (JUL, 16),
        2038: (AUG, 4),
        2039: (JUL, 25),
        2040: (JUL, 13),
        2041: (AUG, 1),
        2042: (JUL, 21),
        2043: (JUL, 10),
        2044: (JUL, 28),
        2045: (JUL, 18),
        2046: (AUG, 6),
        2047: (JUL, 26),
        2048: (JUL, 15),
        2049: (AUG, 2),
        2050: (JUL, 23),
        2051: (JUL, 12),
        2052: (JUL, 29),
        2053: (JUL, 19),
        2054: (JUL, 9),
        2055: (JUL, 28),
        2056: (JUL, 16),
        2057: (AUG, 4),
        2058: (JUL, 24),
        2059: (JUL, 13),
        2060: (JUL, 31),
        2061: (JUL, 20),
        2062: (JUL, 10),
        2063: (JUL, 29),
        2064: (JUL, 18),
        2065: (AUG, 6),
        2066: (JUL, 26),
        2067: (JUL, 15),
        2068: (AUG, 2),
        2069: (JUL, 22),
        2070: (JUL, 11),
        2071: (JUL, 30),
        2072: (JUL, 19),
        2073: (AUG, 7),
        2074: (JUL, 28),
        2075: (JUL, 17),
        2076: (AUG, 4),
        2077: (JUL, 24),
        2078: (JUL, 13),
        2079: (AUG, 1),
        2080: (JUL, 20),
        2081: (JUL, 10),
        2082: (JUL, 29),
        2084: (AUG, 5),
        2085: (JUL, 25),
        2086: (JUL, 14),
        2087: (AUG, 2),
        2088: (JUL, 22),
        2089: (JUL, 11),
        2090: (JUL, 30),
        2091: (JUL, 20),
        2092: (AUG, 7),
        2093: (JUL, 27),
        2094: (JUL, 16),
        2095: (AUG, 4),
        2096: (JUL, 23),
        2097: (JUL, 13),
        2099: (JUL, 21),
    }

    BUDDHA_PARINIRVANA_DATES = {
        1970: (MAY, 21),
        1971: (JUN, 8),
        1972: (MAY, 28),
        1973: (JUN, 15),
        1974: (JUN, 4),
        1975: (MAY, 25),
        1976: (JUN, 12),
        1977: (JUN, 1),
        1978: (MAY, 22),
        1979: (JUN, 10),
        1980: (MAY, 29),
        1981: (MAY, 18),
        1982: (JUN, 6),
        1983: (MAY, 26),
        1984: (JUN, 13),
        1985: (JUN, 3),
        1986: (MAY, 23),
        1987: (JUN, 11),
        1988: (MAY, 31),
        1989: (MAY, 20),
        1990: (JUN, 8),
        1991: (MAY, 28),
        1992: (JUN, 15),
        1993: (JUN, 4),
        1994: (MAY, 25),
        1995: (JUN, 13),
        1996: (JUN, 1),
        1997: (MAY, 22),
        1998: (JUN, 10),
        1999: (MAY, 30),
        2000: (MAY, 18),
        2001: (JUN, 6),
        2002: (MAY, 26),
        2003: (JUN, 14),
        2004: (JUN, 3),
        2005: (MAY, 23),
        2006: (JUN, 11),
        2007: (MAY, 31),
        2008: (MAY, 19),
        2009: (JUN, 7),
        2010: (MAY, 27),
        2011: (JUN, 15),
        2012: (JUN, 4),
        2013: (MAY, 25),
        2014: (JUN, 13),
        2015: (JUN, 2),
        2016: (MAY, 21),
        2017: (JUN, 9),
        2018: (MAY, 29),
        2019: (JUN, 17),
        2020: (JUN, 5),
        2021: (MAY, 26),
        2022: (JUN, 14),
        2023: (JUN, 4),
        2024: (MAY, 23),
        2025: (JUN, 11),
        2026: (MAY, 31),
        2027: (MAY, 20),
        2028: (JUN, 7),
        2029: (MAY, 27),
        2030: (JUN, 15),
        2031: (JUN, 5),
        2032: (MAY, 25),
        2033: (JUN, 12),
        2034: (JUN, 2),
        2035: (MAY, 22),
        2036: (JUN, 8),
        2037: (MAY, 29),
        2038: (JUN, 17),
        2039: (JUN, 6),
        2040: (MAY, 26),
        2041: (JUN, 14),
        2042: (JUN, 3),
        2043: (MAY, 23),
        2044: (JUN, 10),
        2045: (MAY, 30),
        2046: (MAY, 20),
        2047: (JUN, 8),
        2048: (MAY, 27),
        2049: (JUN, 15),
        2050: (JUN, 5),
        2051: (MAY, 25),
        2052: (JUN, 12),
        2053: (JUN, 1),
        2054: (MAY, 21),
        2055: (JUN, 9),
        2056: (MAY, 29),
        2057: (JUN, 17),
        2058: (JUN, 6),
        2059: (MAY, 27),
        2060: (JUN, 14),
        2061: (JUN, 3),
        2062: (MAY, 23),
        2063: (JUN, 11),
        2064: (MAY, 30),
        2065: (MAY, 20),
        2066: (JUN, 8),
        2067: (MAY, 28),
        2068: (JUN, 15),
        2069: (JUN, 4),
        2070: (MAY, 24),
        2071: (JUN, 12),
        2072: (MAY, 31),
        2073: (MAY, 21),
        2074: (JUN, 9),
        2075: (MAY, 30),
        2076: (JUN, 17),
        2077: (JUN, 6),
        2078: (MAY, 26),
        2079: (JUN, 14),
        2080: (JUN, 2),
        2081: (MAY, 22),
        2082: (JUN, 10),
        2083: (MAY, 31),
        2084: (JUN, 18),
        2085: (JUN, 8),
        2086: (MAY, 28),
        2087: (JUN, 16),
        2088: (JUN, 4),
        2089: (MAY, 24),
        2090: (JUN, 12),
        2091: (JUN, 1),
        2092: (MAY, 21),
        2093: (JUN, 9),
        2094: (MAY, 30),
        2095: (JUN, 17),
        2096: (JUN, 5),
        2097: (MAY, 26),
        2098: (JUN, 13),
        2099: (JUN, 3),
    }

    DAY_OF_OFFERING_DATES = {
        1971: (JAN, 27),
        1972: (JAN, 17),
        1973: (JAN, 5),
        1974: (JAN, 24),
        1975: (JAN, 13),
        1976: (FEB, 1),
        1977: (JAN, 20),
        1979: (JAN, 29),
        1980: (JAN, 18),
        1981: (JAN, 7),
        1982: (JAN, 26),
        1983: (JAN, 15),
        1984: (JAN, 4),
        1985: (JAN, 21),
        1986: (JAN, 11),
        1987: (JAN, 30),
        1988: (JAN, 20),
        1989: (JAN, 8),
        1990: (JAN, 27),
        1991: (JAN, 16),
        1992: (JAN, 5),
        1993: (JAN, 23),
        1994: (JAN, 12),
        1995: (JAN, 31),
        1996: (JAN, 21),
        1997: (JAN, 10),
        1998: (JAN, 29),
        1999: (JAN, 18),
        2000: (JAN, 7),
        2001: (JAN, 25),
        2002: (JAN, 14),
        2003: (JAN, 3),
        2004: (JAN, 22),
        2005: (JAN, 11),
        2006: (JAN, 30),
        2007: (JAN, 20),
        2008: (JAN, 9),
        2009: (JAN, 27),
        2010: (JAN, 16),
        2011: (JAN, 5),
        2012: (JAN, 24),
        2013: (JAN, 12),
        2014: (JAN, 31),
        2015: (JAN, 21),
        2016: (JAN, 10),
        2017: (JAN, 28),
        2018: (JAN, 17),
        2019: (JAN, 6),
        2020: (JAN, 25),
        2021: (JAN, 14),
        2022: (JAN, 3),
        2023: (JAN, 22),
        2024: (JAN, 12),
        2025: (JAN, 30),
        2026: (JAN, 19),
        2027: (JAN, 8),
        2028: (JAN, 27),
        2029: (JAN, 15),
        2030: (JAN, 4),
        2032: (JAN, 13),
        2033: (JAN, 31),
        2034: (JAN, 21),
        2035: (JAN, 10),
        2036: (JAN, 29),
        2037: (JAN, 17),
        2038: (JAN, 6),
        2039: (JAN, 25),
        2041: (FEB, 2),
        2042: (JAN, 22),
        2043: (JAN, 12),
        2044: (JAN, 31),
        2045: (JAN, 19),
        2046: (JAN, 8),
        2047: (JAN, 26),
        2048: (JAN, 16),
        2049: (JAN, 4),
        2050: (JAN, 24),
        2051: (JAN, 13),
        2052: (FEB, 1),
        2053: (JAN, 20),
        2054: (JAN, 9),
        2055: (JAN, 28),
        2056: (JAN, 17),
        2057: (JAN, 6),
        2058: (JAN, 25),
        2060: (FEB, 3),
        2061: (JAN, 22),
        2062: (JAN, 11),
        2063: (JAN, 30),
        2064: (JAN, 19),
        2065: (JAN, 7),
        2066: (JAN, 26),
        2067: (JAN, 16),
        2070: (JAN, 13),
        2071: (FEB, 1),
        2072: (JAN, 21),
        2073: (JAN, 9),
        2074: (JAN, 28),
        2075: (JAN, 17),
        2076: (JAN, 7),
        2077: (JAN, 25),
        2078: (JAN, 14),
        2079: (FEB, 2),
        2080: (JAN, 22),
        2081: (JAN, 10),
        2082: (JAN, 29),
        2084: (JAN, 8),
        2085: (JAN, 26),
        2086: (JAN, 16),
        2087: (JAN, 5),
        2088: (JAN, 24),
        2089: (JAN, 12),
        2090: (JAN, 31),
        2091: (JAN, 20),
        2092: (JAN, 9),
        2094: (JAN, 17),
        2095: (JAN, 7),
        2096: (JAN, 26),
        2097: (JAN, 14),
        2098: (FEB, 2),
        2099: (JAN, 22),
    }

    DEATH_OF_ZHABDRUNG_DATES = {
        1970: (APR, 16),
        1971: (MAY, 5),
        1972: (APR, 23),
        1973: (APR, 12),
        1974: (MAY, 1),
        1975: (APR, 21),
        1976: (MAY, 9),
        1977: (APR, 28),
        1978: (APR, 18),
        1979: (MAY, 6),
        1980: (APR, 24),
        1981: (APR, 14),
        1983: (APR, 22),
        1984: (MAY, 10),
        1985: (APR, 30),
        1986: (APR, 19),
        1987: (MAY, 8),
        1988: (APR, 26),
        1989: (APR, 15),
        1990: (MAY, 4),
        1991: (APR, 23),
        1993: (MAY, 1),
        1994: (APR, 21),
        1995: (MAY, 10),
        1996: (APR, 28),
        1997: (APR, 17),
        1998: (MAY, 6),
        1999: (APR, 25),
        2000: (APR, 13),
        2002: (APR, 22),
        2003: (MAY, 11),
        2004: (APR, 30),
        2005: (APR, 19),
        2006: (MAY, 7),
        2007: (APR, 26),
        2008: (APR, 15),
        2009: (MAY, 4),
        2012: (MAY, 1),
        2013: (APR, 20),
        2014: (MAY, 9),
        2015: (APR, 28),
        2016: (APR, 16),
        2017: (MAY, 5),
        2018: (APR, 25),
        2019: (APR, 14),
        2021: (APR, 22),
        2022: (MAY, 11),
        2023: (APR, 30),
        2024: (APR, 18),
        2025: (MAY, 7),
        2026: (APR, 26),
        2027: (APR, 16),
        2028: (MAY, 4),
        2029: (APR, 23),
        2030: (MAY, 12),
        2031: (MAY, 2),
        2032: (APR, 20),
        2033: (MAY, 8),
        2034: (APR, 28),
        2035: (APR, 17),
        2036: (MAY, 5),
        2037: (APR, 25),
        2038: (APR, 14),
        2039: (MAY, 3),
        2040: (APR, 21),
        2041: (MAY, 10),
        2042: (APR, 29),
        2043: (APR, 19),
        2044: (MAY, 6),
        2045: (APR, 26),
        2046: (APR, 16),
        2047: (MAY, 5),
        2048: (APR, 23),
        2049: (MAY, 12),
        2050: (MAY, 1),
        2051: (APR, 20),
        2052: (MAY, 8),
        2053: (APR, 27),
        2054: (APR, 17),
        2055: (MAY, 6),
        2056: (APR, 25),
        2057: (MAY, 14),
        2058: (MAY, 3),
        2059: (APR, 22),
        2060: (MAY, 10),
        2061: (APR, 29),
        2062: (APR, 18),
        2063: (MAY, 7),
        2064: (APR, 26),
        2065: (APR, 16),
        2066: (MAY, 5),
        2067: (APR, 24),
        2068: (MAY, 11),
        2069: (APR, 30),
        2070: (APR, 20),
        2071: (MAY, 9),
        2072: (APR, 27),
        2073: (APR, 17),
        2074: (MAY, 6),
        2075: (APR, 25),
        2076: (MAY, 13),
        2077: (MAY, 2),
        2078: (APR, 21),
        2079: (MAY, 10),
        2080: (APR, 29),
        2081: (APR, 18),
        2082: (MAY, 7),
        2083: (APR, 27),
        2084: (APR, 15),
        2085: (MAY, 4),
        2086: (APR, 23),
        2087: (MAY, 12),
        2088: (APR, 30),
        2089: (APR, 20),
        2090: (MAY, 9),
        2091: (APR, 28),
        2092: (APR, 17),
        2093: (MAY, 6),
        2094: (APR, 25),
        2095: (MAY, 13),
        2096: (MAY, 2),
        2097: (APR, 21),
        2098: (MAY, 10),
        2099: (APR, 30),
    }

    DESCENDING_DAY_OF_LORD_BUDDHA_DATES = {
        1970: (NOV, 20),
        1971: (NOV, 9),
        1972: (OCT, 28),
        1973: (NOV, 16),
        1974: (NOV, 6),
        1975: (OCT, 27),
        1976: (NOV, 14),
        1977: (NOV, 3),
        1978: (NOV, 22),
        1979: (NOV, 11),
        1980: (OCT, 30),
        1981: (NOV, 18),
        1982: (NOV, 7),
        1983: (OCT, 28),
        1984: (NOV, 15),
        1985: (NOV, 5),
        1986: (OCT, 25),
        1987: (NOV, 12),
        1988: (OCT, 31),
        1989: (NOV, 19),
        1990: (NOV, 9),
        1991: (OCT, 29),
        1993: (NOV, 6),
        1994: (OCT, 26),
        1995: (NOV, 14),
        1996: (NOV, 2),
        1997: (NOV, 21),
        1998: (NOV, 10),
        1999: (OCT, 31),
        2000: (NOV, 18),
        2001: (NOV, 7),
        2002: (OCT, 28),
        2003: (NOV, 16),
        2004: (NOV, 4),
        2005: (OCT, 24),
        2006: (NOV, 12),
        2007: (NOV, 1),
        2008: (NOV, 19),
        2009: (NOV, 9),
        2010: (OCT, 29),
        2011: (NOV, 17),
        2012: (NOV, 6),
        2013: (OCT, 26),
        2014: (NOV, 13),
        2015: (NOV, 3),
        2016: (NOV, 20),
        2017: (NOV, 10),
        2018: (OCT, 31),
        2019: (NOV, 19),
        2020: (NOV, 7),
        2021: (OCT, 27),
        2022: (NOV, 15),
        2023: (NOV, 4),
        2024: (NOV, 22),
        2025: (NOV, 11),
        2026: (NOV, 1),
        2027: (NOV, 20),
        2028: (NOV, 9),
        2029: (OCT, 29),
        2030: (NOV, 17),
        2031: (NOV, 6),
        2032: (OCT, 25),
        2033: (NOV, 13),
        2034: (NOV, 2),
        2035: (NOV, 21),
        2036: (NOV, 10),
        2037: (OCT, 31),
        2038: (NOV, 19),
        2039: (NOV, 8),
        2040: (OCT, 27),
        2041: (NOV, 15),
        2042: (NOV, 4),
        2043: (NOV, 23),
        2044: (NOV, 11),
        2045: (NOV, 1),
        2046: (NOV, 20),
        2047: (NOV, 9),
        2048: (OCT, 29),
        2049: (NOV, 16),
        2050: (NOV, 5),
        2051: (OCT, 26),
        2052: (NOV, 13),
        2053: (NOV, 2),
        2054: (NOV, 21),
        2055: (NOV, 11),
        2056: (OCT, 30),
        2057: (NOV, 18),
        2058: (NOV, 7),
        2059: (OCT, 27),
        2060: (NOV, 14),
        2061: (NOV, 4),
        2062: (NOV, 23),
        2063: (NOV, 12),
        2064: (NOV, 1),
        2065: (NOV, 20),
        2066: (NOV, 9),
        2067: (OCT, 29),
        2068: (NOV, 16),
        2069: (NOV, 5),
        2070: (OCT, 26),
        2071: (NOV, 14),
        2072: (NOV, 2),
        2073: (NOV, 21),
        2074: (NOV, 11),
        2075: (OCT, 31),
        2076: (NOV, 17),
        2077: (NOV, 7),
        2078: (OCT, 27),
        2079: (NOV, 15),
        2080: (NOV, 4),
        2081: (NOV, 23),
        2082: (NOV, 12),
        2083: (NOV, 1),
        2084: (NOV, 19),
        2085: (NOV, 8),
        2086: (OCT, 28),
        2087: (NOV, 16),
        2088: (NOV, 5),
        2089: (NOV, 24),
        2090: (NOV, 14),
        2091: (NOV, 3),
        2092: (NOV, 21),
        2093: (NOV, 10),
        2094: (OCT, 30),
        2095: (NOV, 18),
        2096: (NOV, 6),
        2097: (OCT, 27),
        2098: (NOV, 15),
        2099: (NOV, 5),
    }

    LOSAR_DATES = {
        1970: (FEB, 7),
        1971: (FEB, 26),
        1972: (FEB, 15),
        1973: (FEB, 4),
        1974: (FEB, 23),
        1975: (FEB, 12),
        1976: (MAR, 1),
        1977: (FEB, 19),
        1978: (FEB, 8),
        1979: (FEB, 27),
        1980: (FEB, 17),
        1981: (FEB, 5),
        1982: (FEB, 24),
        1983: (FEB, 13),
        1984: (FEB, 2),
        1985: (FEB, 20),
        1986: (FEB, 9),
        1987: (FEB, 28),
        1988: (FEB, 18),
        1989: (FEB, 7),
        1990: (FEB, 26),
        1991: (FEB, 15),
        1992: (FEB, 4),
        1993: (FEB, 22),
        1994: (FEB, 11),
        1995: (MAR, 2),
        1996: (FEB, 19),
        1997: (FEB, 8),
        1998: (FEB, 27),
        1999: (FEB, 17),
        2000: (FEB, 6),
        2001: (FEB, 24),
        2002: (FEB, 13),
        2003: (MAR, 4),
        2004: (FEB, 21),
        2005: (FEB, 9),
        2006: (FEB, 28),
        2007: (FEB, 18),
        2008: (FEB, 8),
        2009: (FEB, 25),
        2010: (FEB, 14),
        2011: (FEB, 3),
        2012: (FEB, 22),
        2013: (FEB, 11),
        2014: (MAR, 2),
        2015: (FEB, 19),
        2016: (FEB, 9),
        2017: (FEB, 27),
        2018: (FEB, 16),
        2019: (FEB, 5),
        2020: (FEB, 24),
        2021: (FEB, 12),
        2022: (MAR, 3),
        2023: (FEB, 21),
        2024: (FEB, 10),
        2025: (FEB, 28),
        2026: (FEB, 18),
        2027: (FEB, 7),
        2028: (FEB, 26),
        2029: (FEB, 14),
        2030: (FEB, 3),
        2031: (FEB, 22),
        2032: (FEB, 12),
        2033: (MAR, 2),
        2034: (FEB, 19),
        2035: (FEB, 9),
        2036: (FEB, 28),
        2037: (FEB, 16),
        2038: (FEB, 5),
        2039: (FEB, 24),
        2040: (FEB, 13),
        2041: (MAR, 3),
        2042: (FEB, 21),
        2043: (FEB, 10),
        2044: (FEB, 29),
        2045: (FEB, 17),
        2046: (FEB, 6),
        2047: (FEB, 25),
        2048: (FEB, 14),
        2049: (FEB, 3),
        2050: (FEB, 22),
        2051: (FEB, 12),
        2052: (MAR, 2),
        2053: (FEB, 19),
        2054: (FEB, 8),
        2055: (FEB, 27),
        2056: (FEB, 16),
        2057: (FEB, 4),
        2058: (FEB, 23),
        2059: (FEB, 13),
        2060: (MAR, 3),
        2061: (FEB, 21),
        2062: (FEB, 10),
        2063: (MAR, 1),
        2064: (FEB, 18),
        2065: (FEB, 6),
        2066: (FEB, 25),
        2067: (FEB, 14),
        2068: (MAR, 4),
        2069: (FEB, 22),
        2070: (FEB, 12),
        2071: (MAR, 2),
        2072: (FEB, 19),
        2073: (FEB, 7),
        2074: (FEB, 26),
        2075: (FEB, 16),
        2076: (FEB, 5),
        2077: (FEB, 23),
        2078: (FEB, 13),
        2079: (MAR, 4),
        2080: (FEB, 21),
        2081: (FEB, 9),
        2082: (FEB, 28),
        2083: (FEB, 17),
        2084: (FEB, 7),
        2085: (FEB, 25),
        2086: (FEB, 14),
        2087: (MAR, 5),
        2088: (FEB, 23),
        2089: (FEB, 11),
        2090: (MAR, 2),
        2091: (FEB, 19),
        2092: (FEB, 8),
        2093: (FEB, 26),
        2094: (FEB, 16),
        2095: (FEB, 5),
        2096: (FEB, 24),
        2097: (FEB, 13),
        2098: (MAR, 4),
        2099: (FEB, 21),
    }

    THIMPHU_DRUBCHEN_DATES = {
        1970: (OCT, 6),
        1971: (SEP, 25),
        1972: (SEP, 13),
        1973: (OCT, 2),
        1974: (SEP, 21),
        1975: (SEP, 11),
        1976: (SEP, 29),
        1978: (SEP, 8),
        1979: (SEP, 27),
        1980: (SEP, 15),
        1981: (OCT, 4),
        1982: (SEP, 23),
        1983: (SEP, 12),
        1984: (SEP, 30),
        1985: (SEP, 20),
        1987: (SEP, 28),
        1988: (SEP, 17),
        1989: (OCT, 6),
        1990: (SEP, 25),
        1991: (SEP, 14),
        1992: (OCT, 2),
        1993: (SEP, 21),
        1994: (SEP, 11),
        1995: (SEP, 30),
        1996: (SEP, 18),
        1997: (OCT, 7),
        1998: (SEP, 26),
        1999: (SEP, 16),
        2000: (OCT, 3),
        2001: (SEP, 23),
        2002: (SEP, 12),
        2003: (OCT, 1),
        2004: (SEP, 20),
        2005: (SEP, 9),
        2006: (SEP, 28),
        2007: (SEP, 17),
        2008: (OCT, 5),
        2009: (SEP, 24),
        2010: (SEP, 13),
        2011: (OCT, 2),
        2012: (SEP, 21),
        2013: (SEP, 11),
        2014: (SEP, 29),
        2015: (SEP, 19),
        2016: (OCT, 7),
        2017: (SEP, 26),
        2018: (SEP, 15),
        2019: (OCT, 4),
        2020: (SEP, 22),
        2021: (SEP, 11),
        2022: (SEP, 30),
        2023: (SEP, 20),
        2024: (SEP, 9),
        2025: (SEP, 28),
        2026: (SEP, 17),
        2027: (OCT, 5),
        2028: (SEP, 24),
        2029: (SEP, 13),
        2030: (OCT, 2),
        2031: (SEP, 22),
        2032: (SEP, 11),
        2033: (SEP, 29),
        2034: (SEP, 18),
        2035: (OCT, 7),
        2036: (SEP, 25),
        2037: (SEP, 15),
        2038: (OCT, 4),
        2039: (SEP, 23),
        2040: (SEP, 12),
        2041: (OCT, 1),
        2042: (SEP, 20),
        2043: (SEP, 9),
        2044: (SEP, 27),
        2045: (SEP, 16),
        2046: (OCT, 5),
        2047: (SEP, 25),
        2048: (SEP, 13),
        2049: (OCT, 2),
        2050: (SEP, 22),
        2051: (SEP, 11),
        2052: (SEP, 29),
        2053: (SEP, 18),
        2054: (OCT, 7),
        2055: (SEP, 26),
        2056: (SEP, 15),
        2057: (OCT, 4),
        2058: (SEP, 23),
        2059: (SEP, 13),
        2060: (SEP, 30),
        2061: (SEP, 19),
        2062: (OCT, 8),
        2063: (SEP, 27),
        2064: (SEP, 16),
        2065: (OCT, 5),
        2066: (SEP, 25),
        2067: (SEP, 14),
        2068: (OCT, 2),
        2069: (SEP, 21),
        2070: (SEP, 10),
        2071: (SEP, 29),
        2072: (SEP, 17),
        2073: (OCT, 6),
        2074: (SEP, 26),
        2075: (SEP, 16),
        2076: (OCT, 4),
        2077: (SEP, 23),
        2078: (SEP, 12),
        2079: (OCT, 1),
        2080: (SEP, 19),
        2081: (OCT, 8),
        2082: (SEP, 27),
        2083: (SEP, 17),
        2084: (OCT, 5),
        2085: (SEP, 25),
        2086: (SEP, 14),
        2087: (OCT, 3),
        2088: (SEP, 21),
        2089: (SEP, 10),
        2090: (SEP, 29),
        2091: (SEP, 18),
        2092: (OCT, 6),
        2093: (SEP, 26),
        2094: (SEP, 16),
        2095: (OCT, 4),
        2096: (SEP, 22),
        2097: (SEP, 11),
        2098: (SEP, 30),
        2099: (SEP, 20),
    }

    THIMPHU_TSHECHU_DATES = {
        1970: (OCT, 10),
        1971: (SEP, 29),
        1972: (SEP, 18),
        1973: (OCT, 6),
        1974: (SEP, 25),
        1975: (SEP, 15),
        1977: (SEP, 22),
        1978: (SEP, 12),
        1979: (OCT, 1),
        1980: (SEP, 19),
        1981: (OCT, 8),
        1982: (SEP, 27),
        1983: (SEP, 16),
        1984: (OCT, 4),
        1985: (SEP, 23),
        1986: (SEP, 13),
        1987: (OCT, 2),
        1988: (SEP, 21),
        1989: (OCT, 10),
        1990: (SEP, 29),
        1991: (SEP, 18),
        1992: (OCT, 6),
        1993: (SEP, 25),
        1994: (SEP, 14),
        1995: (OCT, 3),
        1996: (SEP, 22),
        1997: (OCT, 11),
        1998: (OCT, 1),
        1999: (SEP, 20),
        2000: (OCT, 8),
        2001: (SEP, 27),
        2002: (SEP, 16),
        2003: (OCT, 5),
        2004: (SEP, 23),
        2005: (SEP, 13),
        2006: (OCT, 2),
        2007: (SEP, 22),
        2008: (OCT, 9),
        2009: (SEP, 28),
        2010: (SEP, 17),
        2011: (OCT, 6),
        2012: (SEP, 25),
        2013: (SEP, 14),
        2014: (OCT, 3),
        2015: (SEP, 23),
        2016: (OCT, 11),
        2017: (SEP, 30),
        2018: (SEP, 19),
        2019: (OCT, 8),
        2020: (SEP, 26),
        2021: (SEP, 15),
        2022: (OCT, 4),
        2023: (SEP, 24),
        2024: (SEP, 13),
        2025: (OCT, 2),
        2026: (SEP, 21),
        2027: (OCT, 10),
        2028: (SEP, 28),
        2029: (SEP, 17),
        2030: (OCT, 6),
        2031: (SEP, 26),
        2032: (SEP, 14),
        2033: (OCT, 3),
        2034: (SEP, 23),
        2035: (OCT, 11),
        2036: (SEP, 29),
        2037: (SEP, 19),
        2038: (OCT, 7),
        2039: (SEP, 27),
        2040: (SEP, 16),
        2041: (OCT, 5),
        2042: (SEP, 24),
        2043: (SEP, 13),
        2044: (OCT, 1),
        2045: (SEP, 20),
        2046: (OCT, 9),
        2047: (SEP, 28),
        2048: (SEP, 17),
        2049: (OCT, 6),
        2050: (SEP, 26),
        2051: (SEP, 15),
        2052: (OCT, 3),
        2053: (SEP, 22),
        2054: (OCT, 11),
        2055: (SEP, 30),
        2056: (SEP, 18),
        2057: (OCT, 7),
        2058: (SEP, 27),
        2059: (SEP, 17),
        2060: (OCT, 5),
        2061: (SEP, 24),
        2062: (OCT, 12),
        2063: (OCT, 2),
        2064: (SEP, 20),
        2065: (OCT, 9),
        2066: (SEP, 28),
        2067: (SEP, 18),
        2068: (OCT, 6),
        2069: (SEP, 25),
        2070: (SEP, 15),
        2071: (OCT, 3),
        2072: (SEP, 21),
        2073: (OCT, 10),
        2074: (SEP, 30),
        2075: (SEP, 19),
        2076: (OCT, 7),
        2077: (SEP, 27),
        2078: (SEP, 16),
        2079: (OCT, 5),
        2080: (SEP, 23),
        2081: (OCT, 12),
        2082: (OCT, 1),
        2083: (SEP, 21),
        2084: (OCT, 9),
        2085: (SEP, 28),
        2086: (SEP, 18),
        2087: (OCT, 7),
        2088: (SEP, 25),
        2089: (SEP, 14),
        2090: (OCT, 3),
        2091: (SEP, 22),
        2092: (OCT, 10),
        2093: (SEP, 30),
        2094: (SEP, 19),
        2095: (OCT, 8),
        2096: (SEP, 27),
        2097: (SEP, 16),
        2098: (OCT, 4),
        2099: (SEP, 24),
    }

    WINTER_SOLSTICE_DATES = {
        1970: (JAN, 2),
        1971: (JAN, 2),
        1972: (JAN, 2),
        1973: (JAN, 2),
        1974: (JAN, 2),
        1975: (JAN, 2),
        1976: (JAN, 2),
        1977: (JAN, 2),
        1978: (JAN, 2),
        1979: (JAN, 2),
        1980: (JAN, 2),
        1981: (JAN, 2),
        1982: (JAN, 2),
        1983: (JAN, 2),
        1984: (JAN, 2),
        1985: (JAN, 2),
        1986: (JAN, 2),
        1987: (JAN, 2),
        1988: (JAN, 2),
        1989: (JAN, 2),
        1990: (JAN, 2),
        1991: (JAN, 2),
        1992: (JAN, 2),
        1993: (JAN, 2),
        1994: (JAN, 2),
        1995: (JAN, 2),
        1996: (JAN, 2),
        1997: (JAN, 2),
        1998: (JAN, 2),
        1999: (JAN, 2),
        2000: (JAN, 2),
        2001: (JAN, 2),
        2002: (JAN, 2),
        2003: (JAN, 2),
        2004: (JAN, 2),
        2005: (JAN, 2),
        2006: (JAN, 2),
        2007: (JAN, 2),
        2008: (JAN, 2),
        2009: (JAN, 2),
        2010: (JAN, 2),
        2011: (JAN, 2),
        2012: (JAN, 2),
        2013: (JAN, 2),
        2014: (JAN, 2),
        2015: (JAN, 2),
        2016: (JAN, 2),
        2017: (JAN, 2),
        2018: (JAN, 2),
        2019: (JAN, 3),
        2020: (JAN, 2),
        2021: (JAN, 2),
        2022: (JAN, 1),
        2023: (JAN, 2),
        2024: (JAN, 2),
        2025: (JAN, 2),
        2026: (JAN, 2),
        2027: (JAN, 2),
        2028: (JAN, 2),
        2029: (JAN, 2),
        2030: (JAN, 2),
        2031: (JAN, 2),
        2032: (JAN, 2),
        2033: (JAN, 2),
        2034: (JAN, 2),
        2035: (JAN, 2),
        2036: (JAN, 2),
        2037: (JAN, 2),
        2038: (JAN, 2),
        2039: (JAN, 2),
        2040: (JAN, 2),
        2041: (JAN, 2),
        2042: (JAN, 2),
        2043: (JAN, 2),
        2044: (JAN, 2),
        2045: (JAN, 2),
        2046: (JAN, 2),
        2047: (JAN, 2),
        2048: (JAN, 2),
        2049: (JAN, 2),
        2050: (JAN, 2),
        2051: (JAN, 2),
        2052: (JAN, 2),
        2053: (JAN, 2),
        2054: (JAN, 2),
        2055: (JAN, 2),
        2056: (JAN, 2),
        2057: (JAN, 2),
        2058: (JAN, 2),
        2059: (JAN, 2),
        2060: (JAN, 2),
        2061: (JAN, 2),
        2062: (JAN, 2),
        2063: (JAN, 2),
        2064: (JAN, 2),
        2065: (JAN, 2),
        2066: (JAN, 2),
        2067: (JAN, 2),
        2068: (JAN, 2),
        2069: (JAN, 2),
        2070: (JAN, 2),
        2071: (JAN, 2),
        2072: (JAN, 2),
        2073: (JAN, 2),
        2074: (JAN, 2),
        2075: (JAN, 2),
        2076: (JAN, 2),
        2077: (JAN, 2),
        2078: (JAN, 2),
        2079: (JAN, 2),
        2080: (JAN, 2),
        2081: (JAN, 2),
        2082: (JAN, 2),
        2083: (JAN, 2),
        2084: (JAN, 2),
        2085: (JAN, 2),
        2086: (JAN, 2),
        2087: (JAN, 2),
        2088: (JAN, 2),
        2089: (JAN, 2),
        2090: (JAN, 2),
        2091: (JAN, 2),
        2092: (JAN, 2),
        2093: (JAN, 2),
        2094: (JAN, 2),
        2095: (JAN, 2),
        2096: (JAN, 2),
        2097: (JAN, 2),
        2098: (JAN, 2),
        2099: (JAN, 2),
    }

    def _get_holiday(self, holiday: str, year: int) -> tuple[Optional[date], bool]:
        estimated_dates = getattr(self, f"{holiday}_DATES", {})
        exact_dates = getattr(self, f"{holiday}_DATES_{_CustomCalendar.CUSTOM_ATTR_POSTFIX}", {})
        dt = exact_dates.get(year, estimated_dates.get(year, ()))
        return date(year, *dt) if dt else None, year not in exact_dates

    def blessed_rainy_day_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(BLESSED_RAINY_DAY, year)

    def birth_of_guru_rinpoche_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(BIRTH_OF_GURU_RINPOCHE, year)

    def buddha_first_sermon_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(BUDDHA_FIRST_SERMON, year)

    def buddha_parinirvana_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(BUDDHA_PARINIRVANA, year)

    def day_of_offering_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(DAY_OF_OFFERING, year)

    def death_of_zhabdrung_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(DEATH_OF_ZHABDRUNG, year)

    def descending_day_of_lord_buddha_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(DESCENDING_DAY_OF_LORD_BUDDHA, year)

    def losar_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(LOSAR, year)

    def thimphu_drubchen_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(THIMPHU_DRUBCHEN, year)

    def thimphu_tshechu_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(THIMPHU_TSHECHU, year)

    def tibetan_winter_solstice_date(self, year: int) -> tuple[Optional[date], bool]:
        return self._get_holiday(WINTER_SOLSTICE, year)


class _CustomTibetanHolidays(_CustomCalendar, _TibetanLunisolar):
    pass
