Repository: vacanza/python-holidays

Issue:
Update 2024 Chinese holiday
I am Chinese, and Chinese holidy is various from other years,and the holidays of 2024 is published by Chinese government,ref:https://www.gov.cn/yaowen/liebiao/202310/content_6911540.htm。
I want to update this information as my first issue good issue,Can I do this? 


Discussion:

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,21 +9,20 @@
 #  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.calendars.gregorian import JAN, FEB, MAR, APR, MAY, JUN, SEP, OCT, DEC
 from holidays.constants import HALF_DAY, PUBLIC
 from holidays.groups import ChineseCalendarHolidays, InternationalHolidays, StaticHolidays
-from holidays.holiday_base import HolidayBase
+from holidays.observed_holiday_base import ObservedHolidayBase, SAT_SUN_TO_NEXT_WORKDAY
 
 
-class China(HolidayBase, ChineseCalendarHolidays, InternationalHolidays, StaticHolidays):
+class China(ObservedHolidayBase, ChineseCalendarHolidays, InternationalHolidays, StaticHolidays):
     """
     References:
         - https://en.wikipedia.org/wiki/Public_holidays_in_China
         - `Festivals and Public Holidays <https://zh.wikipedia.org/wiki/中华人民共和国节日与公众假期>`_
+        - `2024 <https://www.gov.cn/zhengce/content/202310/content_6911527.htm>`_
         - `2023 <https://www.gov.cn/gongbao/content/2023/content_5736714.htm>`_
         - `2022 <https://www.gov.cn/gongbao/content/2021/content_5651728.htm>`_
         - `2021 <https://www.gov.cn/gongbao/content/2020/content_5567750.htm>`_
@@ -61,6 +60,8 @@ class China(HolidayBase, ChineseCalendarHolidays, InternationalHolidays, StaticH
     """
 
     country = "CN"
+    # %s (Observed).
+    observed_label = tr("%s（观察日）")
     supported_categories = (PUBLIC, HALF_DAY)
     default_language = "zh_CN"
     supported_languages = ("en_US", "th", "zh_CN", "zh_TW")
@@ -69,123 +70,30 @@ def __init__(self, *args, **kwargs):
         ChineseCalendarHolidays.__init__(self)
         InternationalHolidays.__init__(self)
         StaticHolidays.__init__(self, cls=ChinaStaticHolidays)
+        kwargs.setdefault("observed_rule", SAT_SUN_TO_NEXT_WORKDAY)
+        kwargs.setdefault("observed_since", 2000)
         super().__init__(*args, **kwargs)
 
-    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))
-            else:
-                # [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))
-            else:
-                # [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
 
+        dts_observed = set()
+
         # 元旦 (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)
+        dts_observed.add(self._add_new_years_day(tr("元旦")))
 
         # 春节
         # Status: In-Use (Statutory).
         # Day 1-3 of Chinese New Year in 1949, 1999, 2007, and 2013 revision.
+        # 2007 revision introduced New Year's Eve (农历除夕) instead of
+        # New Year's 3rd day; 2013 revision returned it back.
 
         # Spring Festival Golden Weekend
         # Checked with Official Notice from 2001-2023.
@@ -193,18 +101,13 @@ def _populate_public_holidays(self):
 
         # 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)
+        dts_observed.add(self._add_chinese_new_years_day(chinese_new_year))
+        dts_observed.add(self._add_chinese_new_years_day_two(chinese_new_year))
+        if 2008 <= self._year <= 2013:
+            # Chinese New Year's Eve.
+            dts_observed.add(self._add_chinese_new_years_eve(tr("农历除夕")))
+        else:
+            dts_observed.add(self._add_chinese_new_years_day_three(chinese_new_year))
 
         # 劳动节
         # Status: In-Use (Statutory).
@@ -217,20 +120,10 @@ def _populate_public_holidays(self):
 
         # Labor Day.
         labor_day = tr("劳动节")
-        may_1 = self._add_labor_day(labor_day)
+        dts_observed.add(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)
+            dts_observed.add(self._add_labor_day_two(labor_day))
+            dts_observed.add(self._add_labor_day_three(labor_day))
 
         # 国庆节
         # Status: In-Use (Statutory).
@@ -242,17 +135,10 @@ def _populate_public_holidays(self):
 
         # National Day.
         national_day = tr("国庆节")
-        self._add_holiday_oct_1(national_day)
-        self._add_holiday_oct_2(national_day)
+        dts_observed.add(self._add_holiday_oct_1(national_day))
+        dts_observed.add(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)
+            dts_observed.add(self._add_holiday_oct_3(national_day))
 
         if self._year >= 2008:
             # 清明节
@@ -261,11 +147,7 @@ def _populate_public_holidays(self):
             # 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)
+            dts_observed.add(self._add_qingming_festival(tr("清明节")))
 
             # 端午节
             # Status: In-Use (Statutory).
@@ -274,10 +156,8 @@ def _populate_public_holidays(self):
 
             # 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)
+            if self._year != 2012:
+                dts_observed.add(dragon_boat_festival)
 
             # 中秋节
             # Status: In-Use (Statutory).
@@ -287,16 +167,11 @@ def _populate_public_holidays(self):
 
             # Mid-Autumn Festival.
             mid_autumn_festival = self._add_mid_autumn_festival(tr("中秋节"))
+            if self._year != 2015:
+                dts_observed.add(mid_autumn_festival)
 
-            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)
+        if self.observed:
+            self._populate_observed(dts_observed, multiple=True)
 
     def _populate_half_day_holidays(self):
         # No in lieus are given for this category.
@@ -326,51 +201,234 @@ class CHN(China):
 
 
 class ChinaStaticHolidays:
-    # Special Cases.
-
-    # New Year's Day.
-    new_years_day_overflow = tr("元旦")
+    # Date format (see strftime() Format Codes).
+    substituted_date_format = tr("%Y-%m-%d")
+    # Day off (substituted from %s).
+    substituted_label = tr("休息日（%s日起取代）")
 
-    # National Day.
-    national_day_2008_golden_week = tr("国庆节")
+    # Dragon Boat Festival.
+    dragon_boat_festival = tr("端午节")
 
     # Mid-Autumn Festival.
-    mid_autumn_festival_2010_special = tr("中秋节")
+    mid_autumn_festival = tr("中秋节")
+
+    # 70th Anniversary of the Victory of the Chinese People’s War of Resistance against
+    # Japanese Aggression and the World Anti-Fascist War.
+    victory_70_anniversary = tr("中国人民抗日战争暨世界反法西斯战争胜利70周年纪念日")
 
     special_public_holidays = {
+        2001: (
+            (JAN, 29, JAN, 20),  # Spring Festival
+            (JAN, 30, JAN, 21),  # Spring Festival
+            (MAY, 4, APR, 28),  # Labor Day
+            (MAY, 7, APR, 29),  # Labor Day
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 5, SEP, 30),  # National Day
+        ),
+        2002: (
+            (JAN, 2, DEC, 29, 2001),  # New Year's Day
+            (JAN, 3, DEC, 30, 2001),  # New Year's Day
+            (FEB, 15, FEB, 9),  # Spring Festival
+            (FEB, 18, FEB, 10),  # Spring Festival
+            (MAY, 6, APR, 27),  # Labor Day
+            (MAY, 7, APR, 28),  # Labor Day
+            (OCT, 4, SEP, 28),  # National Day
+            (OCT, 7, SEP, 29),  # National Day
+        ),
+        2003: (
+            (FEB, 6, FEB, 8),  # Spring Festival
+            (FEB, 7, FEB, 9),  # Spring Festival
+            (MAY, 6, APR, 26),  # Labor Day
+            (MAY, 7, APR, 27),  # Labor Day
+            (OCT, 6, SEP, 27),  # National Day
+            (OCT, 7, SEP, 28),  # National Day
+        ),
+        2004: (
+            (JAN, 27, JAN, 17),  # Spring Festival
+            (JAN, 28, JAN, 18),  # Spring Festival
+            (MAY, 6, MAY, 8),  # Labor Day
+            (MAY, 7, MAY, 9),  # Labor Day
+            (OCT, 6, OCT, 9),  # National Day
+            (OCT, 7, OCT, 10),  # National Day
+        ),
+        2005: (
+            (FEB, 14, FEB, 5),  # Spring Festival
+            (FEB, 15, FEB, 6),  # Spring Festival
+            (MAY, 5, APR, 30),  # Labor Day
+            (MAY, 6, MAY, 8),  # Labor Day
+            (OCT, 6, OCT, 8),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
+        ),
+        2006: (
+            (JAN, 3, DEC, 31, 2005),  # New Year's Day
+            (FEB, 2, JAN, 28),  # Spring Festival
+            (FEB, 3, FEB, 5),  # Spring Festival
+            (MAY, 4, APR, 29),  # Labor Day
+            (MAY, 5, APR, 30),  # Labor Day
+            (OCT, 5, SEP, 30),  # National Day
+            (OCT, 6, OCT, 8),  # National Day
+        ),
         2007: (
-            # 2007: Overflow from 2008 Notice.
-            (DEC, 30, new_years_day_overflow),
-            (DEC, 31, new_years_day_overflow),
+            (JAN, 2, DEC, 30, 2006),  # New Year's Day
+            (JAN, 3, DEC, 31, 2006),  # New Year's Day
+            (FEB, 22, FEB, 17),  # Spring Festival
+            (FEB, 23, FEB, 25),  # Spring Festival
+            (MAY, 4, APR, 28),  # Labor Day
+            (MAY, 7, APR, 29),  # Labor Day
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 5, SEP, 30),  # National Day
+            (DEC, 31, DEC, 29),  # New Year's Day
         ),
         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),
