Repository: vacanza/python-holidays

Issue:
Incomplete list of Chinese holidays
Hello, I'd like to ask you to check list of  _Chinese_ (CN) holidays. Based on my research (see links below) it seems that some of public holidays are missing there, for example 4.-6.10.2023 (week of _National Day_).
https://www.officeholidays.com/countries/china/2023
https://www.china-briefing.com/news/china-public-holiday-2023-schedule/
https://en.wikipedia.org/wiki/Public_holidays_in_China

Could you please have a look?
Thank you in advance!


Discussion:
Seems like none of the English version sources pre-2022 are reliable, though the Chinese government appears to have official ones from [2007](https://www.gov.cn/gongbao/content/2007/content_503397.htm) onwards from their website, which I'm working on at the moment - as well as adding both l10n support (English(US)/Thai/Simplified Chinese/Traditional Chinese) and half-day holiday supports.

Resolving patch:
diff --git a/holidays/countries/china.py b/holidays/countries/china.py
--- a/holidays/countries/china.py
+++ b/holidays/countries/china.py
@@ -9,53 +9,361 @@
 #  Website: https://github.com/dr-prodigy/python-holidays
 #  License: MIT (see LICENSE file)
 
+from datetime import date
+from datetime import timedelta as td
+from gettext import gettext as tr
+
+from holidays.calendars.gregorian import JAN, MAY, SEP, OCT, DEC
+from holidays.constants import HALF_DAY, PUBLIC
 from holidays.groups import ChineseCalendarHolidays, InternationalHolidays
 from holidays.holiday_base import HolidayBase
 
 
 class China(HolidayBase, ChineseCalendarHolidays, InternationalHolidays):
     """
-    https://en.wikipedia.org/wiki/Public_holidays_in_China
+    References:
+    - https://en.wikipedia.org/wiki/Public_holidays_in_China
+    - https://zh.wikipedia.org/wiki/中华人民共和国节日与公众假期
+    - https://www.gov.cn/gongbao/content/2023/content_5736714.htm # 2023
+    - https://www.gov.cn/gongbao/content/2021/content_5651728.htm # 2022
+    - https://www.gov.cn/gongbao/content/2020/content_5567750.htm # 2021
+    - https://www.gov.cn/gongbao/content/2019/content_5459138.htm # 2020
+    - https://www.gov.cn/gongbao/content/2018/content_5350046.htm # 2019
+    - https://www.gov.cn/gongbao/content/2017/content_5248221.htm # 2018
+    - https://www.gov.cn/gongbao/content/2016/content_5148793.htm # 2017
+    - https://www.gov.cn/gongbao/content/2016/content_2979719.htm # 2016
+    - https://www.gov.cn/gongbao/content/2015/content_2799019.htm # 2015
+    - https://www.gov.cn/gongbao/content/2014/content_2561299.htm # 2014
+    - https://www.gov.cn/gongbao/content/2012/content_2292057.htm # 2013
+    - https://www.gov.cn/gongbao/content/2011/content_2020918.htm # 2012
+    - https://www.gov.cn/gongbao/content/2010/content_1765282.htm # 2011
+    - https://www.gov.cn/gongbao/content/2009/content_1487011.htm # 2010
+    - https://www.gov.cn/gongbao/content/2008/content_1175823.htm # 2009
+    - https://www.gov.cn/gongbao/content/2008/content_859870.htm # 2008
+    - https://www.gov.cn/gongbao/content/2007/content_503397.htm # 2007
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2006年部分节假日安排的通知 # 2006
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2005年部分节假日安排的通知 # 2005
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2004年部分节假日安排的通知 # 2004
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2003年部分节假日休息安排的通知 # 2003
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2002年部分节假日休息安排的通知 # 2002
+    - https://zh.wikisource.org/wiki/国务院办公厅关于2001年春节、“五一”、“十一”放假安排的通知 # 2001
+
+    Checked With:
+    - https://www.officeholidays.com/countries/china/2023
+    - https://www.china-briefing.com/news/china-public-holiday-2023-schedule/
+    - https://www.timeanddate.com/calendar/?year=2023&country=41
+    - https://m.wannianli.tianqi.com/fangjiaanpai/2001.html # 2001-2010
+
+    Limitations:
+
+    - Only checked with the official General Office of the State Council Notice from 2001 onwards.
+
+    - Due to its complexity, need yearly checks 3-weeks before year's end each year.
     """
 
     country = "CN"
+    supported_categories = {PUBLIC, HALF_DAY}
+    default_language = "zh_CN"
+    supported_languages = ("en_US", "th", "zh_CN", "zh_TW")
+
+    # Special Cases.
+
+    # New Year's Day.
+    new_years_day_overflow = tr("元旦")
+
+    # National Day.
+    national_day_2008_golden_week = tr("国庆节")
+
+    # Mid-Autumn Festival.
+    mid_autumn_festival_2010_special = tr("中秋节")
+
+    special_public_holidays = {
+        2007: (
+            # 2007: Overflow from 2008 Notice.
+            (DEC, 30, new_years_day_overflow),
+            (DEC, 31, new_years_day_overflow),
+        ),
+        2008: (
+            # 2008: weird National Day Golden Week pattern.
+            (SEP, 29, national_day_2008_golden_week),
+            (SEP, 30, national_day_2008_golden_week),
+            (OCT, 4, national_day_2008_golden_week),
+            (OCT, 5, national_day_2008_golden_week),
+        ),
+        2010: (
+            # 2010: doesn't fit with existing observed pattern.
+            (SEP, 23, mid_autumn_festival_2010_special),
+            (SEP, 24, mid_autumn_festival_2010_special),
+        ),
+        2013: (
+            # 2013: doesn't fit with existing observed pattern.
+            (JAN, 2, new_years_day_overflow),
+            (JAN, 3, new_years_day_overflow),
+        ),
+        2018: (
+            # 2018: Overflow from 2019 Notice.
+            (DEC, 30, new_years_day_overflow),
+            (DEC, 31, new_years_day_overflow),
+        ),
+        2022: (
+            # 2022: Overflow from 2023 Notice.
+            (DEC, 31, new_years_day_overflow),
+        ),
+        2023: (
+            # 2023: Overflow from 2023 Notice.
+            (JAN, 2, new_years_day_overflow),
+        ),
+    }
 
     def __init__(self, *args, **kwargs):
         ChineseCalendarHolidays.__init__(self)
         InternationalHolidays.__init__(self)
         super().__init__(*args, **kwargs)
 
-    def _populate(self, year):
-        if year <= 1949:
+    def _add_observed_one_off_holidays(self, dt: date):
+        """
+        Based on 2002-2023 data, adds observance for one-off
+        holidays (New Year's Day, Tomb-Sweeping Day, ..., etc.)
+         - Monday -> TUE-WED (????-2007), [SAT]-[SUN] (2008-???)
+         - Tuesday -> WED-THU (????-2007), [SUN]-[MON] (2008-????)
+         - Wednesday -> None (????-2007), [MON]-[TUE] (2008-????)
+         - Thursday -> None (????-2007), FRI-SAT (2008-????)
+         - Friday -> SAT-SUN (????-????)
+         - Saturday -> [FRI]-SUN (2012-2019), SUN-MON (????-2011, 2020-????)
+         - Sunday -> MON-TUE (????-2007, 2012-2019), [SAT]-MON (2008-2011, 2020-????)
+
+         '[DAY]' denotes that this applies prior to the input date, with 'DAY' as after.
+        """
+
+        if self._is_monday(dt):
+            if self._year <= 2007:
+                # TUE-WED
+                self._add_holiday(self[dt], dt + td(days=+1))
+                self._add_holiday(self[dt], dt + td(days=+2))
+            else:
+                # [SAT]-[SUN]
+                self._add_holiday(self[dt], dt + td(days=-2))
+                self._add_holiday(self[dt], dt + td(days=-1))
+                if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                    # 2 Extra Days for May Day >= 2020:
+                    self._add_holiday(self[dt], dt + td(days=+1))
+                    self._add_holiday(self[dt], dt + td(days=+2))
+        elif self._is_tuesday(dt):
+            if self._year <= 2007:
+                # WED-THU
+                self._add_holiday(self[dt], dt + td(days=+1))
+                self._add_holiday(self[dt], dt + td(days=+2))
+            else:
+                # [SUN]-[MON]
+                self._add_holiday(self[dt], dt + td(days=-2))
+                self._add_holiday(self[dt], dt + td(days=-1))
+                if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                    # 2 Extra Days for May Day >= 2020:
+                    self._add_holiday(self[dt], dt + td(days=+1))
+                    self._add_holiday(self[dt], dt + td(days=+2))
+        elif self._is_wednesday(dt) and self._year >= 2008:
+            # [MON]-[TUE]
+            self._add_holiday(self[dt], dt + td(days=-2))
+            self._add_holiday(self[dt], dt + td(days=-1))
+            if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                # 2 Extra Days for May Day >= 2020:
+                self._add_holiday(self[dt], dt + td(days=+1))
+                self._add_holiday(self[dt], dt + td(days=+2))
+        elif self._is_thursday(dt) and self._year >= 2008:
+            # FRI-SAT
+            self._add_holiday(self[dt], dt + td(days=+1))
+            self._add_holiday(self[dt], dt + td(days=+2))
+            if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                # 2 Extra Days for May Day >= 2020:
+                self._add_holiday(self[dt], dt + td(days=+3))
+                self._add_holiday(self[dt], dt + td(days=+4))
+        elif self._is_friday(dt):
+            # SAT-SUN
+            self._add_holiday(self[dt], dt + td(days=+1))
+            self._add_holiday(self[dt], dt + td(days=+2))
+            if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                # 2 Extra Days for May Day >= 2020:
+                self._add_holiday(self[dt], dt + td(days=+3))
+                self._add_holiday(self[dt], dt + td(days=+4))
+        elif self._is_saturday(dt):
+            if self._year <= 2011 or self._year >= 2020:
+                # SUN-MON
+                self._add_holiday(self[dt], dt + td(days=+1))
+                self._add_holiday(self[dt], dt + td(days=+2))
+                if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                    # 2 Extra Days for May Day >= 2020:
+                    self._add_holiday(self[dt], dt + td(days=+3))
+                    self._add_holiday(self[dt], dt + td(days=+4))
+            elif 2012 <= self._year <= 2019:
+                # [FRI]-SUN
+                self._add_holiday(self[dt], dt + td(days=-1))
+                self._add_holiday(self[dt], dt + td(days=+1))
+        elif self._is_sunday(dt):
+            if self._year <= 2007 or 2012 <= self._year <= 2019:
+                # MON-TUE
+                self._add_holiday(self[dt], dt + td(days=+1))
+                self._add_holiday(self[dt], dt + td(days=+2))
+            elif 2008 <= self._year <= 2011 or self._year >= 2020:
+                # [SAT]-MON
+                self._add_holiday(self[dt], dt + td(days=-1))
+                self._add_holiday(self[dt], dt + td(days=+1))
+                if self._year >= 2020 and dt == date(self._year, MAY, 1):
+                    # 2 Extra Days for May Day >= 2020:
+                    self._add_holiday(self[dt], dt + td(days=+2))
+                    self._add_holiday(self[dt], dt + td(days=+3))
+
+    def _populate_public_holidays(self):
+        # Proclamation of the People's Republic of China on Oct 1, 1949.
+        if self._year <= 1949:
+            return None
+
+        # 元旦 (simp.) / 新年 (trad.)
+        # Status: In-Use (Statutory).
+        # Jan 1 in 1949, 1999, 2007, and 2013 revision.
+        # Consecutive Holidays are available from 2002, except in 2014/2016/2017/2018.
+
+        # New Year's Day.
+        jan_1 = self._add_new_years_day(tr("元旦"))
+
+        if (
+            self.observed
+            and (2002 <= self._year <= 2015 or self._year >= 2020)
+            and self._year not in {2008, 2013, 2014, 2023}
+        ):
+            self._add_observed_one_off_holidays(jan_1)
+
+        # 春节
+        # Status: In-Use (Statutory).
+        # Day 1-3 of Chinese New Year in 1949, 1999, 2007, and 2013 revision.
+
+        # Spring Festival Golden Weekend
+        # Checked with Official Notice from 2001-2023.
+        # Consecutive Holidays are available from 2000 (1999 rev.).
+
+        # Chinese New Year (Spring Festival).
+        chinese_new_year = tr("春节")
+        self._add_chinese_new_years_day(chinese_new_year)
+        self._add_chinese_new_years_day_two(chinese_new_year)
+        self._add_chinese_new_years_day_three(chinese_new_year)
+        if self.observed and self._year >= 2000:
+            # Non-Statutory.
+            self._add_chinese_new_years_day_four(chinese_new_year)
+            self._add_chinese_new_years_day_five(chinese_new_year)
+            self._add_chinese_new_years_day_six(chinese_new_year)
+            if 2008 <= self._year <= 2013 or self._year >= 2015:
+                self._add_chinese_new_years_eve(chinese_new_year)
+            else:
+                self._add_chinese_new_years_day_seven(chinese_new_year)
+
+        # 劳动节
+        # Status: In-Use (Statutory).
+        # May 1 in 1949, 1999, 2007, and 2013 revision.
+        # Additional Holidays (May 2-3) are available from 2000 (1999 rev.) - 2007 (2007 rev.).
+
+        # Labor Day Golden Weekend
+        # Checked with Official Notice from 2001-2023.
+        # Consecutive Holidays are available from 2002, with exception of ????-????.
+
+        # Labor Day.
+        labor_day = tr("劳动节")
+        may_1 = self._add_labor_day(labor_day)
+        if 2000 <= self._year <= 2007:
+            self._add_labor_day_two(labor_day)
+            self._add_labor_day_three(labor_day)
+            if self.observed:
+                # Non-Statutory.
+                self._add_holiday_may_4(labor_day)
+                self._add_holiday_may_5(labor_day)
+                self._add_holiday_may_6(labor_day)
+                self._add_holiday_may_7(labor_day)
+        elif self.observed and (
+            2008 <= self._year <= 2014 or self._year == 2018 or self._year >= 2020
+        ):
+            self._add_observed_one_off_holidays(may_1)
+
+        # 国庆节
+        # Status: In-Use (Statutory).
+        # Oct 1-2 in 1949, 1999, 2007, and 2013 revision
+        # Additional Holiday (Oct 3) is available from Sep 1999 (1999 rev.).
+
+        # National Day Golden Weekend
+        # Checked with Official Notice from 2001-2023.
+
+        # National Day.
+        national_day = tr("国庆节")
+        self._add_holiday_oct_1(national_day)
+        self._add_holiday_oct_2(national_day)
+        if self._year >= 1999:
+            self._add_holiday_oct_3(national_day)
+        if self.observed and 2000 <= self._year != 2008:
+            # Non-Statutory.
+            self._add_holiday_oct_4(national_day)
+            self._add_holiday_oct_5(national_day)
+            self._add_holiday_oct_6(national_day)
+            if self._year != 2023:
+                self._add_holiday_oct_7(national_day)
+
+        if self._year >= 2008:
+            # 清明节
+            # Status: In-Use (Statutory).
+            # Tomb-Sweeping Day in 2007, and 2013 revision.
+            # Consecutive Holidays are available from 2008, except in 2014/2015/2016/2019.
+
+            # Tomb-Sweeping Day.
+            qingming_festival = self._add_qingming_festival(tr("清明节"))
+
+            if self.observed and self._year not in {2014, 2015, 2016, 2019, 2023}:
+                # Non-Statutory.
+                self._add_observed_one_off_holidays(qingming_festival)
+
+            # 端午节
+            # Status: In-Use (Statutory).
+            # Dragon Boat Festival in 2007, and 2013 revision.
+            # Consecutive Holidays are available from 2008, except in 2014/2015/2018/2019/2023.
+
+            # Dragon Boat Festival.
+            dragon_boat_festival = self._add_dragon_boat_festival(tr("端午节"))
+
+            if self.observed and self._year not in {2014, 2015, 2018, 2019}:
+                # Non-Statutory.
+                self._add_observed_one_off_holidays(dragon_boat_festival)
+
+            # 中秋节
+            # Status: In-Use (Statutory).
+            # Mid-Autumn Festival in 2007, and 2013 revision.
+            # Consecutive Holidays are available from 2008, except in 2010/2014/2015/2018/2019.
+            # Extra Day (Oct 8) is instead aded to the National Day Week if overlaps.
+
+            # Mid-Autumn Festival.
+            mid_autumn_festival = self._add_mid_autumn_festival(tr("中秋节"))
+
+            if self.observed:
+                # Non-Statutory.
+                if mid_autumn_festival.month == OCT and 1 <= mid_autumn_festival.day <= 7:
+                    self._add_holiday_oct_8(national_day)
+                elif mid_autumn_festival == date(self._year, SEP, 29):
+                    self._add_holiday_sep_30(self[mid_autumn_festival])
+                elif self._year not in {2010, 2012, 2014, 2015, 2018, 2019, 2030, 2050, 2096}:
+                    # SEP 30's "no observance added" rule for 2012/2030/2050/2096 included.
+                    self._add_observed_one_off_holidays(mid_autumn_festival)
+
+    def _populate_half_day_holidays(self):
+        # No in lieus are given for this category.
+        # Proclamation of the People's Republic of China on Oct 1, 1949.
+        if self._year <= 1949:
             return None
-        super()._populate(year)
-
-        self._add_new_years_day("New Year's Day")
-
-        name = "Labour Day"
-        self._add_labor_day(name)
-        if 2000 <= year <= 2007:
-            self._add_labor_day_two(name)
-            self._add_labor_day_three(name)
-
-        name = "Chinese New Year (Spring Festival)"
-        self._add_chinese_new_years_day(name)
-        self._add_chinese_new_years_day_two(name)
-        if 2008 <= year <= 2013:
-            self._add_chinese_new_years_eve(name)
-        else:
-            self._add_chinese_new_years_day_three(name)
-
-        name = "National Day"
-        self._add_holiday_oct_1(name)
-        self._add_holiday_oct_2(name)
-        if year >= 2000:
-            self._add_holiday_oct_3(name)
-
-        if year >= 2008:
-            self._add_qingming_festival("Tomb-Sweeping Day")
-            self._add_dragon_boat_festival("Dragon Boat Festival")
-            self._add_mid_autumn_festival("Mid-Autumn Festival")
+
+        # International Women's Day.
+        self._add_womens_day(tr("国际妇女节"))
+
+        # Youth Day.
+        self._add_holiday_may_4(tr("五四青年节"))
+
+        # Children's Day.
+        self._add_childrens_day(tr("六一儿童节"))
+
+        # Army Day.
+        self._add_holiday_aug_1(tr("建军节"))
 
 
 class CN(China):
diff --git a/holidays/groups/chinese.py b/holidays/groups/chinese.py
--- a/holidays/groups/chinese.py
+++ b/holidays/groups/chinese.py
@@ -146,6 +146,26 @@ def _add_chinese_new_years_day_five(self, name) -> Optional[date]:
             name, self._chinese_calendar.lunar_new_year_date(self._year), days_delta=+4
         )
 