+            (FEB, 11, FEB, 2),  # Spring Festival
+            (FEB, 12, FEB, 3),  # Spring Festival
+            (MAY, 2, MAY, 4),  # Labor Day
+            (SEP, 29, SEP, 27),  # National Day
+            (SEP, 30, SEP, 28),  # National Day
+        ),
+        2009: (
+            (JAN, 2, JAN, 4),  # New Year's Day
+            (JAN, 29, JAN, 24),  # Spring Festival
+            (JAN, 30, FEB, 1),  # Spring Festival
+            (MAY, 29, MAY, 31),  # Dragon Boat Festival
+            (OCT, 7, SEP, 27),  # National Day
+            (OCT, 8, OCT, 10),  # National Day
         ),
         2010: (
-            # 2010: doesn't fit with existing observed pattern.
-            (SEP, 23, mid_autumn_festival_2010_special),
-            (SEP, 24, mid_autumn_festival_2010_special),
+            (FEB, 18, FEB, 20),  # Spring Festival
+            (FEB, 19, FEB, 21),  # Spring Festival
+            (JUN, 14, JUN, 12),  # Dragon Boat Festival
+            (JUN, 15, JUN, 13),  # Dragon Boat Festival
+            (SEP, 23, SEP, 19),  # Mid-Autumn Festival
+            (SEP, 24, SEP, 25),  # Mid-Autumn Festival
+            (OCT, 6, SEP, 26),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
+        ),
+        2011: (
+            (FEB, 7, JAN, 30),  # Spring Festival
+            (FEB, 8, FEB, 12),  # Spring Festival
+            (APR, 4, APR, 2),  # Tomb-Sweeping Day
+            (OCT, 6, OCT, 8),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
+        ),
+        2012: (
+            (JAN, 3, DEC, 31, 2011),  # New Year's Day
+            (JAN, 26, JAN, 21),  # Spring Festival
+            (JAN, 27, JAN, 29),  # Spring Festival
+            (APR, 2, MAR, 31),  # Tomb-Sweeping Day
+            (APR, 3, APR, 1),  # Tomb-Sweeping Day
+            (APR, 30, APR, 28),  # Labor Day
+            (OCT, 5, SEP, 29),  # National Day
         ),
         2013: (
-            # 2013: doesn't fit with existing observed pattern.
-            (JAN, 2, new_years_day_overflow),
-            (JAN, 3, new_years_day_overflow),
+            (JAN, 2, JAN, 5),  # New Year's Day
+            (JAN, 3, JAN, 6),  # New Year's Day
+            (FEB, 14, FEB, 16),  # Spring Festival
+            (FEB, 15, FEB, 17),  # Spring Festival
+            (APR, 5, APR, 7),  # Tomb-Sweeping Day
+            (APR, 29, APR, 27),  # Labor Day
+            (APR, 30, APR, 28),  # Labor Day
+            (JUN, 10, JUN, 8),  # Dragon Boat Festival
+            (JUN, 11, JUN, 9),  # Dragon Boat Festival
+            (SEP, 20, SEP, 22),  # Mid-Autumn Festival
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 7, OCT, 12),  # National Day
+        ),
+        2014: (
+            (FEB, 5, JAN, 26),  # Spring Festival
+            (FEB, 6, FEB, 8),  # Spring Festival
+            (MAY, 2, MAY, 4),  # Labor Day
+            (OCT, 6, SEP, 28),  # National Day
+            (OCT, 7, OCT, 11),  # National Day
+        ),
+        2015: (
+            (JAN, 2, JAN, 4),  # New Year's Day
+            (FEB, 18, FEB, 15),  # Spring Festival
+            (FEB, 24, FEB, 28),  # Spring Festival
+            (SEP, 3, victory_70_anniversary),
+            (SEP, 4, SEP, 6),  # 70th Anniversary of the Victory
+            (OCT, 7, OCT, 10),  # National Day
+        ),
+        2016: (
+            (FEB, 11, FEB, 6),  # Spring Festival
+            (FEB, 12, FEB, 14),  # Spring Festival
+            (JUN, 10, JUN, 12),  # Dragon Boat Festival
+            (SEP, 16, SEP, 18),  # Mid-Autumn Festival
+            (OCT, 6, OCT, 8),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
+        ),
+        2017: (
+            (JAN, 27, JAN, 22),  # Spring Festival
+            (FEB, 2, FEB, 4),  # Spring Festival
+            (APR, 3, APR, 1),  # Tomb-Sweeping Day
+            (MAY, 29, MAY, 27),  # Dragon Boat Festival
+            (OCT, 6, SEP, 30),  # National Day
         ),
         2018: (
-            # 2018: Overflow from 2019 Notice.
-            (DEC, 30, new_years_day_overflow),
-            (DEC, 31, new_years_day_overflow),
+            (FEB, 15, FEB, 11),  # Spring Festival
+            (FEB, 21, FEB, 24),  # Spring Festival
+            (APR, 6, APR, 8),  # Tomb-Sweeping Day
+            (APR, 30, APR, 28),  # Labor Day
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 5, SEP, 30),  # National Day
+            (DEC, 31, DEC, 29),  # New Year's Day
+        ),
+        2019: (
+            (FEB, 4, FEB, 2),  # Spring Festival
+            (FEB, 8, FEB, 3),  # Spring Festival
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 7, OCT, 12),  # National Day
+        ),
+        2020: (
+            (JAN, 24, JAN, 19),  # Spring Festival
+            (JAN, 30, FEB, 1),  # Spring Festival
+            (MAY, 4, APR, 26),  # Labor Day
+            (MAY, 5, MAY, 9),  # Labor Day
+            (JUN, 26, JUN, 28),  # Dragon Boat Festival
+            (OCT, 7, SEP, 27),  # National Day
+            (OCT, 8, OCT, 10),  # National Day
+        ),
+        2021: (
+            (FEB, 11, FEB, 7),  # Spring Festival
+            (FEB, 17, FEB, 20),  # Spring Festival
+            (MAY, 4, APR, 25),  # Labor Day
+            (MAY, 5, MAY, 8),  # Labor Day
+            (SEP, 20, SEP, 18),  # Mid-Autumn Festival
+            (OCT, 6, SEP, 26),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
         ),
         2022: (
-            # 2022: Overflow from 2023 Notice.
-            (DEC, 31, new_years_day_overflow),
+            (JAN, 31, JAN, 29),  # Spring Festival
+            (FEB, 4, JAN, 30),  # Spring Festival
+            (APR, 4, APR, 2),  # Tomb-Sweeping Day
+            (MAY, 3, APR, 24),  # Labor Day
+            (MAY, 4, MAY, 7),  # Labor Day
+            (OCT, 6, OCT, 8),  # National Day
+            (OCT, 7, OCT, 9),  # National Day
         ),
         2023: (
-            # 2023: Overflow from 2023 Notice.
-            (JAN, 2, new_years_day_overflow),
+            (JAN, 26, JAN, 28),  # Spring Festival
+            (JAN, 27, JAN, 29),  # Spring Festival
+            (MAY, 2, APR, 23),  # Labor Day
+            (MAY, 3, MAY, 6),  # Labor Day
+            (JUN, 23, JUN, 25),  # Dragon Boat Festival
+            (OCT, 5, OCT, 7),  # National Day
+            (OCT, 6, OCT, 8),  # National Day
         ),
+        2024: (
+            (FEB, 15, FEB, 4),  # Spring Festival
+            (FEB, 16, FEB, 18),  # Spring Festival
+            (APR, 5, APR, 7),  # Tomb-Sweeping Day
+            (MAY, 2, APR, 28),  # Labor Day
+            (MAY, 3, MAY, 11),  # Labor Day
+            (SEP, 16, SEP, 14),  # Mid-Autumn Festival
+            (OCT, 4, SEP, 29),  # National Day
+            (OCT, 7, OCT, 12),  # National Day
+        ),
+    }
+
+    special_public_holidays_observed = {
+        2012: (JUN, 22, dragon_boat_festival),  # observed from Jun 23
+        2015: (OCT, 6, mid_autumn_festival),  # observed from Sep 27
+        2020: (OCT, 6, mid_autumn_festival),  # observed from Oct 1, overlap with National Day
     }
diff --git a/holidays/groups/chinese.py b/holidays/groups/chinese.py
--- a/holidays/groups/chinese.py
+++ b/holidays/groups/chinese.py
@@ -146,26 +146,6 @@ 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
@@ -17,7 +17,7 @@
 class TestChina(TestCase):
     @classmethod
     def setUpClass(cls):
-        super().setUpClass(China, years=range(1950, 2051))
+        super().setUpClass(China, years=range(1950, 2051), years_non_observed=range(2001, 2025))
 
     def test_country_aliases(self):
         self.assertCountryAliases(China, CN, CHN)
@@ -26,6 +26,97 @@ def test_no_holidays(self):
         self.assertNoHolidays(China(years=1949))
         self.assertNoHolidays(China(years=1949, categories=HALF_DAY))
 
+    def test_new_years_day(self):
+        self.assertHolidayName("元旦", (f"{year}-01-01" for year in range(1950, 2051)))
+
+        self.assertNoNonObservedHoliday(
+            "2005-01-03",
+            "2006-01-02",
+            "2011-01-03",
+            "2012-01-02",
+            "2017-01-02",
+            "2022-01-03",
+            "2023-01-02",
+        )
+
+    def test_chinese_new_year_eve(self):
+        name = "农历除夕"
+        self.assertHolidayName(
+            name,
+            "2008-02-06",
+            "2009-01-25",
+            "2010-02-13",
+            "2011-02-02",
+            "2012-01-22",
+            "2013-02-09",
+        )
+        self.assertNoHolidayName(name, range(1950, 2008), range(2014, 2051))
+
+        self.assertNoNonObservedHoliday(
+            "2009-01-28",
+            "2010-02-16",
+            "2012-01-25",
+            "2013-02-12",
+        )
+
+    def test_chinese_new_year(self):
+        name = "春节"
+        self.assertHolidayName(name, range(1950, 2051))
+        self.assertHolidayName(
+            name,
+            "2021-02-12",
+            "2021-02-13",
+            "2021-02-14",
+            "2022-02-01",
+            "2022-02-02",
+            "2022-02-03",
+            "2023-01-22",
+            "2023-01-23",
+            "2023-01-24",
+        )
+
+        self.assertNoNonObservedHoliday(
+            "2003-02-04",
+            "2003-02-05",
+            "2004-01-26",
+            "2006-02-01",
+            "2007-02-21",
+            "2010-02-17",
+            "2013-02-13",
+            "2014-02-03",
+            "2014-02-04",
+            "2015-02-23",
+            "2017-01-31",
+            "2017-02-01",
+            "2018-02-19",
+            "2018-02-20",
+            "2020-01-28",
+            "2020-01-29",
+            "2021-02-15",
+            "2021-02-16",
+            "2023-01-25",
+            "2024-02-13",
+            "2024-02-14",
+        )
+
+    def test_labor_day(self):
+        name = "劳动节"
+        self.assertHolidayName(name, (f"{year}-05-01" for year in range(1950, 2051)))
+        for year in range(2000, 2008):
+            self.assertHolidayName(name, (f"{year}-05-02", f"{year}-05-03"))
+
+        self.assertNoNonObservedHoliday(
+            "2003-05-05",
+            "2004-05-04",
+            "2004-05-05",
+            "2005-05-04",
+            "2010-05-03",
+            "2011-05-02",
+            "2016-05-02",
+            "2021-05-03",
+            "2022-05-02",
+        )
+
     def test_national_day(self):
         name = "国庆节"
         for year in range(1950, 1999):
@@ -34,23 +125,100 @@ def test_national_day(self):
             self.assertHolidayName(name, (f"{year}-10-01", f"{year}-10-02", f"{year}-10-03"))
 
         self.assertNoNonObservedHoliday(
-            "2020-10-04",
+            "2004-10-04",
+            "2004-10-05",
+            "2005-10-04",
+            "2005-10-05",
+            "2006-10-04",
+            "2009-10-06",
+            "2010-10-04",
+            "2010-10-05",
+            "2011-10-04",
+            "2011-10-05",
+            "2015-10-05",
+            "2016-10-04",
+            "2016-10-05",
+            "2017-10-05",
             "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_qingming_festival(self):
+        name = "清明节"
+        self.assertHolidayName(name, range(2008, 2051))
+        self.assertNoHolidayName(name, range(1950, 2008))
+
+        self.assertHolidayName(
+            name,
+            "2017-04-04",
+            "2018-04-05",
+            "2019-04-05",
+            "2020-04-04",
+            "2021-04-04",
+            "2022-04-05",
+            "2023-04-05",
+            "2024-04-04",
+        )
+
+        self.assertNoNonObservedHoliday(
+            "2009-04-06",
+            "2014-04-07",
+            "2015-04-06",
+            "2020-04-06",
+            "2021-04-05",
+        )
+
+    def test_dragon_boat_festival(self):
+        name = "端午节"
+        self.assertHolidayName(name, range(2008, 2051))
+        self.assertNoHolidayName(name, range(1950, 2008))
+
+        self.assertHolidayName(
+            name,
+            "2017-05-30",
+            "2018-06-18",
+            "2019-06-07",
+            "2020-06-25",
+            "2021-06-14",
+            "2022-06-03",
+            "2023-06-22",
+            "2024-06-10",
+        )
+
+        self.assertNoNonObservedHoliday(
+            "2008-06-09",
+            "2012-06-22",
+            "2015-06-22",
+        )
+
+    def test_mid_autumn_festival(self):
+        name = "中秋节"
+        self.assertHolidayName(name, range(2008, 2051))
+        self.assertNoHolidayName(name, range(1950, 2008))
+
+        self.assertHolidayName(
+            name,
+            "2017-10-04",
+            "2018-09-24",
+            "2019-09-13",
+            "2020-10-01",
+            "2021-09-21",
+            "2022-09-10",
+            "2023-09-29",
+            "2024-09-17",
+        )
+
+        self.assertNoNonObservedHoliday(
+            "2008-09-15",
+            "2009-10-05",
+            "2012-10-04",
+            "2015-10-06",
+            "2020-10-06",
+            "2022-09-12",
         )
 
     def test_1950_public_holiday(self):
@@ -87,24 +255,18 @@ def test_2001_public_holiday(self):
             ("2001-01-24", "春节"),
             ("2001-01-25", "春节"),
             ("2001-01-26", "春节"),
-            ("2001-01-27", "春节"),
-            ("2001-01-28", "春节"),
-            ("2001-01-29", "春节"),
-            ("2001-01-30", "春节"),
+            ("2001-01-29", "休息日（2001-01-20日起取代）"),
+            ("2001-01-30", "休息日（2001-01-21日起取代）"),
             ("2001-05-01", "劳动节"),
             ("2001-05-02", "劳动节"),
             ("2001-05-03", "劳动节"),
-            ("2001-05-04", "劳动节"),
-            ("2001-05-05", "劳动节"),
-            ("2001-05-06", "劳动节"),
-            ("2001-05-07", "劳动节"),
+            ("2001-05-04", "休息日（2001-04-28日起取代）"),
+            ("2001-05-07", "休息日（2001-04-29日起取代）"),
             ("2001-10-01", "国庆节"),
             ("2001-10-02", "国庆节"),
             ("2001-10-03", "国庆节"),
-            ("2001-10-04", "国庆节"),
-            ("2001-10-05", "国庆节"),
-            ("2001-10-06", "国庆节"),
-            ("2001-10-07", "国庆节"),
+            ("2001-10-04", "休息日（2001-09-29日起取代）"),
+            ("2001-10-05", "休息日（2001-09-30日起取代）"),
         )
 
     def test_2002_public_holiday(self):
@@ -112,29 +274,23 @@ def test_2002_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2002),
             ("2002-01-01", "元旦"),
-            ("2002-01-02", "元旦"),
-            ("2002-01-03", "元旦"),
+            ("2002-01-02", "休息日（2001-12-29日起取代）"),
+            ("2002-01-03", "休息日（2001-12-30日起取代）"),
             ("2002-02-12", "春节"),
             ("2002-02-13", "春节"),
             ("2002-02-14", "春节"),
-            ("2002-02-15", "春节"),
-            ("2002-02-16", "春节"),
-            ("2002-02-17", "春节"),
-            ("2002-02-18", "春节"),
+            ("2002-02-15", "休息日（2002-02-09日起取代）"),
+            ("2002-02-18", "休息日（2002-02-10日起取代）"),
             ("2002-05-01", "劳动节"),
             ("2002-05-02", "劳动节"),
             ("2002-05-03", "劳动节"),
-            ("2002-05-04", "劳动节"),
-            ("2002-05-05", "劳动节"),
-            ("2002-05-06", "劳动节"),
-            ("2002-05-07", "劳动节"),
+            ("2002-05-06", "休息日（2002-04-27日起取代）"),
+            ("2002-05-07", "休息日（2002-04-28日起取代）"),
             ("2002-10-01", "国庆节"),
             ("2002-10-02", "国庆节"),
             ("2002-10-03", "国庆节"),