+    def _add_chinese_new_years_day_six(self, name) -> Optional[date]:
+        """
+        Add Chinese New Year's Day Six.
+
+        https://en.wikipedia.org/wiki/Chinese_New_Year
+        """
+        return self._add_chinese_calendar_holiday(
+            name, self._chinese_calendar.lunar_new_year_date(self._year), days_delta=+5
+        )
+
+    def _add_chinese_new_years_day_seven(self, name) -> Optional[date]:
+        """
+        Add Chinese New Year's Day Seven.
+
+        https://en.wikipedia.org/wiki/Chinese_New_Year
+        """
+        return self._add_chinese_calendar_holiday(
+            name, self._chinese_calendar.lunar_new_year_date(self._year), days_delta=+6
+        )
+
     def _add_qingming_festival(self, name) -> date:
         """
         Add Qingming Festival (15th day after the Spring Equinox).


Test patch:
diff --git a/tests/countries/test_china.py b/tests/countries/test_china.py
--- a/tests/countries/test_china.py
+++ b/tests/countries/test_china.py
@@ -9,93 +9,970 @@
 #  Website: https://github.com/dr-prodigy/python-holidays
 #  License: MIT (see LICENSE file)
 
-import unittest
-from datetime import date
-
-import holidays
-
-
-class TestChina(unittest.TestCase):
-    # https: // en.wikipedia.org / wiki / Public_holidays_in_China
-    def setUp(self):
-        self.holidays = holidays.CN()
-
-    def test_1950(self):
-        self.assertIn(date(1950, 1, 1), self.holidays)  # New Year's Day
-        # Chinese New Year day 1
-        self.assertIn(date(1950, 2, 17), self.holidays)
-        # Chinese New Year day 2
-        self.assertIn(date(1950, 2, 18), self.holidays)
-        # Chinese New Year day 3
-        self.assertIn(date(1950, 2, 19), self.holidays)
-        # Labour Day day 1
-        self.assertIn(date(1950, 5, 1), self.holidays)
-        # NO Labour Day day 2
-        self.assertNotIn(date(1950, 5, 2), self.holidays)
-        # NO Labour Day day 3
-        self.assertNotIn(date(1950, 5, 3), self.holidays)
-        # NO Dragon Boat Festival
-        self.assertNotIn(date(1950, 6, 19), self.holidays)
-        # NO Mid-Autumn Festival
-        self.assertNotIn(date(1950, 9, 26), self.holidays)
-        self.assertIn(date(1950, 10, 1), self.holidays)  # National Day day 1
-        self.assertIn(date(1950, 10, 2), self.holidays)  # National Day day 2
-        # NO National Day day 3
-        self.assertNotIn(date(1950, 10, 3), self.holidays)
-
-    def test_2005(self):
-        # New Year's Day
-        self.assertIn(date(2005, 1, 1), self.holidays)
-        # Chinese New Year day 1
-        self.assertIn(date(2005, 2, 9), self.holidays)
-        # Chinese New Year day 2
-        self.assertIn(date(2005, 2, 10), self.holidays)
-        # Chinese New Year day 3
-        self.assertIn(date(2005, 2, 11), self.holidays)
-        # NO Tomb-Sweeping Day
-        self.assertNotIn(date(2005, 4, 5), self.holidays)
-        # Labour Day day 1
-        self.assertIn(date(2005, 5, 1), self.holidays)
-        # Labour Day day 2
-        self.assertIn(date(2005, 5, 2), self.holidays)
-        # Labour Day day 3
-        self.assertIn(date(2005, 5, 3), self.holidays)
-        self.assertNotIn(date(2005, 6, 11), self.holidays)  # NO Dragon Boat Festival
-        # NO Mid-Autumn Festival
-        self.assertNotIn(date(2005, 9, 18), self.holidays)
-        # National Day day 1
-        self.assertIn(date(2005, 10, 1), self.holidays)
-        # National Day day 2
-        self.assertIn(date(2005, 10, 2), self.holidays)
-        # National Day day 3
-        self.assertIn(date(2005, 10, 3), self.holidays)
-
-    def test_chinese_new_year_2010(self):
-        self.assertIn(date(2010, 2, 13), self.holidays)
-        self.assertIn(date(2010, 2, 14), self.holidays)
-        self.assertIn(date(2010, 2, 15), self.holidays)
-
-    def test_2015(self):
-        # New Year's Day
-        self.assertIn(date(2015, 1, 1), self.holidays)
-        # Chinese New Year day 1
-        self.assertIn(date(2015, 2, 19), self.holidays)  # Chinese New Year day 2
-        self.assertIn(date(2015, 2, 20), self.holidays)
-        # Chinese New Year day 3
-        self.assertIn(date(2015, 2, 21), self.holidays)
-        # Tomb-Sweeping Day
-        self.assertIn(date(2015, 4, 5), self.holidays)
-        # Labour Day
-        self.assertIn(date(2015, 5, 1), self.holidays)
-        # NO Labour Day day 2
-        self.assertNotIn(date(2015, 5, 2), self.holidays)
-        # NO Labour Day day 3
-        self.assertNotIn(date(2015, 5, 3), self.holidays)
-        self.assertIn(date(2015, 6, 20), self.holidays)  # Dragon Boat Festival
-        self.assertIn(date(2015, 9, 27), self.holidays)  # Mid-Autumn Festival
-        self.assertIn(date(2015, 10, 1), self.holidays)  # National Day day 1
-        self.assertIn(date(2015, 10, 2), self.holidays)  # National Day day 2
-        self.assertIn(date(2015, 10, 3), self.holidays)  # National Day day 3
-
-    def test_pre_1950(self):
-        self.assertNotIn(date(1949, 1, 1), self.holidays)
+from holidays.constants import HALF_DAY, PUBLIC
+from holidays.countries.china import China, CN, CHN
+from tests.common import TestCase
+
+
+class TestChina(TestCase):
+    @classmethod
+    def setUpClass(cls):
+        super().setUpClass(China, years=range(1950, 2051))
+
+    def test_country_aliases(self):
+        self.assertCountryAliases(China, CN, CHN)
+
+    def test_no_holidays(self):
+        self.assertNoHolidays(China(years=1949))
+        self.assertNoHolidays(China(years=1949, categories=(HALF_DAY,)))
+
+    def test_national_day(self):
+        name = "国庆节"
+        for year in range(1950, 1999):
+            self.assertHolidayName(name, (f"{year}-10-01", f"{year}-10-02"))
+        for year in range(1999, 2051):
+            self.assertHolidayName(name, (f"{year}-10-01", f"{year}-10-02", f"{year}-10-03"))
+
+        self.assertNoNonObservedHoliday(
+            "2020-10-04",
+            "2020-10-05",
+            "2020-10-06",
+            "2020-10-07",
+            "2020-10-08",
+            "2021-10-04",
+            "2021-10-05",
+            "2021-10-06",
+            "2021-10-07",
+            "2022-10-04",
+            "2022-10-05",
+            "2022-10-06",
+            "2022-10-07",
+            "2023-09-30",
+            "2023-10-04",
+            "2023-10-05",
+            "2023-10-06",
+        )
+
+    def test_1950_public_holiday(self):
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=1950),
+            ("1950-01-01", "元旦"),
+            ("1950-02-17", "春节"),
+            ("1950-02-18", "春节"),
+            ("1950-02-19", "春节"),
+            ("1950-05-01", "劳动节"),
+            ("1950-10-01", "国庆节"),
+            ("1950-10-02", "国庆节"),
+        )
+
+    def test_1999_public_holiday(self):
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=1999),
+            ("1999-01-01", "元旦"),
+            ("1999-02-16", "春节"),
+            ("1999-02-17", "春节"),
+            ("1999-02-18", "春节"),
+            ("1999-05-01", "劳动节"),
+            ("1999-10-01", "国庆节"),
+            ("1999-10-02", "国庆节"),
+            ("1999-10-03", "国庆节"),
+        )
+
+    def test_2001_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2001年春节、“五一”、“十一”放假安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2001),
+            # New Year is not listed, but should be there according to 1999 revision.
+            ("2001-01-01", "元旦"),
+            ("2001-01-24", "春节"),
+            ("2001-01-25", "春节"),
+            ("2001-01-26", "春节"),
+            ("2001-01-27", "春节"),
+            ("2001-01-28", "春节"),
+            ("2001-01-29", "春节"),
+            ("2001-01-30", "春节"),
+            ("2001-05-01", "劳动节"),
+            ("2001-05-02", "劳动节"),
+            ("2001-05-03", "劳动节"),
+            ("2001-05-04", "劳动节"),
+            ("2001-05-05", "劳动节"),
+            ("2001-05-06", "劳动节"),
+            ("2001-05-07", "劳动节"),
+            ("2001-10-01", "国庆节"),
+            ("2001-10-02", "国庆节"),
+            ("2001-10-03", "国庆节"),
+            ("2001-10-04", "国庆节"),
+            ("2001-10-05", "国庆节"),
+            ("2001-10-06", "国庆节"),
+            ("2001-10-07", "国庆节"),
+        )
+
+    def test_2002_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2002年部分节假日休息安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2002),
+            ("2002-01-01", "元旦"),
+            ("2002-01-02", "元旦"),
+            ("2002-01-03", "元旦"),
+            ("2002-02-12", "春节"),
+            ("2002-02-13", "春节"),
+            ("2002-02-14", "春节"),
+            ("2002-02-15", "春节"),
+            ("2002-02-16", "春节"),
+            ("2002-02-17", "春节"),
+            ("2002-02-18", "春节"),
+            ("2002-05-01", "劳动节"),
+            ("2002-05-02", "劳动节"),
+            ("2002-05-03", "劳动节"),
+            ("2002-05-04", "劳动节"),
+            ("2002-05-05", "劳动节"),
+            ("2002-05-06", "劳动节"),
+            ("2002-05-07", "劳动节"),
+            ("2002-10-01", "国庆节"),
+            ("2002-10-02", "国庆节"),
+            ("2002-10-03", "国庆节"),
+            ("2002-10-04", "国庆节"),
+            ("2002-10-05", "国庆节"),
+            ("2002-10-06", "国庆节"),
+            ("2002-10-07", "国庆节"),
+        )
+
+    def test_2003_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2003年部分节假日休息安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2003),
+            ("2003-01-01", "元旦"),
+            ("2003-02-01", "春节"),
+            ("2003-02-02", "春节"),
+            ("2003-02-03", "春节"),
+            ("2003-02-04", "春节"),
+            ("2003-02-05", "春节"),
+            ("2003-02-06", "春节"),
+            ("2003-02-07", "春节"),
+            ("2003-05-01", "劳动节"),
+            ("2003-05-02", "劳动节"),
+            ("2003-05-03", "劳动节"),
+            ("2003-05-04", "劳动节"),
+            ("2003-05-05", "劳动节"),
+            ("2003-05-06", "劳动节"),
+            ("2003-05-07", "劳动节"),
+            ("2003-10-01", "国庆节"),
+            ("2003-10-02", "国庆节"),
+            ("2003-10-03", "国庆节"),
+            ("2003-10-04", "国庆节"),
+            ("2003-10-05", "国庆节"),
+            ("2003-10-06", "国庆节"),
+            ("2003-10-07", "国庆节"),
+        )
+
+    def test_2004_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2004年部分节假日安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2004),
+            ("2004-01-01", "元旦"),
+            ("2004-01-22", "春节"),
+            ("2004-01-23", "春节"),
+            ("2004-01-24", "春节"),
+            ("2004-01-25", "春节"),
+            ("2004-01-26", "春节"),
+            ("2004-01-27", "春节"),
+            ("2004-01-28", "春节"),
+            ("2004-05-01", "劳动节"),
+            ("2004-05-02", "劳动节"),
+            ("2004-05-03", "劳动节"),
+            ("2004-05-04", "劳动节"),
+            ("2004-05-05", "劳动节"),
+            ("2004-05-06", "劳动节"),
+            ("2004-05-07", "劳动节"),
+            ("2004-10-01", "国庆节"),
+            ("2004-10-02", "国庆节"),
+            ("2004-10-03", "国庆节"),
+            ("2004-10-04", "国庆节"),
+            ("2004-10-05", "国庆节"),
+            ("2004-10-06", "国庆节"),
+            ("2004-10-07", "国庆节"),
+        )
+
+    def test_2005_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2005年部分节假日安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2005),
+            ("2005-01-01", "元旦"),
+            ("2005-01-02", "元旦"),
+            ("2005-01-03", "元旦"),
+            ("2005-02-09", "春节"),
+            ("2005-02-10", "春节"),
+            ("2005-02-11", "春节"),
+            ("2005-02-12", "春节"),
+            ("2005-02-13", "春节"),
+            ("2005-02-14", "春节"),
+            ("2005-02-15", "春节"),
+            ("2005-05-01", "劳动节"),
+            ("2005-05-02", "劳动节"),
+            ("2005-05-03", "劳动节"),
+            ("2005-05-04", "劳动节"),
+            ("2005-05-05", "劳动节"),
+            ("2005-05-06", "劳动节"),
+            ("2005-05-07", "劳动节"),
+            ("2005-10-01", "国庆节"),
+            ("2005-10-02", "国庆节"),
+            ("2005-10-03", "国庆节"),
+            ("2005-10-04", "国庆节"),
+            ("2005-10-05", "国庆节"),
+            ("2005-10-06", "国庆节"),
+            ("2005-10-07", "国庆节"),
+        )
+
+    def test_2006_public_holiday(self):
+        # https://zh.wikisource.org/wiki/国务院办公厅关于2006年部分节假日安排的通知
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2006),
+            ("2006-01-01", "元旦"),
+            ("2006-01-02", "元旦"),
+            ("2006-01-03", "元旦"),
+            ("2006-01-29", "春节"),
+            ("2006-01-30", "春节"),
+            ("2006-01-31", "春节"),
+            ("2006-02-01", "春节"),
+            ("2006-02-02", "春节"),
+            ("2006-02-03", "春节"),
+            ("2006-02-04", "春节"),
+            ("2006-05-01", "劳动节"),
+            ("2006-05-02", "劳动节"),
+            ("2006-05-03", "劳动节"),
+            ("2006-05-04", "劳动节"),
+            ("2006-05-05", "劳动节"),
+            ("2006-05-06", "劳动节"),
+            ("2006-05-07", "劳动节"),
+            ("2006-10-01", "国庆节"),
+            ("2006-10-02", "国庆节"),
+            ("2006-10-03", "国庆节"),
+            ("2006-10-04", "国庆节"),
+            ("2006-10-05", "国庆节"),
+            ("2006-10-06", "国庆节"),
+            ("2006-10-07", "国庆节"),
+        )
+
+    def test_2007_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2007/content_503397.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2007),
+            ("2007-01-01", "元旦"),
+            ("2007-01-02", "元旦"),
+            ("2007-01-03", "元旦"),
+            ("2007-02-18", "春节"),
+            ("2007-02-19", "春节"),
+            ("2007-02-20", "春节"),
+            ("2007-02-21", "春节"),
+            ("2007-02-22", "春节"),
+            ("2007-02-23", "春节"),
+            ("2007-02-24", "春节"),
+            ("2007-05-01", "劳动节"),
+            ("2007-05-02", "劳动节"),
+            ("2007-05-03", "劳动节"),
+            ("2007-05-04", "劳动节"),
+            ("2007-05-05", "劳动节"),
+            ("2007-05-06", "劳动节"),
+            ("2007-05-07", "劳动节"),
+            ("2007-10-01", "国庆节"),
+            ("2007-10-02", "国庆节"),
+            ("2007-10-03", "国庆节"),
+            ("2007-10-04", "国庆节"),
+            ("2007-10-05", "国庆节"),
+            ("2007-10-06", "国庆节"),
+            ("2007-10-07", "国庆节"),
+            # From 2008 Notice.
+            ("2007-12-30", "元旦"),
+            ("2007-12-31", "元旦"),
+        )
+
+    def test_2008_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2008/content_859870.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2008),
+            ("2008-01-01", "元旦"),
+            ("2008-02-06", "春节"),
+            ("2008-02-07", "春节"),
+            ("2008-02-08", "春节"),
+            ("2008-02-09", "春节"),
+            ("2008-02-10", "春节"),
+            ("2008-02-11", "春节"),
+            ("2008-02-12", "春节"),
+            ("2008-04-04", "清明节"),
+            ("2008-04-05", "清明节"),
+            ("2008-04-06", "清明节"),
+            ("2008-05-01", "劳动节"),
+            ("2008-05-02", "劳动节"),
+            ("2008-05-03", "劳动节"),
+            ("2008-06-07", "端午节"),
+            ("2008-06-08", "端午节"),
+            ("2008-06-09", "端午节"),
+            ("2008-09-13", "中秋节"),
+            ("2008-09-14", "中秋节"),
+            ("2008-09-15", "中秋节"),
+            ("2008-09-29", "国庆节"),
+            ("2008-09-30", "国庆节"),
+            ("2008-10-01", "国庆节"),
+            ("2008-10-02", "国庆节"),
+            ("2008-10-03", "国庆节"),
+            ("2008-10-04", "国庆节"),
+            ("2008-10-05", "国庆节"),
+        )
+
+    def test_2009_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2008/content_1175823.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2009),
+            ("2009-01-01", "元旦"),
+            ("2009-01-02", "元旦"),
+            ("2009-01-03", "元旦"),
+            ("2009-01-25", "春节"),
+            ("2009-01-26", "春节"),
+            ("2009-01-27", "春节"),
+            ("2009-01-28", "春节"),
+            ("2009-01-29", "春节"),
+            ("2009-01-30", "春节"),
+            ("2009-01-31", "春节"),
+            ("2009-04-04", "清明节"),
+            ("2009-04-05", "清明节"),
+            ("2009-04-06", "清明节"),
+            ("2009-05-01", "劳动节"),
+            ("2009-05-02", "劳动节"),
+            ("2009-05-03", "劳动节"),
+            ("2009-05-28", "端午节"),
+            ("2009-05-29", "端午节"),
+            ("2009-05-30", "端午节"),
+            ("2009-10-01", "国庆节"),
+            ("2009-10-02", "国庆节"),
+            ("2009-10-03", "中秋节; 国庆节"),
+            ("2009-10-04", "国庆节"),
+            ("2009-10-05", "国庆节"),
+            ("2009-10-06", "国庆节"),
+            ("2009-10-07", "国庆节"),
+            ("2009-10-08", "国庆节"),
+        )
+
+    def test_2010_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2009/content_1487011.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2010),
+            ("2010-01-01", "元旦"),
+            ("2010-01-02", "元旦"),
+            ("2010-01-03", "元旦"),
+            ("2010-02-13", "春节"),
+            ("2010-02-14", "春节"),
+            ("2010-02-15", "春节"),
+            ("2010-02-16", "春节"),
+            ("2010-02-17", "春节"),
+            ("2010-02-18", "春节"),
+            ("2010-02-19", "春节"),
+            ("2010-04-03", "清明节"),
+            ("2010-04-04", "清明节"),
+            ("2010-04-05", "清明节"),
+            ("2010-05-01", "劳动节"),
+            ("2010-05-02", "劳动节"),
+            ("2010-05-03", "劳动节"),
+            ("2010-06-14", "端午节"),
+            ("2010-06-15", "端午节"),
+            ("2010-06-16", "端午节"),
+            ("2010-09-22", "中秋节"),
+            ("2010-09-23", "中秋节"),
+            ("2010-09-24", "中秋节"),
+            ("2010-10-01", "国庆节"),
+            ("2010-10-02", "国庆节"),
+            ("2010-10-03", "国庆节"),
+            ("2010-10-04", "国庆节"),
+            ("2010-10-05", "国庆节"),
+            ("2010-10-06", "国庆节"),
+            ("2010-10-07", "国庆节"),
+        )
+
+    def test_2011_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2010/content_1765282.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2011),
+            ("2011-01-01", "元旦"),
+            ("2011-01-02", "元旦"),
+            ("2011-01-03", "元旦"),
+            ("2011-02-02", "春节"),
+            ("2011-02-03", "春节"),
+            ("2011-02-04", "春节"),
+            ("2011-02-05", "春节"),
+            ("2011-02-06", "春节"),
+            ("2011-02-07", "春节"),
+            ("2011-02-08", "春节"),
+            ("2011-04-03", "清明节"),
+            ("2011-04-04", "清明节"),
+            ("2011-04-05", "清明节"),
+            ("2011-04-30", "劳动节"),
+            ("2011-05-01", "劳动节"),
+            ("2011-05-02", "劳动节"),
+            ("2011-06-04", "端午节"),
+            ("2011-06-05", "端午节"),
+            ("2011-06-06", "端午节"),
+            ("2011-09-10", "中秋节"),
+            ("2011-09-11", "中秋节"),
+            ("2011-09-12", "中秋节"),
+            ("2011-10-01", "国庆节"),
+            ("2011-10-02", "国庆节"),
+            ("2011-10-03", "国庆节"),
+            ("2011-10-04", "国庆节"),
+            ("2011-10-05", "国庆节"),
+            ("2011-10-06", "国庆节"),
+            ("2011-10-07", "国庆节"),
+        )
+
+    def test_2012_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2011/content_2020918.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2012),
+            ("2012-01-01", "元旦"),
+            ("2012-01-02", "元旦"),
+            ("2012-01-03", "元旦"),
+            ("2012-01-22", "春节"),
+            ("2012-01-23", "春节"),
+            ("2012-01-24", "春节"),
+            ("2012-01-25", "春节"),
+            ("2012-01-26", "春节"),
+            ("2012-01-27", "春节"),
+            ("2012-01-28", "春节"),
+            ("2012-04-02", "清明节"),
+            ("2012-04-03", "清明节"),
+            ("2012-04-04", "清明节"),
+            ("2012-04-29", "劳动节"),
+            ("2012-04-30", "劳动节"),
+            ("2012-05-01", "劳动节"),
+            ("2012-06-22", "端午节"),
+            ("2012-06-23", "端午节"),
+            ("2012-06-24", "端午节"),
+            ("2012-09-30", "中秋节"),
+            ("2012-10-01", "国庆节"),
+            ("2012-10-02", "国庆节"),
+            ("2012-10-03", "国庆节"),
+            ("2012-10-04", "国庆节"),
+            ("2012-10-05", "国庆节"),
+            ("2012-10-06", "国庆节"),
+            ("2012-10-07", "国庆节"),
+        )
+
+    def test_2013_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2012/content_2292057.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2013),
+            ("2013-01-01", "元旦"),
+            ("2013-01-02", "元旦"),
+            ("2013-01-03", "元旦"),
+            ("2013-02-09", "春节"),
+            ("2013-02-10", "春节"),
+            ("2013-02-11", "春节"),
+            ("2013-02-12", "春节"),
+            ("2013-02-13", "春节"),
+            ("2013-02-14", "春节"),
+            ("2013-02-15", "春节"),
+            ("2013-04-04", "清明节"),
+            ("2013-04-05", "清明节"),
+            ("2013-04-06", "清明节"),
+            ("2013-04-29", "劳动节"),
+            ("2013-04-30", "劳动节"),
+            ("2013-05-01", "劳动节"),
+            ("2013-06-10", "端午节"),
+            ("2013-06-11", "端午节"),
+            ("2013-06-12", "端午节"),
+            ("2013-09-19", "中秋节"),
+            ("2013-09-20", "中秋节"),
+            ("2013-09-21", "中秋节"),
+            ("2013-10-01", "国庆节"),
+            ("2013-10-02", "国庆节"),
+            ("2013-10-03", "国庆节"),
+            ("2013-10-04", "国庆节"),
+            ("2013-10-05", "国庆节"),
+            ("2013-10-06", "国庆节"),
+            ("2013-10-07", "国庆节"),
+        )
+
+    def test_2014_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2014/content_2561299.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2014),
+            ("2014-01-01", "元旦"),
+            ("2014-01-31", "春节"),
+            ("2014-02-01", "春节"),
+            ("2014-02-02", "春节"),
+            ("2014-02-03", "春节"),
+            ("2014-02-04", "春节"),
+            ("2014-02-05", "春节"),
+            ("2014-02-06", "春节"),
+            ("2014-04-05", "清明节"),
+            ("2014-05-01", "劳动节"),
+            ("2014-05-02", "劳动节"),
+            ("2014-05-03", "劳动节"),
+            ("2014-06-02", "端午节"),
+            ("2014-09-08", "中秋节"),
+            ("2014-10-01", "国庆节"),
+            ("2014-10-02", "国庆节"),
+            ("2014-10-03", "国庆节"),
+            ("2014-10-04", "国庆节"),
+            ("2014-10-05", "国庆节"),
+            ("2014-10-06", "国庆节"),
+            ("2014-10-07", "国庆节"),
+        )
+
+    def test_2015_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2015/content_2799019.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2015),
+            ("2015-01-01", "元旦"),
+            ("2015-01-02", "元旦"),
+            ("2015-01-03", "元旦"),
+            ("2015-02-18", "春节"),
+            ("2015-02-19", "春节"),
+            ("2015-02-20", "春节"),
+            ("2015-02-21", "春节"),
+            ("2015-02-22", "春节"),
+            ("2015-02-23", "春节"),
+            ("2015-02-24", "春节"),
+            ("2015-04-05", "清明节"),
+            ("2015-05-01", "劳动节"),
+            ("2015-06-20", "端午节"),
+            ("2015-09-27", "中秋节"),
+            ("2015-10-01", "国庆节"),
+            ("2015-10-02", "国庆节"),
+            ("2015-10-03", "国庆节"),
+            ("2015-10-04", "国庆节"),
+            ("2015-10-05", "国庆节"),
+            ("2015-10-06", "国庆节"),
+            ("2015-10-07", "国庆节"),
+        )
+
+    def test_2016_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2016/content_2979719.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2016),
+            ("2016-01-01", "元旦"),
+            ("2016-02-07", "春节"),
+            ("2016-02-08", "春节"),
+            ("2016-02-09", "春节"),
+            ("2016-02-10", "春节"),
+            ("2016-02-11", "春节"),
+            ("2016-02-12", "春节"),
+            ("2016-02-13", "春节"),
+            ("2016-04-04", "清明节"),
+            ("2016-05-01", "劳动节"),
+            ("2016-06-09", "端午节"),
+            ("2016-06-10", "端午节"),
+            ("2016-06-11", "端午节"),
+            ("2016-09-15", "中秋节"),
+            ("2016-09-16", "中秋节"),
+            ("2016-09-17", "中秋节"),
+            ("2016-10-01", "国庆节"),
+            ("2016-10-02", "国庆节"),
+            ("2016-10-03", "国庆节"),
+            ("2016-10-04", "国庆节"),
+            ("2016-10-05", "国庆节"),
+            ("2016-10-06", "国庆节"),
+            ("2016-10-07", "国庆节"),
+        )
+
+    def test_2017_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2016/content_5148793.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2017),
+            ("2017-01-01", "元旦"),
+            ("2017-01-27", "春节"),
+            ("2017-01-28", "春节"),
+            ("2017-01-29", "春节"),
+            ("2017-01-30", "春节"),
+            ("2017-01-31", "春节"),
+            ("2017-02-01", "春节"),
+            ("2017-02-02", "春节"),
+            ("2017-04-02", "清明节"),
+            ("2017-04-03", "清明节"),
+            ("2017-04-04", "清明节"),
+            ("2017-05-01", "劳动节"),
+            ("2017-05-28", "端午节"),
+            ("2017-05-29", "端午节"),
+            ("2017-05-30", "端午节"),
+            ("2017-10-01", "国庆节"),
+            ("2017-10-02", "国庆节"),
+            ("2017-10-03", "国庆节"),
+            ("2017-10-04", "中秋节; 国庆节"),
+            ("2017-10-05", "国庆节"),
+            ("2017-10-06", "国庆节"),
+            ("2017-10-07", "国庆节"),
+            ("2017-10-08", "国庆节"),
+        )
+
+    def test_2018_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2017/content_5248221.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2018),
+            ("2018-01-01", "元旦"),
+            ("2018-02-15", "春节"),
+            ("2018-02-16", "春节"),
+            ("2018-02-17", "春节"),
+            ("2018-02-18", "春节"),
+            ("2018-02-19", "春节"),
+            ("2018-02-20", "春节"),
+            ("2018-02-21", "春节"),
+            ("2018-04-05", "清明节"),
+            ("2018-04-06", "清明节"),
+            ("2018-04-07", "清明节"),
+            ("2018-04-29", "劳动节"),
+            ("2018-04-30", "劳动节"),
+            ("2018-05-01", "劳动节"),
+            ("2018-06-18", "端午节"),
+            ("2018-09-24", "中秋节"),
+            ("2018-10-01", "国庆节"),
+            ("2018-10-02", "国庆节"),
+            ("2018-10-03", "国庆节"),
+            ("2018-10-04", "国庆节"),
+            ("2018-10-05", "国庆节"),
+            ("2018-10-06", "国庆节"),
+            ("2018-10-07", "国庆节"),
+            # From 2019 Notice.
+            ("2018-12-30", "元旦"),
+            ("2018-12-31", "元旦"),
+        )
+
+    def test_2019_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2018/content_5350046.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2019),
+            ("2019-01-01", "元旦"),
+            ("2019-02-04", "春节"),
+            ("2019-02-05", "春节"),
+            ("2019-02-06", "春节"),
+            ("2019-02-07", "春节"),
+            ("2019-02-08", "春节"),
+            ("2019-02-09", "春节"),
+            ("2019-02-10", "春节"),
+            ("2019-04-05", "清明节"),
+            ("2019-05-01", "劳动节"),
+            ("2019-06-07", "端午节"),
+            ("2019-09-13", "中秋节"),
+            ("2019-10-01", "国庆节"),
+            ("2019-10-02", "国庆节"),
+            ("2019-10-03", "国庆节"),
+            ("2019-10-04", "国庆节"),
+            ("2019-10-05", "国庆节"),
+            ("2019-10-06", "国庆节"),
+            ("2019-10-07", "国庆节"),
+        )
+
+    def test_2020_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2019/content_5459138.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2020),
+            ("2020-01-01", "元旦"),
+            ("2020-01-24", "春节"),
+            ("2020-01-25", "春节"),
+            ("2020-01-26", "春节"),
+            ("2020-01-27", "春节"),
+            ("2020-01-28", "春节"),
+            ("2020-01-29", "春节"),
+            ("2020-01-30", "春节"),
+            ("2020-04-04", "清明节"),
+            ("2020-04-05", "清明节"),
+            ("2020-04-06", "清明节"),
+            ("2020-05-01", "劳动节"),
+            ("2020-05-02", "劳动节"),
+            ("2020-05-03", "劳动节"),
+            ("2020-05-04", "劳动节"),
+            ("2020-05-05", "劳动节"),
+            ("2020-06-25", "端午节"),
+            ("2020-06-26", "端午节"),
+            ("2020-06-27", "端午节"),
+            ("2020-10-01", "中秋节; 国庆节"),
+            ("2020-10-02", "国庆节"),
+            ("2020-10-03", "国庆节"),
+            ("2020-10-04", "国庆节"),
+            ("2020-10-05", "国庆节"),
+            ("2020-10-06", "国庆节"),
+            ("2020-10-07", "国庆节"),
+            ("2020-10-08", "国庆节"),
+        )
+
+    def test_2021_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2020/content_5567750.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2021),
+            ("2021-01-01", "元旦"),
+            ("2021-01-02", "元旦"),
+            ("2021-01-03", "元旦"),
+            ("2021-02-11", "春节"),
+            ("2021-02-12", "春节"),
+            ("2021-02-13", "春节"),
+            ("2021-02-14", "春节"),
+            ("2021-02-15", "春节"),
+            ("2021-02-16", "春节"),
+            ("2021-02-17", "春节"),
+            ("2021-04-03", "清明节"),
+            ("2021-04-04", "清明节"),
+            ("2021-04-05", "清明节"),
+            ("2021-05-01", "劳动节"),
+            ("2021-05-02", "劳动节"),
+            ("2021-05-03", "劳动节"),
+            ("2021-05-04", "劳动节"),
+            ("2021-05-05", "劳动节"),
+            ("2021-06-12", "端午节"),
+            ("2021-06-13", "端午节"),
+            ("2021-06-14", "端午节"),
+            ("2021-09-19", "中秋节"),
+            ("2021-09-20", "中秋节"),
+            ("2021-09-21", "中秋节"),
+            ("2021-10-01", "国庆节"),
+            ("2021-10-02", "国庆节"),
+            ("2021-10-03", "国庆节"),
+            ("2021-10-04", "国庆节"),
+            ("2021-10-05", "国庆节"),
+            ("2021-10-06", "国庆节"),
+            ("2021-10-07", "国庆节"),
+        )
+
+    def test_2022_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2021/content_5651728.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2022),
+            ("2022-01-01", "元旦"),
+            ("2022-01-02", "元旦"),
+            ("2022-01-03", "元旦"),
+            ("2022-01-31", "春节"),
+            ("2022-02-01", "春节"),
+            ("2022-02-02", "春节"),
+            ("2022-02-03", "春节"),
+            ("2022-02-04", "春节"),
+            ("2022-02-05", "春节"),
+            ("2022-02-06", "春节"),
+            ("2022-04-03", "清明节"),
+            ("2022-04-04", "清明节"),
+            ("2022-04-05", "清明节"),
+            ("2022-04-30", "劳动节"),
+            ("2022-05-01", "劳动节"),
+            ("2022-05-02", "劳动节"),
+            ("2022-05-03", "劳动节"),
+            ("2022-05-04", "劳动节"),
+            ("2022-06-03", "端午节"),
+            ("2022-06-04", "端午节"),
+            ("2022-06-05", "端午节"),
+            ("2022-09-10", "中秋节"),
+            ("2022-09-11", "中秋节"),
+            ("2022-09-12", "中秋节"),
+            ("2022-10-01", "国庆节"),
+            ("2022-10-02", "国庆节"),
+            ("2022-10-03", "国庆节"),
+            ("2022-10-04", "国庆节"),
+            ("2022-10-05", "国庆节"),
+            ("2022-10-06", "国庆节"),
+            ("2022-10-07", "国庆节"),
+            # From 2023 Notice.
+            ("2022-12-31", "元旦"),
+        )
+
+    def test_2023_public_holiday(self):
+        # https://www.gov.cn/gongbao/content/2023/content_5736714.htm
+        self.assertHolidays(
+            China(categories=(PUBLIC,), years=2023),
+            ("2023-01-01", "元旦"),
+            ("2023-01-02", "元旦"),
+            ("2023-01-21", "春节"),
+            ("2023-01-22", "春节"),
+            ("2023-01-23", "春节"),
+            ("2023-01-24", "春节"),
+            ("2023-01-25", "春节"),
+            ("2023-01-26", "春节"),
+            ("2023-01-27", "春节"),
+            ("2023-04-05", "清明节"),
+            ("2023-04-29", "劳动节"),
+            ("2023-04-30", "劳动节"),
+            ("2023-05-01", "劳动节"),
+            ("2023-05-02", "劳动节"),
+            ("2023-05-03", "劳动节"),
+            ("2023-06-22", "端午节"),
+            ("2023-06-23", "端午节"),
+            ("2023-06-24", "端午节"),
+            ("2023-09-29", "中秋节"),
+            ("2023-09-30", "中秋节"),
+            ("2023-10-01", "国庆节"),
+            ("2023-10-02", "国庆节"),
+            ("2023-10-03", "国庆节"),
+            ("2023-10-04", "国庆节"),
+            ("2023-10-05", "国庆节"),
+            ("2023-10-06", "国庆节"),
+        )
+
+    def test_2022_half_day_holiday(self):
+        self.assertHolidays(
+            China(categories=(HALF_DAY,), years=2022),
+            ("2022-03-08", "国际妇女节"),
+            ("2022-05-04", "五四青年节"),
+            ("2022-06-01", "六一儿童节"),
+            ("2022-08-01", "建军节"),
+        )
+
+    def test_2023_half_day_holiday(self):
+        self.assertHolidays(
+            China(categories=(HALF_DAY,), years=2023),
+            ("2023-03-08", "国际妇女节"),
+            ("2023-05-04", "五四青年节"),
+            ("2023-06-01", "六一儿童节"),
+            ("2023-08-01", "建军节"),
+        )
+
+    def test_l10n_default(self):
+        self.assertLocalizedHolidays(
+            ("2022-01-01", "元旦"),
+            ("2022-01-02", "元旦"),
+            ("2022-01-03", "元旦"),
+            ("2022-01-31", "春节"),
+            ("2022-02-01", "春节"),
+            ("2022-02-02", "春节"),
+            ("2022-02-03", "春节"),
+            ("2022-02-04", "春节"),
+            ("2022-02-05", "春节"),
+            ("2022-02-06", "春节"),
+            ("2022-03-08", "国际妇女节"),
+            ("2022-04-03", "清明节"),
+            ("2022-04-04", "清明节"),
+            ("2022-04-05", "清明节"),
+            ("2022-04-30", "劳动节"),
+            ("2022-05-01", "劳动节"),
+            ("2022-05-02", "劳动节"),
+            ("2022-05-03", "劳动节"),
+            ("2022-05-04", "五四青年节; 劳动节"),
+            ("2022-06-01", "六一儿童节"),
+            ("2022-06-03", "端午节"),
+            ("2022-06-04", "端午节"),
+            ("2022-06-05", "端午节"),
+            ("2022-08-01", "建军节"),
+            ("2022-09-10", "中秋节"),
+            ("2022-09-11", "中秋节"),
+            ("2022-09-12", "中秋节"),
+            ("2022-10-01", "国庆节"),
+            ("2022-10-02", "国庆节"),
+            ("2022-10-03", "国庆节"),
+            ("2022-10-04", "国庆节"),
+            ("2022-10-05", "国庆节"),
+            ("2022-10-06", "国庆节"),
+            ("2022-10-07", "国庆节"),
+            ("2022-12-31", "元旦"),
+        )
+
+    def test_l10n_en_us(self):
+        self.assertLocalizedHolidays(
+            "en_US",
+            ("2022-01-01", "New Year's Day"),
+            ("2022-01-02", "New Year's Day"),
+            ("2022-01-03", "New Year's Day"),
+            ("2022-01-31", "Chinese New Year (Spring Festival)"),
+            ("2022-02-01", "Chinese New Year (Spring Festival)"),
+            ("2022-02-02", "Chinese New Year (Spring Festival)"),
+            ("2022-02-03", "Chinese New Year (Spring Festival)"),
+            ("2022-02-04", "Chinese New Year (Spring Festival)"),
+            ("2022-02-05", "Chinese New Year (Spring Festival)"),
+            ("2022-02-06", "Chinese New Year (Spring Festival)"),
+            ("2022-03-08", "International Women's Day"),
+            ("2022-04-03", "Tomb-Sweeping Day"),
+            ("2022-04-04", "Tomb-Sweeping Day"),
+            ("2022-04-05", "Tomb-Sweeping Day"),
+            ("2022-04-30", "Labor Day"),
+            ("2022-05-01", "Labor Day"),
+            ("2022-05-02", "Labor Day"),
+            ("2022-05-03", "Labor Day"),
+            ("2022-05-04", "Labor Day; Youth Day"),
+            ("2022-06-01", "Children's Day"),
+            ("2022-06-03", "Dragon Boat Festival"),
+            ("2022-06-04", "Dragon Boat Festival"),
+            ("2022-06-05", "Dragon Boat Festival"),
+            ("2022-08-01", "Army Day"),
+            ("2022-09-10", "Mid-Autumn Festival"),
+            ("2022-09-11", "Mid-Autumn Festival"),
+            ("2022-09-12", "Mid-Autumn Festival"),
+            ("2022-10-01", "National Day"),
+            ("2022-10-02", "National Day"),
+            ("2022-10-03", "National Day"),
+            ("2022-10-04", "National Day"),
+            ("2022-10-05", "National Day"),
+            ("2022-10-06", "National Day"),
+            ("2022-10-07", "National Day"),
+            ("2022-12-31", "New Year's Day"),
+        )
+
+    def test_l10n_th(self):
+        self.assertLocalizedHolidays(
+            "th",
+            ("2022-01-01", "วันปีใหม่สากล"),
+            ("2022-01-02", "วันปีใหม่สากล"),
+            ("2022-01-03", "วันปีใหม่สากล"),
+            ("2022-01-31", "วันตรุษจีน"),
+            ("2022-02-01", "วันตรุษจีน"),
+            ("2022-02-02", "วันตรุษจีน"),
+            ("2022-02-03", "วันตรุษจีน"),
+            ("2022-02-04", "วันตรุษจีน"),
+            ("2022-02-05", "วันตรุษจีน"),
+            ("2022-02-06", "วันตรุษจีน"),
+            ("2022-03-08", "วันสตรีสากล"),
+            ("2022-04-03", "วันเช็งเม้ง"),
+            ("2022-04-04", "วันเช็งเม้ง"),
+            ("2022-04-05", "วันเช็งเม้ง"),
+            ("2022-04-30", "วันแรงงาน"),
+            ("2022-05-01", "วันแรงงาน"),
+            ("2022-05-02", "วันแรงงาน"),
+            ("2022-05-03", "วันแรงงาน"),
+            ("2022-05-04", "วันเยาวชนห่งชาติจีน; วันแรงงาน"),
+            ("2022-06-01", "วันเด็กสากล"),
+            ("2022-06-03", "วันไหว้บ๊ะจ่าง"),
+            ("2022-06-04", "วันไหว้บ๊ะจ่าง"),
+            ("2022-06-05", "วันไหว้บ๊ะจ่าง"),
+            ("2022-08-01", "วันสถาปนากองทัพปลดปล่อยประชาชนจีน"),
+            ("2022-09-10", "วันไหว้พระจันทร์"),
+            ("2022-09-11", "วันไหว้พระจันทร์"),
+            ("2022-09-12", "วันไหว้พระจันทร์"),
+            ("2022-10-01", "วันชาติจีน"),
+            ("2022-10-02", "วันชาติจีน"),
+            ("2022-10-03", "วันชาติจีน"),
+            ("2022-10-04", "วันชาติจีน"),
+            ("2022-10-05", "วันชาติจีน"),
+            ("2022-10-06", "วันชาติจีน"),
+            ("2022-10-07", "วันชาติจีน"),
+            ("2022-12-31", "วันปีใหม่สากล"),
+        )
+
+    def test_l10n_zh_tw(self):
+        self.assertLocalizedHolidays(
+            "zh_TW",
+            ("2022-01-01", "元旦"),
+            ("2022-01-02", "元旦"),
+            ("2022-01-03", "元旦"),
+            ("2022-01-31", "春節"),
+            ("2022-02-01", "春節"),
+            ("2022-02-02", "春節"),
+            ("2022-02-03", "春節"),
+            ("2022-02-04", "春節"),
+            ("2022-02-05", "春節"),
+            ("2022-02-06", "春節"),
+            ("2022-03-08", "國際婦女節"),
+            ("2022-04-03", "清明節"),
+            ("2022-04-04", "清明節"),
+            ("2022-04-05", "清明節"),
+            ("2022-04-30", "勞動節"),
+            ("2022-05-01", "勞動節"),
+            ("2022-05-02", "勞動節"),
+            ("2022-05-03", "勞動節"),
+            ("2022-05-04", "五四青年節; 勞動節"),
+            ("2022-06-01", "六一兒童節"),
+            ("2022-06-03", "端午節"),
+            ("2022-06-04", "端午節"),
+            ("2022-06-05", "端午節"),
+            ("2022-08-01", "建軍節"),
+            ("2022-09-10", "中秋節"),
+            ("2022-09-11", "中秋節"),
+            ("2022-09-12", "中秋節"),
+            ("2022-10-01", "國慶日"),
+            ("2022-10-02", "國慶日"),
+            ("2022-10-03", "國慶日"),
+            ("2022-10-04", "國慶日"),
+            ("2022-10-05", "國慶日"),
+            ("2022-10-06", "國慶日"),
+            ("2022-10-07", "國慶日"),
+            ("2022-12-31", "元旦"),
+        )