-            ("2002-10-04", "国庆节"),
-            ("2002-10-05", "国庆节"),
-            ("2002-10-06", "国庆节"),
-            ("2002-10-07", "国庆节"),
+            ("2002-10-04", "休息日（2002-09-28日起取代）"),
+            ("2002-10-07", "休息日（2002-09-29日起取代）"),
         )
 
     def test_2003_public_holiday(self):
@@ -145,24 +301,21 @@ def test_2003_public_holiday(self):
             ("2003-02-01", "春节"),
             ("2003-02-02", "春节"),
             ("2003-02-03", "春节"),
-            ("2003-02-04", "春节"),
-            ("2003-02-05", "春节"),
-            ("2003-02-06", "春节"),
-            ("2003-02-07", "春节"),
+            ("2003-02-04", "春节（观察日）"),
+            ("2003-02-05", "春节（观察日）"),
+            ("2003-02-06", "休息日（2003-02-08日起取代）"),
+            ("2003-02-07", "休息日（2003-02-09日起取代）"),
             ("2003-05-01", "劳动节"),
             ("2003-05-02", "劳动节"),
             ("2003-05-03", "劳动节"),
-            ("2003-05-04", "劳动节"),
-            ("2003-05-05", "劳动节"),
-            ("2003-05-06", "劳动节"),
-            ("2003-05-07", "劳动节"),
+            ("2003-05-05", "劳动节（观察日）"),
+            ("2003-05-06", "休息日（2003-04-26日起取代）"),
+            ("2003-05-07", "休息日（2003-04-27日起取代）"),
             ("2003-10-01", "国庆节"),
             ("2003-10-02", "国庆节"),
             ("2003-10-03", "国庆节"),
-            ("2003-10-04", "国庆节"),
-            ("2003-10-05", "国庆节"),
-            ("2003-10-06", "国庆节"),
-            ("2003-10-07", "国庆节"),
+            ("2003-10-06", "休息日（2003-09-27日起取代）"),
+            ("2003-10-07", "休息日（2003-09-28日起取代）"),
         )
 
     def test_2004_public_holiday(self):
@@ -173,24 +326,23 @@ def test_2004_public_holiday(self):
             ("2004-01-22", "春节"),
             ("2004-01-23", "春节"),
             ("2004-01-24", "春节"),
-            ("2004-01-25", "春节"),
-            ("2004-01-26", "春节"),
-            ("2004-01-27", "春节"),
-            ("2004-01-28", "春节"),
+            ("2004-01-26", "春节（观察日）"),
+            ("2004-01-27", "休息日（2004-01-17日起取代）"),
+            ("2004-01-28", "休息日（2004-01-18日起取代）"),
             ("2004-05-01", "劳动节"),
             ("2004-05-02", "劳动节"),
             ("2004-05-03", "劳动节"),
-            ("2004-05-04", "劳动节"),
-            ("2004-05-05", "劳动节"),
-            ("2004-05-06", "劳动节"),
-            ("2004-05-07", "劳动节"),
+            ("2004-05-04", "劳动节（观察日）"),
+            ("2004-05-05", "劳动节（观察日）"),
+            ("2004-05-06", "休息日（2004-05-08日起取代）"),
+            ("2004-05-07", "休息日（2004-05-09日起取代）"),
             ("2004-10-01", "国庆节"),
             ("2004-10-02", "国庆节"),
             ("2004-10-03", "国庆节"),
-            ("2004-10-04", "国庆节"),
-            ("2004-10-05", "国庆节"),
-            ("2004-10-06", "国庆节"),
-            ("2004-10-07", "国庆节"),
+            ("2004-10-04", "国庆节（观察日）"),
+            ("2004-10-05", "国庆节（观察日）"),
+            ("2004-10-06", "休息日（2004-10-09日起取代）"),
+            ("2004-10-07", "休息日（2004-10-10日起取代）"),
         )
 
     def test_2005_public_holiday(self):
@@ -198,29 +350,25 @@ def test_2005_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2005),
             ("2005-01-01", "元旦"),
-            ("2005-01-02", "元旦"),
-            ("2005-01-03", "元旦"),
+            ("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-02-14", "休息日（2005-02-05日起取代）"),
+            ("2005-02-15", "休息日（2005-02-06日起取代）"),
             ("2005-05-01", "劳动节"),
             ("2005-05-02", "劳动节"),
             ("2005-05-03", "劳动节"),
-            ("2005-05-04", "劳动节"),
-            ("2005-05-05", "劳动节"),
-            ("2005-05-06", "劳动节"),
-            ("2005-05-07", "劳动节"),
+            ("2005-05-04", "劳动节（观察日）"),
+            ("2005-05-05", "休息日（2005-04-30日起取代）"),
+            ("2005-05-06", "休息日（2005-05-08日起取代）"),
             ("2005-10-01", "国庆节"),
             ("2005-10-02", "国庆节"),
             ("2005-10-03", "国庆节"),
-            ("2005-10-04", "国庆节"),
-            ("2005-10-05", "国庆节"),
-            ("2005-10-06", "国庆节"),
-            ("2005-10-07", "国庆节"),
+            ("2005-10-04", "国庆节（观察日）"),
+            ("2005-10-05", "国庆节（观察日）"),
+            ("2005-10-06", "休息日（2005-10-08日起取代）"),
+            ("2005-10-07", "休息日（2005-10-09日起取代）"),
         )
 
     def test_2006_public_holiday(self):
@@ -228,29 +376,25 @@ def test_2006_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2006),
             ("2006-01-01", "元旦"),
-            ("2006-01-02", "元旦"),
-            ("2006-01-03", "元旦"),
+            ("2006-01-02", "元旦（观察日）"),
+            ("2006-01-03", "休息日（2005-12-31日起取代）"),
             ("2006-01-29", "春节"),
             ("2006-01-30", "春节"),
             ("2006-01-31", "春节"),
-            ("2006-02-01", "春节"),
-            ("2006-02-02", "春节"),
-            ("2006-02-03", "春节"),
-            ("2006-02-04", "春节"),
+            ("2006-02-01", "春节（观察日）"),
+            ("2006-02-02", "休息日（2006-01-28日起取代）"),
+            ("2006-02-03", "休息日（2006-02-05日起取代）"),
             ("2006-05-01", "劳动节"),
             ("2006-05-02", "劳动节"),
             ("2006-05-03", "劳动节"),
-            ("2006-05-04", "劳动节"),
-            ("2006-05-05", "劳动节"),
-            ("2006-05-06", "劳动节"),
-            ("2006-05-07", "劳动节"),
+            ("2006-05-04", "休息日（2006-04-29日起取代）"),
+            ("2006-05-05", "休息日（2006-04-30日起取代）"),
             ("2006-10-01", "国庆节"),
             ("2006-10-02", "国庆节"),
             ("2006-10-03", "国庆节"),
-            ("2006-10-04", "国庆节"),
-            ("2006-10-05", "国庆节"),
-            ("2006-10-06", "国庆节"),
-            ("2006-10-07", "国庆节"),
+            ("2006-10-04", "国庆节（观察日）"),
+            ("2006-10-05", "休息日（2006-09-30日起取代）"),
+            ("2006-10-06", "休息日（2006-10-08日起取代）"),
         )
 
     def test_2007_public_holiday(self):
@@ -258,48 +402,25 @@ def test_2007_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2007),
             ("2007-01-01", "元旦"),
-            ("2007-01-02", "元旦"),
-            ("2007-01-03", "元旦"),
+            ("2007-01-02", "休息日（2006-12-30日起取代）"),
+            ("2007-01-03", "休息日（2006-12-31日起取代）"),
             ("2007-02-18", "春节"),
             ("2007-02-19", "春节"),
             ("2007-02-20", "春节"),
-            ("2007-02-21", "春节"),
-            ("2007-02-22", "春节"),
-            ("2007-02-23", "春节"),
-            ("2007-02-24", "春节"),
+            ("2007-02-21", "春节（观察日）"),
+            ("2007-02-22", "休息日（2007-02-17日起取代）"),
+            ("2007-02-23", "休息日（2007-02-25日起取代）"),
             ("2007-05-01", "劳动节"),
             ("2007-05-02", "劳动节"),
             ("2007-05-03", "劳动节"),
-            ("2007-05-04", "劳动节"),
-            ("2007-05-05", "劳动节"),
-            ("2007-05-06", "劳动节"),
-            ("2007-05-07", "劳动节"),
+            ("2007-05-04", "休息日（2007-04-28日起取代）"),
+            ("2007-05-07", "休息日（2007-04-29日起取代）"),
             ("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", "元旦"),
-        )
-
-        self.assertNonObservedHolidays(
-            China(categories=PUBLIC, observed=False, years=2007),
-            ("2007-01-01", "元旦"),
-            ("2007-02-18", "春节"),
-            ("2007-02-19", "春节"),
-            ("2007-02-20", "春节"),
-            ("2007-05-01", "劳动节"),
-            ("2007-05-02", "劳动节"),
-            ("2007-05-03", "劳动节"),
-            ("2007-10-01", "国庆节"),
-            ("2007-10-02", "国庆节"),
-            ("2007-10-03", "国庆节"),
-            ("2007-12-30", "元旦"),
-            ("2007-12-31", "元旦"),
+            ("2007-10-04", "休息日（2007-09-29日起取代）"),
+            ("2007-10-05", "休息日（2007-09-30日起取代）"),
+            ("2007-12-31", "休息日（2007-12-29日起取代）"),
         )
 
     def test_2008_public_holiday(self):
@@ -307,32 +428,23 @@ def test_2008_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2008),
             ("2008-01-01", "元旦"),
-            ("2008-02-06", "春节"),
+            ("2008-02-06", "农历除夕"),
             ("2008-02-07", "春节"),
             ("2008-02-08", "春节"),
-            ("2008-02-09", "春节"),
-            ("2008-02-10", "春节"),
-            ("2008-02-11", "春节"),
-            ("2008-02-12", "春节"),
+            ("2008-02-11", "休息日（2008-02-02日起取代）"),
+            ("2008-02-12", "休息日（2008-02-03日起取代）"),
             ("2008-04-04", "清明节"),
-            ("2008-04-05", "清明节"),
-            ("2008-04-06", "清明节"),
             ("2008-05-01", "劳动节"),
-            ("2008-05-02", "劳动节"),
-            ("2008-05-03", "劳动节"),
-            ("2008-06-07", "端午节"),
+            ("2008-05-02", "休息日（2008-05-04日起取代）"),
             ("2008-06-08", "端午节"),
-            ("2008-06-09", "端午节"),
-            ("2008-09-13", "中秋节"),
+            ("2008-06-09", "端午节（观察日）"),
             ("2008-09-14", "中秋节"),
-            ("2008-09-15", "中秋节"),
-            ("2008-09-29", "国庆节"),
-            ("2008-09-30", "国庆节"),
+            ("2008-09-15", "中秋节（观察日）"),
+            ("2008-09-29", "休息日（2008-09-27日起取代）"),
+            ("2008-09-30", "休息日（2008-09-28日起取代）"),
             ("2008-10-01", "国庆节"),
             ("2008-10-02", "国庆节"),
             ("2008-10-03", "国庆节"),
-            ("2008-10-04", "国庆节"),
-            ("2008-10-05", "国庆节"),
         )
 
     def test_2009_public_holiday(self):
@@ -340,32 +452,25 @@ def test_2009_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2009),
             ("2009-01-01", "元旦"),
-            ("2009-01-02", "元旦"),
-            ("2009-01-03", "元旦"),
-            ("2009-01-25", "春节"),
+            ("2009-01-02", "休息日（2009-01-04日起取代）"),
+            ("2009-01-25", "农历除夕"),
             ("2009-01-26", "春节"),
             ("2009-01-27", "春节"),
-            ("2009-01-28", "春节"),
-            ("2009-01-29", "春节"),
-            ("2009-01-30", "春节"),
-            ("2009-01-31", "春节"),
+            ("2009-01-28", "农历除夕（观察日）"),
+            ("2009-01-29", "休息日（2009-01-24日起取代）"),
+            ("2009-01-30", "休息日（2009-02-01日起取代）"),
             ("2009-04-04", "清明节"),
-            ("2009-04-05", "清明节"),
-            ("2009-04-06", "清明节"),
+            ("2009-04-06", "清明节（观察日）"),
             ("2009-05-01", "劳动节"),
-            ("2009-05-02", "劳动节"),
-            ("2009-05-03", "劳动节"),
             ("2009-05-28", "端午节"),
-            ("2009-05-29", "端午节"),
-            ("2009-05-30", "端午节"),
+            ("2009-05-29", "休息日（2009-05-31日起取代）"),
             ("2009-10-01", "国庆节"),
             ("2009-10-02", "国庆节"),
             ("2009-10-03", "中秋节; 国庆节"),
-            ("2009-10-04", "国庆节"),
-            ("2009-10-05", "国庆节"),
-            ("2009-10-06", "国庆节"),
-            ("2009-10-07", "国庆节"),
-            ("2009-10-08", "国庆节"),
+            ("2009-10-05", "中秋节（观察日）"),
+            ("2009-10-06", "国庆节（观察日）"),
+            ("2009-10-07", "休息日（2009-09-27日起取代）"),
+            ("2009-10-08", "休息日（2009-10-10日起取代）"),
         )
 
     def test_2010_public_holiday(self):
@@ -373,34 +478,29 @@ def test_2010_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2010),
             ("2010-01-01", "元旦"),
-            ("2010-01-02", "元旦"),
-            ("2010-01-03", "元旦"),
-            ("2010-02-13", "春节"),
+            ("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-02-16", "农历除夕（观察日）"),
+            ("2010-02-17", "春节（观察日）"),
+            ("2010-02-18", "休息日（2010-02-20日起取代）"),
+            ("2010-02-19", "休息日（2010-02-21日起取代）"),
             ("2010-04-05", "清明节"),
             ("2010-05-01", "劳动节"),
-            ("2010-05-02", "劳动节"),
-            ("2010-05-03", "劳动节"),
-            ("2010-06-14", "端午节"),
-            ("2010-06-15", "端午节"),
+            ("2010-05-03", "劳动节（观察日）"),
+            ("2010-06-14", "休息日（2010-06-12日起取代）"),
+            ("2010-06-15", "休息日（2010-06-13日起取代）"),
             ("2010-06-16", "端午节"),
             ("2010-09-22", "中秋节"),
-            ("2010-09-23", "中秋节"),
-            ("2010-09-24", "中秋节"),
+            ("2010-09-23", "休息日（2010-09-19日起取代）"),
+            ("2010-09-24", "休息日（2010-09-25日起取代）"),
             ("2010-10-01", "国庆节"),
             ("2010-10-02", "国庆节"),
             ("2010-10-03", "国庆节"),
-            ("2010-10-04", "国庆节"),
-            ("2010-10-05", "国庆节"),
-            ("2010-10-06", "国庆节"),
-            ("2010-10-07", "国庆节"),
+            ("2010-10-04", "国庆节（观察日）"),
+            ("2010-10-05", "国庆节（观察日）"),
+            ("2010-10-06", "休息日（2010-09-26日起取代）"),
+            ("2010-10-07", "休息日（2010-10-09日起取代）"),
         )
 
     def test_2011_public_holiday(self):
@@ -408,34 +508,25 @@ def test_2011_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2011),
             ("2011-01-01", "元旦"),
-            ("2011-01-02", "元旦"),
-            ("2011-01-03", "元旦"),
-            ("2011-02-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-02-07", "休息日（2011-01-30日起取代）"),
+            ("2011-02-08", "休息日（2011-02-12日起取代）"),
+            ("2011-04-04", "休息日（2011-04-02日起取代）"),
             ("2011-04-05", "清明节"),
-            ("2011-04-30", "劳动节"),
             ("2011-05-01", "劳动节"),
-            ("2011-05-02", "劳动节"),
-            ("2011-06-04", "端午节"),
-            ("2011-06-05", "端午节"),
+            ("2011-05-02", "劳动节（观察日）"),
             ("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", "国庆节"),
+            ("2011-10-04", "国庆节（观察日）"),
+            ("2011-10-05", "国庆节（观察日）"),
+            ("2011-10-06", "休息日（2011-10-08日起取代）"),
+            ("2011-10-07", "休息日（2011-10-09日起取代）"),
         )
 
     def test_2012_public_holiday(self):
@@ -443,32 +534,27 @@ def test_2012_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2012),
             ("2012-01-01", "元旦"),
-            ("2012-01-02", "元旦"),
-            ("2012-01-03", "元旦"),
-            ("2012-01-22", "春节"),
+            ("2012-01-02", "元旦（观察日）"),
+            ("2012-01-03", "休息日（2011-12-31日起取代）"),
+            ("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-01-25", "农历除夕（观察日）"),
+            ("2012-01-26", "休息日（2012-01-21日起取代）"),
+            ("2012-01-27", "休息日（2012-01-29日起取代）"),
+            ("2012-04-02", "休息日（2012-03-31日起取代）"),
+            ("2012-04-03", "休息日（2012-04-01日起取代）"),
             ("2012-04-04", "清明节"),
-            ("2012-04-29", "劳动节"),
-            ("2012-04-30", "劳动节"),
+            ("2012-04-30", "休息日（2012-04-28日起取代）"),
             ("2012-05-01", "劳动节"),
-            ("2012-06-22", "端午节"),
+            ("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", "国庆节"),
+            ("2012-10-04", "中秋节（观察日）"),
+            ("2012-10-05", "休息日（2012-09-29日起取代）"),
         )
 
     def test_2013_public_holiday(self):
@@ -476,34 +562,30 @@ def test_2013_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2013),
             ("2013-01-01", "元旦"),
-            ("2013-01-02", "元旦"),
-            ("2013-01-03", "元旦"),
-            ("2013-02-09", "春节"),
+            ("2013-01-02", "休息日（2013-01-05日起取代）"),
+            ("2013-01-03", "休息日（2013-01-06日起取代）"),
+            ("2013-02-09", "农历除夕"),
             ("2013-02-10", "春节"),
             ("2013-02-11", "春节"),
-            ("2013-02-12", "春节"),
-            ("2013-02-13", "春节"),
-            ("2013-02-14", "春节"),
-            ("2013-02-15", "春节"),
+            ("2013-02-12", "农历除夕（观察日）"),
+            ("2013-02-13", "春节（观察日）"),
+            ("2013-02-14", "休息日（2013-02-16日起取代）"),
+            ("2013-02-15", "休息日（2013-02-17日起取代）"),
             ("2013-04-04", "清明节"),
-            ("2013-04-05", "清明节"),
-            ("2013-04-06", "清明节"),
-            ("2013-04-29", "劳动节"),
-            ("2013-04-30", "劳动节"),
+            ("2013-04-05", "休息日（2013-04-07日起取代）"),
+            ("2013-04-29", "休息日（2013-04-27日起取代）"),
+            ("2013-04-30", "休息日（2013-04-28日起取代）"),
             ("2013-05-01", "劳动节"),
-            ("2013-06-10", "端午节"),
-            ("2013-06-11", "端午节"),
+            ("2013-06-10", "休息日（2013-06-08日起取代）"),
+            ("2013-06-11", "休息日（2013-06-09日起取代）"),
             ("2013-06-12", "端午节"),
             ("2013-09-19", "中秋节"),
-            ("2013-09-20", "中秋节"),
-            ("2013-09-21", "中秋节"),
+            ("2013-09-20", "休息日（2013-09-22日起取代）"),
             ("2013-10-01", "国庆节"),
             ("2013-10-02", "国庆节"),
             ("2013-10-03", "国庆节"),
-            ("2013-10-04", "国庆节"),
-            ("2013-10-05", "国庆节"),
-            ("2013-10-06", "国庆节"),
-            ("2013-10-07", "国庆节"),
+            ("2013-10-04", "休息日（2013-09-29日起取代）"),
+            ("2013-10-07", "休息日（2013-10-12日起取代）"),
         )
 
     def test_2014_public_holiday(self):
@@ -514,23 +596,21 @@ def test_2014_public_holiday(self):
             ("2014-01-31", "春节"),
             ("2014-02-01", "春节"),
             ("2014-02-02", "春节"),
-            ("2014-02-03", "春节"),
-            ("2014-02-04", "春节"),
-            ("2014-02-05", "春节"),
-            ("2014-02-06", "春节"),
+            ("2014-02-03", "春节（观察日）"),
+            ("2014-02-04", "春节（观察日）"),
+            ("2014-02-05", "休息日（2014-01-26日起取代）"),
+            ("2014-02-06", "休息日（2014-02-08日起取代）"),
             ("2014-04-05", "清明节"),
+            ("2014-04-07", "清明节（观察日）"),
             ("2014-05-01", "劳动节"),
-            ("2014-05-02", "劳动节"),
-            ("2014-05-03", "劳动节"),
+            ("2014-05-02", "休息日（2014-05-04日起取代）"),
             ("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", "国庆节"),
+            ("2014-10-06", "休息日（2014-09-28日起取代）"),
+            ("2014-10-07", "休息日（2014-10-11日起取代）"),
         )
 
     def test_2015_public_holiday(self):
@@ -538,26 +618,27 @@ def test_2015_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2015),
             ("2015-01-01", "元旦"),
-            ("2015-01-02", "元旦"),
-            ("2015-01-03", "元旦"),
-            ("2015-02-18", "春节"),
+            ("2015-01-02", "休息日（2015-01-04日起取代）"),
+            ("2015-02-18", "休息日（2015-02-15日起取代）"),
             ("2015-02-19", "春节"),
             ("2015-02-20", "春节"),
             ("2015-02-21", "春节"),
-            ("2015-02-22", "春节"),
-            ("2015-02-23", "春节"),
-            ("2015-02-24", "春节"),
+            ("2015-02-23", "春节（观察日）"),
+            ("2015-02-24", "休息日（2015-02-28日起取代）"),
             ("2015-04-05", "清明节"),
+            ("2015-04-06", "清明节（观察日）"),
             ("2015-05-01", "劳动节"),
             ("2015-06-20", "端午节"),
+            ("2015-06-22", "端午节（观察日）"),
+            ("2015-09-03", "中国人民抗日战争暨世界反法西斯战争胜利70周年纪念日"),
+            ("2015-09-04", "休息日（2015-09-06日起取代）"),
             ("2015-09-27", "中秋节"),
             ("2015-10-01", "国庆节"),
             ("2015-10-02", "国庆节"),
             ("2015-10-03", "国庆节"),
-            ("2015-10-04", "国庆节"),
-            ("2015-10-05", "国庆节"),
-            ("2015-10-06", "国庆节"),
-            ("2015-10-07", "国庆节"),
+            ("2015-10-05", "国庆节（观察日）"),
+            ("2015-10-06", "中秋节（观察日）"),
+            ("2015-10-07", "休息日（2015-10-10日起取代）"),
         )
 
     def test_2016_public_holiday(self):
@@ -565,28 +646,25 @@ def test_2016_public_holiday(self):
         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-02-11", "休息日（2016-02-06日起取代）"),
+            ("2016-02-12", "休息日（2016-02-14日起取代）"),
             ("2016-04-04", "清明节"),
             ("2016-05-01", "劳动节"),
+            ("2016-05-02", "劳动节（观察日）"),
             ("2016-06-09", "端午节"),
-            ("2016-06-10", "端午节"),
-            ("2016-06-11", "端午节"),
+            ("2016-06-10", "休息日（2016-06-12日起取代）"),
             ("2016-09-15", "中秋节"),
-            ("2016-09-16", "中秋节"),
-            ("2016-09-17", "中秋节"),
+            ("2016-09-16", "休息日（2016-09-18日起取代）"),
             ("2016-10-01", "国庆节"),
             ("2016-10-02", "国庆节"),
             ("2016-10-03", "国庆节"),
-            ("2016-10-04", "国庆节"),
-            ("2016-10-05", "国庆节"),
-            ("2016-10-06", "国庆节"),
-            ("2016-10-07", "国庆节"),
+            ("2016-10-04", "国庆节（观察日）"),
+            ("2016-10-05", "国庆节（观察日）"),
+            ("2016-10-06", "休息日（2016-10-08日起取代）"),
+            ("2016-10-07", "休息日（2016-10-09日起取代）"),
         )
 
     def test_2017_public_holiday(self):
@@ -594,28 +672,25 @@ def test_2017_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2017),
             ("2017-01-01", "元旦"),
-            ("2017-01-27", "春节"),
+            ("2017-01-02", "元旦（观察日）"),
+            ("2017-01-27", "休息日（2017-01-22日起取代）"),
             ("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-01-31", "春节（观察日）"),
+            ("2017-02-01", "春节（观察日）"),
+            ("2017-02-02", "休息日（2017-02-04日起取代）"),
+            ("2017-04-03", "休息日（2017-04-01日起取代）"),
             ("2017-04-04", "清明节"),
             ("2017-05-01", "劳动节"),
-            ("2017-05-28", "端午节"),
-            ("2017-05-29", "端午节"),
+            ("2017-05-29", "休息日（2017-05-27日起取代）"),
             ("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", "国庆节"),
+            ("2017-10-04", "中秋节"),
+            ("2017-10-05", "国庆节（观察日）"),
+            ("2017-10-06", "休息日（2017-09-30日起取代）"),
         )
 
     def test_2018_public_holiday(self):
@@ -623,31 +698,25 @@ def test_2018_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2018),
             ("2018-01-01", "元旦"),
-            ("2018-02-15", "春节"),
+            ("2018-02-15", "休息日（2018-02-11日起取代）"),
             ("2018-02-16", "春节"),
             ("2018-02-17", "春节"),
             ("2018-02-18", "春节"),
-            ("2018-02-19", "春节"),
-            ("2018-02-20", "春节"),
-            ("2018-02-21", "春节"),
+            ("2018-02-19", "春节（观察日）"),
+            ("2018-02-20", "春节（观察日）"),
+            ("2018-02-21", "休息日（2018-02-24日起取代）"),
             ("2018-04-05", "清明节"),
-            ("2018-04-06", "清明节"),
-            ("2018-04-07", "清明节"),
-            ("2018-04-29", "劳动节"),
-            ("2018-04-30", "劳动节"),
+            ("2018-04-06", "休息日（2018-04-08日起取代）"),
+            ("2018-04-30", "休息日（2018-04-28日起取代）"),
             ("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", "元旦"),
+            ("2018-10-04", "休息日（2018-09-29日起取代）"),
+            ("2018-10-05", "休息日（2018-09-30日起取代）"),
+            ("2018-12-31", "休息日（2018-12-29日起取代）"),
         )
 
     def test_2019_public_holiday(self):
@@ -655,13 +724,11 @@ def test_2019_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2019),
             ("2019-01-01", "元旦"),
-            ("2019-02-04", "春节"),
+            ("2019-02-04", "休息日（2019-02-02日起取代）"),
             ("2019-02-05", "春节"),
             ("2019-02-06", "春节"),
             ("2019-02-07", "春节"),
-            ("2019-02-08", "春节"),
-            ("2019-02-09", "春节"),
-            ("2019-02-10", "春节"),
+            ("2019-02-08", "休息日（2019-02-03日起取代）"),
             ("2019-04-05", "清明节"),
             ("2019-05-01", "劳动节"),
             ("2019-06-07", "端午节"),
@@ -669,10 +736,8 @@ def test_2019_public_holiday(self):
             ("2019-10-01", "国庆节"),
             ("2019-10-02", "国庆节"),
             ("2019-10-03", "国庆节"),
-            ("2019-10-04", "国庆节"),
-            ("2019-10-05", "国庆节"),
-            ("2019-10-06", "国庆节"),
-            ("2019-10-07", "国庆节"),
+            ("2019-10-04", "休息日（2019-09-29日起取代）"),
+            ("2019-10-07", "休息日（2019-10-12日起取代）"),
         )
 
     def test_2020_public_holiday(self):
@@ -680,32 +745,27 @@ def test_2020_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2020),
             ("2020-01-01", "元旦"),
-            ("2020-01-24", "春节"),
+            ("2020-01-24", "休息日（2020-01-19日起取代）"),
             ("2020-01-25", "春节"),
             ("2020-01-26", "春节"),
             ("2020-01-27", "春节"),
-            ("2020-01-28", "春节"),
-            ("2020-01-29", "春节"),
-            ("2020-01-30", "春节"),
+            ("2020-01-28", "春节（观察日）"),
+            ("2020-01-29", "春节（观察日）"),
+            ("2020-01-30", "休息日（2020-02-01日起取代）"),
             ("2020-04-04", "清明节"),
-            ("2020-04-05", "清明节"),
-            ("2020-04-06", "清明节"),
+            ("2020-04-06", "清明节（观察日）"),
             ("2020-05-01", "劳动节"),
-            ("2020-05-02", "劳动节"),
-            ("2020-05-03", "劳动节"),
-            ("2020-05-04", "劳动节"),
-            ("2020-05-05", "劳动节"),
+            ("2020-05-04", "休息日（2020-04-26日起取代）"),
+            ("2020-05-05", "休息日（2020-05-09日起取代）"),
             ("2020-06-25", "端午节"),
-            ("2020-06-26", "端午节"),
-            ("2020-06-27", "端午节"),
+            ("2020-06-26", "休息日（2020-06-28日起取代）"),
             ("2020-10-01", "中秋节; 国庆节"),
             ("2020-10-02", "国庆节"),
             ("2020-10-03", "国庆节"),
-            ("2020-10-04", "国庆节"),
-            ("2020-10-05", "国庆节"),
-            ("2020-10-06", "国庆节"),
-            ("2020-10-07", "国庆节"),
-            ("2020-10-08", "国庆节"),
+            ("2020-10-05", "国庆节（观察日）"),
+            ("2020-10-06", "中秋节（观察日）"),
+            ("2020-10-07", "休息日（2020-09-27日起取代）"),
+            ("2020-10-08", "休息日（2020-10-10日起取代）"),
         )
 
     def test_2021_public_holiday(self):
@@ -713,36 +773,29 @@ def test_2021_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2021),
             ("2021-01-01", "元旦"),
-            ("2021-01-02", "元旦"),
-            ("2021-01-03", "元旦"),
-            ("2021-02-11", "春节"),
+            ("2021-02-11", "休息日（2021-02-07日起取代）"),
             ("2021-02-12", "春节"),
             ("2021-02-13", "春节"),
             ("2021-02-14", "春节"),
-            ("2021-02-15", "春节"),
-            ("2021-02-16", "春节"),
-            ("2021-02-17", "春节"),
-            ("2021-04-03", "清明节"),
+            ("2021-02-15", "春节（观察日）"),
+            ("2021-02-16", "春节（观察日）"),
+            ("2021-02-17", "休息日（2021-02-20日起取代）"),
             ("2021-04-04", "清明节"),
-            ("2021-04-05", "清明节"),
+            ("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-05-03", "劳动节（观察日）"),
+            ("2021-05-04", "休息日（2021-04-25日起取代）"),
+            ("2021-05-05", "休息日（2021-05-08日起取代）"),
             ("2021-06-14", "端午节"),
-            ("2021-09-19", "中秋节"),
-            ("2021-09-20", "中秋节"),
+            ("2021-09-20", "休息日（2021-09-18日起取代）"),
             ("2021-09-21", "中秋节"),
             ("2021-10-01", "国庆节"),
             ("2021-10-02", "国庆节"),
             ("2021-10-03", "国庆节"),
-            ("2021-10-04", "国庆节"),
-            ("2021-10-05", "国庆节"),
-            ("2021-10-06", "国庆节"),
-            ("2021-10-07", "国庆节"),
+            ("2021-10-04", "国庆节（观察日）"),
+            ("2021-10-05", "国庆节（观察日）"),
+            ("2021-10-06", "休息日（2021-09-26日起取代）"),
+            ("2021-10-07", "休息日（2021-10-09日起取代）"),
         )
 
     def test_2022_public_holiday(self):
@@ -750,38 +803,28 @@ def test_2022_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2022),
             ("2022-01-01", "元旦"),
-            ("2022-01-02", "元旦"),
-            ("2022-01-03", "元旦"),
-            ("2022-01-31", "春节"),
+            ("2022-01-03", "元旦（观察日）"),
+            ("2022-01-31", "休息日（2022-01-29日起取代）"),
             ("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-02-04", "休息日（2022-01-30日起取代）"),
+            ("2022-04-04", "休息日（2022-04-02日起取代）"),
             ("2022-04-05", "清明节"),
-            ("2022-04-30", "劳动节"),
             ("2022-05-01", "劳动节"),
-            ("2022-05-02", "劳动节"),
-            ("2022-05-03", "劳动节"),
-            ("2022-05-04", "劳动节"),
+            ("2022-05-02", "劳动节（观察日）"),
+            ("2022-05-03", "休息日（2022-04-24日起取代）"),
+            ("2022-05-04", "休息日（2022-05-07日起取代）"),
             ("2022-06-03", "端午节"),
-            ("2022-06-04", "端午节"),
-            ("2022-06-05", "端午节"),
             ("2022-09-10", "中秋节"),
-            ("2022-09-11", "中秋节"),
-            ("2022-09-12", "中秋节"),
+            ("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", "元旦"),
+            ("2022-10-04", "国庆节（观察日）"),
+            ("2022-10-05", "国庆节（观察日）"),
+            ("2022-10-06", "休息日（2022-10-08日起取代）"),
+            ("2022-10-07", "休息日（2022-10-09日起取代）"),
         )
 
     def test_2023_public_holiday(self):
@@ -789,31 +832,53 @@ def test_2023_public_holiday(self):
         self.assertHolidays(
             China(categories=PUBLIC, years=2023),
             ("2023-01-01", "元旦"),
-            ("2023-01-02", "元旦"),
-            ("2023-01-21", "春节"),
+            ("2023-01-02", "元旦（观察日）"),
             ("2023-01-22", "春节"),
             ("2023-01-23", "春节"),
             ("2023-01-24", "春节"),
-            ("2023-01-25", "春节"),
-            ("2023-01-26", "春节"),
-            ("2023-01-27", "春节"),
+            ("2023-01-25", "春节（观察日）"),
+            ("2023-01-26", "休息日（2023-01-28日起取代）"),
+            ("2023-01-27", "休息日（2023-01-29日起取代）"),
             ("2023-04-05", "清明节"),
-            ("2023-04-29", "劳动节"),
-            ("2023-04-30", "劳动节"),
             ("2023-05-01", "劳动节"),
-            ("2023-05-02", "劳动节"),
-            ("2023-05-03", "劳动节"),
+            ("2023-05-02", "休息日（2023-04-23日起取代）"),
+            ("2023-05-03", "休息日（2023-05-06日起取代）"),
             ("2023-06-22", "端午节"),
-            ("2023-06-23", "端午节"),
-            ("2023-06-24", "端午节"),
+            ("2023-06-23", "休息日（2023-06-25日起取代）"),
             ("2023-09-29", "中秋节"),
-            ("2023-09-30", "中秋节"),
             ("2023-10-01", "国庆节"),
             ("2023-10-02", "国庆节"),
             ("2023-10-03", "国庆节"),
-            ("2023-10-04", "国庆节"),
-            ("2023-10-05", "国庆节"),
-            ("2023-10-06", "国庆节"),
+            ("2023-10-04", "国庆节（观察日）"),
+            ("2023-10-05", "休息日（2023-10-07日起取代）"),
+            ("2023-10-06", "休息日（2023-10-08日起取代）"),
+        )
+
+    def test_2024_public_holiday(self):
+        # https://www.gov.cn/zhengce/content/202310/content_6911527.htm
+        self.assertHolidays(
+            China(categories=PUBLIC, years=2024),
+            ("2024-01-01", "元旦"),
+            ("2024-02-10", "春节"),
+            ("2024-02-11", "春节"),
+            ("2024-02-12", "春节"),
+            ("2024-02-13", "春节（观察日）"),
+            ("2024-02-14", "春节（观察日）"),
+            ("2024-02-15", "休息日（2024-02-04日起取代）"),
+            ("2024-02-16", "休息日（2024-02-18日起取代）"),
+            ("2024-04-04", "清明节"),
+            ("2024-04-05", "休息日（2024-04-07日起取代）"),
+            ("2024-05-01", "劳动节"),
+            ("2024-05-02", "休息日（2024-04-28日起取代）"),
+            ("2024-05-03", "休息日（2024-05-11日起取代）"),
+            ("2024-06-10", "端午节"),
+            ("2024-09-16", "休息日（2024-09-14日起取代）"),
+            ("2024-09-17", "中秋节"),
+            ("2024-10-01", "国庆节"),
+            ("2024-10-02", "国庆节"),
+            ("2024-10-03", "国庆节"),
+            ("2024-10-04", "休息日（2024-09-29日起取代）"),
+            ("2024-10-07", "休息日（2024-10-12日起取代）"),
         )
 
     def test_2022_half_day_holiday(self):
@@ -837,158 +902,122 @@ def test_2023_half_day_holiday(self):
     def test_l10n_default(self):
         self.assertLocalizedHolidays(
             ("2022-01-01", "元旦"),
-            ("2022-01-02", "元旦"),
-            ("2022-01-03", "元旦"),
-            ("2022-01-31", "春节"),
+            ("2022-01-03", "元旦（观察日）"),
+            ("2022-01-31", "休息日（2022-01-29日起取代）"),
             ("2022-02-01", "春节"),
             ("2022-02-02", "春节"),
             ("2022-02-03", "春节"),
-            ("2022-02-04", "春节"),
-            ("2022-02-05", "春节"),
-            ("2022-02-06", "春节"),
+            ("2022-02-04", "休息日（2022-01-30日起取代）"),
             ("2022-03-08", "国际妇女节"),
-            ("2022-04-03", "清明节"),
-            ("2022-04-04", "清明节"),
+            ("2022-04-04", "休息日（2022-04-02日起取代）"),
             ("2022-04-05", "清明节"),
-            ("2022-04-30", "劳动节"),
             ("2022-05-01", "劳动节"),
-            ("2022-05-02", "劳动节"),
-            ("2022-05-03", "劳动节"),
-            ("2022-05-04", "五四青年节; 劳动节"),
+            ("2022-05-02", "劳动节（观察日）"),
+            ("2022-05-03", "休息日（2022-04-24日起取代）"),
+            ("2022-05-04", "五四青年节; 休息日（2022-05-07日起取代）"),
             ("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-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", "元旦"),
+            ("2022-10-04", "国庆节（观察日）"),
+            ("2022-10-05", "国庆节（观察日）"),
+            ("2022-10-06", "休息日（2022-10-08日起取代）"),
+            ("2022-10-07", "休息日（2022-10-09日起取代）"),
         )
 
     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-01-03", "New Year's Day (Observed)"),
+            ("2022-01-31", "Day off (substituted from 01/29/2022)"),
             ("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-02-04", "Day off (substituted from 01/30/2022)"),
             ("2022-03-08", "International Women's Day"),
-            ("2022-04-03", "Tomb-Sweeping Day"),
-            ("2022-04-04", "Tomb-Sweeping Day"),
+            ("2022-04-04", "Day off (substituted from 04/02/2022)"),
             ("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-05-02", "Labor Day (Observed)"),
+            ("2022-05-03", "Day off (substituted from 04/24/2022)"),
+            ("2022-05-04", "Day off (substituted from 05/07/2022); 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-09-12", "Mid-Autumn Festival (Observed)"),
             ("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"),
+            ("2022-10-04", "National Day (Observed)"),
+            ("2022-10-05", "National Day (Observed)"),
+            ("2022-10-06", "Day off (substituted from 10/08/2022)"),
+            ("2022-10-07", "Day off (substituted from 10/09/2022)"),
         )
 
     def test_l10n_th(self):
         self.assertLocalizedHolidays(
             "th",
             ("2022-01-01", "วันปีใหม่สากล"),
-            ("2022-01-02", "วันปีใหม่สากล"),
-            ("2022-01-03", "วันปีใหม่สากล"),
-            ("2022-01-31", "วันตรุษจีน"),
+            ("2022-01-03", "ชดเชยวันปีใหม่สากล"),
+            ("2022-01-31", "วันหยุด (แทน 29/01/2022)"),
             ("2022-02-01", "วันตรุษจีน"),
             ("2022-02-02", "วันตรุษจีน"),
             ("2022-02-03", "วันตรุษจีน"),
-            ("2022-02-04", "วันตรุษจีน"),
-            ("2022-02-05", "วันตรุษจีน"),
-            ("2022-02-06", "วันตรุษจีน"),
+            ("2022-02-04", "วันหยุด (แทน 30/01/2022)"),
             ("2022-03-08", "วันสตรีสากล"),
-            ("2022-04-03", "วันเช็งเม้ง"),
-            ("2022-04-04", "วันเช็งเม้ง"),
+            ("2022-04-04", "วันหยุด (แทน 02/04/2022)"),
             ("2022-04-05", "วันเช็งเม้ง"),
-            ("2022-04-30", "วันแรงงาน"),
             ("2022-05-01", "วันแรงงาน"),
-            ("2022-05-02", "วันแรงงาน"),
-            ("2022-05-03", "วันแรงงาน"),
-            ("2022-05-04", "วันเยาวชนห่งชาติจีน; วันแรงงาน"),
+            ("2022-05-02", "ชดเชยวันแรงงาน"),
+            ("2022-05-03", "วันหยุด (แทน 24/04/2022)"),
+            ("2022-05-04", "วันหยุด (แทน 07/05/2022); วันเยาวชนห่งชาติจีน"),
             ("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-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", "วันปีใหม่สากล"),
+            ("2022-10-04", "ชดเชยวันชาติจีน"),
+            ("2022-10-05", "ชดเชยวันชาติจีน"),
+            ("2022-10-06", "วันหยุด (แทน 08/10/2022)"),
+            ("2022-10-07", "วันหยุด (แทน 09/10/2022)"),
         )
 
     def test_l10n_zh_tw(self):
         self.assertLocalizedHolidays(
             "zh_TW",
             ("2022-01-01", "元旦"),
-            ("2022-01-02", "元旦"),
-            ("2022-01-03", "元旦"),
-            ("2022-01-31", "春節"),
+            ("2022-01-03", "元旦（觀察日）"),
+            ("2022-01-31", "休息日（2022-01-29日起取代）"),
             ("2022-02-01", "春節"),
             ("2022-02-02", "春節"),
             ("2022-02-03", "春節"),
-            ("2022-02-04", "春節"),
-            ("2022-02-05", "春節"),
-            ("2022-02-06", "春節"),
+            ("2022-02-04", "休息日（2022-01-30日起取代）"),
             ("2022-03-08", "國際婦女節"),
-            ("2022-04-03", "清明節"),
-            ("2022-04-04", "清明節"),
+            ("2022-04-04", "休息日（2022-04-02日起取代）"),
             ("2022-04-05", "清明節"),
-            ("2022-04-30", "勞動節"),
             ("2022-05-01", "勞動節"),
-            ("2022-05-02", "勞動節"),
-            ("2022-05-03", "勞動節"),
-            ("2022-05-04", "五四青年節; 勞動節"),
+            ("2022-05-02", "勞動節（觀察日）"),
+            ("2022-05-03", "休息日（2022-04-24日起取代）"),
+            ("2022-05-04", "五四青年節; 休息日（2022-05-07日起取代）"),
             ("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-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", "元旦"),
+            ("2022-10-04", "國慶日（觀察日）"),
+            ("2022-10-05", "國慶日（觀察日）"),
+            ("2022-10-06", "休息日（2022-10-08日起取代）"),
+            ("2022-10-07", "休息日（2022-10-09日起取代）"),
         )