Repository: peopledoc/workalendar
Pull request #286 (2018-10-11 15:13:08)

South Africa cleanup and extended class
Cleans up SouthAfrica class and tests to take into account the specs of holidays that vary over the periods.
As a side-effect, it effectively cleans the duplicates that were generated by the previous code.

refs #285 

- [x] Tests with a significant number of years to be tested for your calendar.
- [x] Changelog amended with a mention describing your changes.



Patch:
diff --git a/Changelog.md b/Changelog.md
index 4400384..da86153 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -3,6 +3,9 @@
 ## master (unreleased)
 
 - Added support for Python 3.7 (#283).
+- Bugfix for South Africa: disableing the possibility to compute holidays prior to the year 1910.
+- Cleans up SouthAfrica class and tests to take into account the specs of holidays that vary over the periods. As a consequence, it cleans up erroneous holidays that were duplicated in some years (#285). Thx to @surfer190 for his review & suggestions.
+- Minor change: Renamed Madagascar test class name into `MadagascarTest` (#286).
 
 ## v3.0.0 (2019-09-20)
 
diff --git a/workalendar/africa/south_africa.py b/workalendar/africa/south_africa.py
index bfb5a0b..0d5c448 100644
--- a/workalendar/africa/south_africa.py
+++ b/workalendar/africa/south_africa.py
@@ -5,8 +5,9 @@ from __future__ import (absolute_import, division, print_function,
 from datetime import timedelta, date
 
 from ..core import WesternCalendar
-from ..core import SUN, MON
+from ..core import SUN, MON, FRI
 from ..core import ChristianMixin
+from ..exceptions import CalendarError
 from ..registry import iso_register
 
 
@@ -14,54 +15,110 @@ from ..registry import iso_register
 class SouthAfrica(WesternCalendar, ChristianMixin):
     "South Africa"
     include_good_friday = True
-    include_easter_monday = True
     include_christmas = True
-    include_boxing_day = True
 
-    FIXED_HOLIDAYS = WesternCalendar.FIXED_HOLIDAYS + (
-        (5, 1, "Workers Day"),
-        (12, 16, "Day of reconcilation"),
-    )
+    def holidays(self, year=None):
+        if year < 1910:
+            raise CalendarError("It's not possible to compute holidays prior"
+                                " to 1910 for South Africa.")
+        return super(SouthAfrica, self).holidays(year)
 
-    def get_family_day(self, year):
-        return (self.get_good_friday(year), "Family Day")
+    def get_easter_monday_or_family_day(self, year):
+        if year < 1980:
+            label = "Easter Monday"
+        else:
+            label = "Family Day"
+        return (self.get_easter_monday(year), label)
 
     def get_fixed_holidays(self, year):
         days = super(SouthAfrica, self).get_fixed_holidays(year)
-        if year < 1952:
-            days.append((date(year, 5, 24), "Empire Day"))
-        if year >= 1952 and year <= 1974:
+        if year >= 1990:
+            days.append((date(year, 3, 21), 'Human Rights Day'))
+
+        # Van Riebeeck's day & Founder's day
+        if year >= 1952 and year <= 1973:
             days.append((date(year, 4, 6), "Van Riebeeck's Day"))
-        if year >= 1952 and year <= 1979:
-            days.append((self.get_nth_weekday_in_month(year, 9, MON, 1),
-                         "Settlers' Day"))
-        if year >= 1952 and year <= 1993:
-            days.append((date(year, 10, 10), "Kruger Day"))
-        if year <= 1960:
-            days.append((date(year, 5, 31), "Union Day"))
-        if year > 1960 and year <= 1993:
-            days.append((date(year, 5, 31), "Republic Day"))
-        if year > 1960 and year <= 1974:
-            days.append((date(year, 7, 10), "Family Day"))
         if year >= 1980 and year <= 1994:
             days.append((date(year, 4, 6), "Founder's Day"))
-        if year >= 1990:
-            days.append((date(year, 3, 21), 'Human Rights Day'))
-        if year <= 1993:
-            days.append((self.get_ascension_thursday(year), "Ascension Day"))
+
         if year >= 1994:
             days.append((date(year, 4, 27), "Freedom Day"))
-            days.append((date(year, 12, 26), "Day of good will"))
+
+        # Workers day established in 1995 to May 1st
+        if year >= 1995:
+            days.append((date(year, 5, 1), "Workers' Day"))
+
+        if year <= 1951:
+            days.append((date(year, 5, 24), "Victoria Day / Empire Day"))
+
+        # May 31st: Union Day & Republic Day
+        if year <= 1960:
+            days.append((date(year, 5, 31), "Union Day"))
+        elif year <= 1993:
+            days.append((date(year, 5, 31), "Republic Day"))
+
         if year >= 1995:
             days.append((date(year, 6, 16), "Youth Day"))
-            days.append((date(year, 8, 9), "National Women Day"))
+
+        if year > 1960 and year <= 1973:
+            days.append((date(year, 7, 10), "Family Day"))
+
+        if year >= 1995:
+            days.append((date(year, 8, 9), "National Women's Day"))
             days.append((date(year, 9, 24), "Heritage Day"))
 
+        if year >= 1952 and year <= 1993:
+            days.append((date(year, 10, 10), "Kruger Day"))
+
+        if year <= 1951:
+            december_16th_label = "Dingaan's Day"
+        elif 1952 <= year <= 1979:
+            december_16th_label = "Day of the Covenant"
+        elif 1980 <= year <= 1994:
+            december_16th_label = "Day of the Vow"
+        else:
+            december_16th_label = "Day of Reconciliation"
+        days.append((date(year, 12, 16), december_16th_label))
+
+        # Boxing day renamed
+        boxing_day_label = "Boxing Day"
+        if year >= 1980:
+            boxing_day_label = "Day of Goodwill"
+        days.append((date(year, 12, 26), boxing_day_label))
+
         return days
 
     def get_variable_days(self, year):
         days = super(SouthAfrica, self).get_variable_days(year)
-        days.append(self.get_family_day(year))
+
+        days.append(self.get_easter_monday_or_family_day(year))
+
+        # Workers day was first friday of may 1987-1989
+        if 1987 <= year <= 1989:
+            days.append(
+                (self.get_nth_weekday_in_month(year, 5, FRI), "Workers' Day")
+            )
+
+        if year <= 1993:
+            days.append((self.get_ascension_thursday(year), "Ascension Day"))
+
+        # Queen's Birthday on the 2nd Monday of july 1952-1960
+        if 1952 <= year <= 1960:
+            days.append((
+                self.get_nth_weekday_in_month(year, 7, MON, 2),
+                "Queen's Birthday"
+            ))
+
+        # King's Birthday on the first Monday of August 1910-1951
+        if 1910 <= year <= 1951:
+            days.append((
+                self.get_nth_weekday_in_month(year, 8, MON),
+                "King's Birthday"
+            ))
+
+        if year >= 1952 and year <= 1979:
+            days.append((self.get_nth_weekday_in_month(year, 9, MON),
+                         "Settlers' Day"))
         return days
 
     def get_calendar_holidays(self, year):
diff --git a/workalendar/exceptions.py b/workalendar/exceptions.py
new file mode 100644
index 0000000..ac9aa32
--- /dev/null
+++ b/workalendar/exceptions.py
@@ -0,0 +1,9 @@
+"""
+Core Workalendar Exceptions
+"""
+
+
+class CalendarError(Exception):
+    """
+    Base Calendar Error
+    """


Test patch:
diff --git a/workalendar/tests/test_africa.py b/workalendar/tests/test_africa.py
index 2718f1c..e2046dc 100644
--- a/workalendar/tests/test_africa.py
+++ b/workalendar/tests/test_africa.py
@@ -10,7 +10,8 @@ from workalendar.africa import (
     SaoTomeAndPrincipe,
     SouthAfrica,
 )
-from workalendar.core import MON
+from workalendar.core import MON, FRI
+from workalendar.exceptions import CalendarError
 
 
 class AlgeriaTest(GenericCalendarTest):
@@ -54,11 +55,15 @@ class BeninTest(GenericCalendarTest):
 class SouthAfricaTest(GenericCalendarTest):
     cal_class = SouthAfrica
 
+    def test_before_1910(self):
+        with self.assertRaises(CalendarError):
+            self.cal.holidays_set(1909)
+
     def test_year_2013(self):
         holidays = self.cal.holidays_set(2013)
         self.assertIn(date(2013, 1, 1), holidays)  # new year
         self.assertIn(date(2013, 3, 21), holidays)  # human rights day
-        self.assertIn(date(2013, 3, 29), holidays)
+        self.assertIn(date(2013, 3, 29), holidays)  # good friday
         self.assertIn(date(2013, 4, 1), holidays)  # Easter monday / Family day
         self.assertIn(date(2013, 4, 27), holidays)  # freedom day
         self.assertIn(date(2013, 5, 1), holidays)  # labour day
@@ -76,23 +81,349 @@ class SouthAfricaTest(GenericCalendarTest):
         self.assertIn(date(2014, 4, 27), holidays)  # freedom day
         self.assertIn(date(2014, 4, 28), holidays)  # freedom day sub
 
+    def test_easter_monday(self):
+        # 1910-1979, Easter Monday label was "Easter Monday"
+        holidays = self.cal.holidays(1979)
+        easter_monday_1979 = date(1979, 4, 16)
+        holidays_dates = [item[0] for item in holidays]
+        self.assertEqual(holidays_dates.count(easter_monday_1979), 1, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[easter_monday_1979], "Easter Monday")
+
+        # From 1980 to "now", it's Family Day
+        holidays = self.cal.holidays(1980)
+        # Since the Founders' day is a Sunday, the same date appears twice
+        # The second one is a substitute
+        holidays = [item for item in holidays
+                    if item[1] != "Founder's Day substitute"]
+        easter_monday_1980 = date(1980, 4, 7)
+        holidays_dates = [item[0] for item in holidays]
+        self.assertEqual(holidays_dates.count(easter_monday_1980), 1, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[easter_monday_1980], "Family Day")
+
+    def test_april_6th(self):
+        # 1951, no April 6th
+        holidays = self.cal.holidays(1951)
+        holidays_dates = [item[0] for item in holidays]
+        april_6th = date(1951, 4, 6)
+        self.assertNotIn(april_6th, holidays_dates, holidays)
+
+        # 1952-1973, it was named Van Riebeeck's day
+        holidays = self.cal.holidays(1952)
+        holidays_dates = [item[0] for item in holidays]
+        april_6th = date(1952, 4, 6)
+        self.assertIn(april_6th, holidays_dates, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[april_6th], "Van Riebeeck's Day")
+
+        # 1974: No April 6th
+        holidays = self.cal.holidays(1974)
+        holidays_dates = [item[0] for item in holidays]
+        april_6th = date(1974, 4, 6)
+        self.assertNotIn(april_6th, holidays_dates, holidays)
+
+        # 1980-1994, it became Founder's day
+        holidays = self.cal.holidays(1980)
+        holidays_dates = [item[0] for item in holidays]
+        april_6th = date(1980, 4, 6)
+        self.assertIn(april_6th, holidays_dates, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[april_6th], "Founder's Day")
+
+        # 1995, no April 6th
+        holidays = self.cal.holidays(1995)
+        holidays_dates = [item[0] for item in holidays]
+        april_6th = date(1995, 4, 6)
+        self.assertNotIn(april_6th, holidays_dates, holidays)
+
+    def test_workers_day(self):
+        # No Workers' day before 1987
+        holidays = self.cal.holidays(1986)
+        holidays_labels = [item[1] for item in holidays]
+        self.assertNotIn("Workers' Day", holidays_labels, holidays)
+
+        # 1987-1989: 1st Friday in May
+        holidays = self.cal.holidays(1987)
+        holidays_dates = [item[0] for item in holidays]
+        first_friday_may = self.cal.get_nth_weekday_in_month(1987, 5, FRI)
+        self.assertIn(first_friday_may, holidays_dates)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[first_friday_may], "Workers' Day")
+
+        # 1990-1994: No Workers' day
+        holidays = self.cal.holidays(1990)
+        holidays_labels = [item[1] for item in holidays]
+        self.assertNotIn("Workers' Day", holidays_labels, holidays)
+
+        # as of 1995: Workers' day is on May 1st
+        holidays = self.cal.holidays(1995)
+        holidays_dates = [item[0] for item in holidays]
+        first_may = date(1995, 5, 1)
+        self.assertIn(first_may, holidays_dates)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[first_may], "Workers' Day")
+
+    def test_ascension_day(self):
+        # Before 1993 (included), Ascension day was a holiday
+        holidays = self.cal.holidays(1993)
+        holidays_dates = [item[0] for item in holidays]
+        ascension_1993 = self.cal.get_ascension_thursday(1993)
+        self.assertIn(ascension_1993, holidays_dates)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[ascension_1993], "Ascension Day")
+
+        # After 1993, no more Ascension day
+        holidays = self.cal.holidays(1994)
+        holidays_dates = [item[0] for item in holidays]
+        ascension_1994 = self.cal.get_ascension_thursday(1994)
+        self.assertNotIn(ascension_1994, holidays_dates)
+
+    def test_victoria_empire_day(self):
+        # 1910–1951: 24 May is Victoria Day / Empire Day
+        holidays = self.cal.holidays(1951)
+        holidays_dates = [item[0] for item in holidays]
+        may_24th_1951 = date(1951, 5, 24)
+        self.assertIn(may_24th_1951, holidays_dates, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(
+            holidays_dict[may_24th_1951], "Victoria Day / Empire Day")
+
+        # 1952-present, no Victoria / Empire day
+        holidays = self.cal.holidays(1952)
+        holidays_dates = [item[0] for item in holidays]
+        may_24th_1952 = date(1952, 5, 24)
+        self.assertNotIn(may_24th_1952, holidays_dates, holidays)
+
+    def test_may_31st(self):
+        # 1910-1960, it's Union Day
+        holidays = self.cal.holidays(1960)
+        holidays_dates = [item[0] for item in holidays]
+        may_31st_1960 = date(1960, 5, 31)
+        self.assertIn(may_31st_1960, holidays_dates, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[may_31st_1960], "Union Day")
+
+        # 1961-1993, it's Republic Day
+        holidays = self.cal.holidays(1993)
+        holidays_dates = [item[0] for item in holidays]
+        may_31st_1993 = date(1993, 5, 31)
+        self.assertIn(may_31st_1993, holidays_dates, holidays)
+        holidays_dict = dict(holidays)
+        self.assertEqual(holidays_dict[may_31st_1993], "Republic Day")
+
+        # As of 1994, no more may 31st
+        holidays = self.cal.holidays(1994)
+        holidays_dates = [item[0] for item in holidays]
+        may_31st_1994 = date(1994, 5, 31)
+        self.assertNotIn(may_31st_1994, holidays_dates, holidays)
+
+    def test_queens_birthday(self):
+        # Before 1952, no Queens Birthday
+        holidays = self.cal.holidays(1951)
+        holidays_dates = [item[0] for item in holidays]
+        july_2nd_monday = self.cal.get_nth_weekday_in_month(1951, 7, MON, 2)
+        self.assertNotIn(july_2nd_monday, holidays_dates)
+
+        # 1952–1960: 2nd Monday in July is Queen's Birthday
+        for year in (1952, 1959, 1960):  # interval of the years
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            july_2nd_monday = self.cal.get_nth_weekday_in_month(
+                year, 7, MON, 2)
+            self.assertIn(july_2nd_monday, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(
+                holidays_dict[july_2nd_monday],
+                "Queen's Birthday"
+            )
+
+        # After 1961, no more Queen's Birthday
+        for year in (1961, 1962, 2008, 2018):  # interval of the years
+            holidays = self.cal.holidays(year)
+            holidays_labels = [item[1] for item in holidays]
+            self.assertNotIn("Queen's Birthday", holidays_labels)
+
+    def test_womens_day_label(self):
+        holidays = self.cal.holidays(2018)
+        womens_day = date(2018, 8, 9)
+        holidays_dict = dict(holidays)
+        self.assertEqual(
+            holidays_dict[womens_day],
+            "National Women's Day"
+        )
+
+    def test_family_day_in_july(self):
+        # Before 1961, no Family day in July
+        holidays = self.cal.holidays(1960)
+        holidays_dates = [item[0] for item in holidays]
+        family_day = date(1960, 7, 10)
+        self.assertNotIn(family_day, holidays_dates)
+
+        # From 1961 to 1973, Family day is on July 10th
+        for year in (1961, 1970, 1973):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            family_day = date(year, 7, 10)
+            self.assertIn(family_day, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[family_day], "Family Day")
+
+        # As of 1974, no more
+        for year in (1974, 1980, 1990, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            family_day = date(year, 7, 10)
+            self.assertNotIn(family_day, holidays_dates)
+
+    def test_king_birthday(self):
+        # From 1910 to 1951, 1st Monday in August
+        for year in (1910, 1935, 1951):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            king_birthday = self.cal.get_nth_weekday_in_month(year, 8, MON)
+            self.assertIn(king_birthday, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[king_birthday], "King's Birthday")
+
+        # Not after 1952
+        for year in (1952, 1960, 1990, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            king_birthday = self.cal.get_nth_weekday_in_month(year, 8, MON)
+            self.assertNotIn(king_birthday, holidays_dates)
+
+    def test_settlers_day(self):
+        # Before 1952, no settler's day
+        holidays = self.cal.holidays(1951)
+        holidays_dates = [item[0] for item in holidays]
+        settlers_day = self.cal.get_nth_weekday_in_month(1951, 9, MON)
+        self.assertNotIn(settlers_day, holidays_dates)
+
+        # From 1952 to 1979, 1st Monday in August
+        for year in (1952, 1960, 1952, 1979):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            settlers_day = self.cal.get_nth_weekday_in_month(year, 9, MON)
+            self.assertIn(settlers_day, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[settlers_day], "Settlers' Day")
+
+        # Not after 1979
+        for year in (1980, 1990, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            settlers_day = self.cal.get_nth_weekday_in_month(year, 9, MON)
+            self.assertNotIn(settlers_day, holidays_dates)
+
+    def test_kruger_day(self):
+        # Not before 1952
+        holidays = self.cal.holidays(1951)
+        holidays_dates = [item[0] for item in holidays]
+        kruger_day = date(1951, 10, 10)
+        self.assertNotIn(kruger_day, holidays_dates)
+
+        # Kruger Day was on October 10th 1952-1993
+        for year in (1952, 1960, 1952, 1979, 1993):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            kruger_day = date(year, 10, 10)
+            self.assertIn(kruger_day, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[kruger_day], "Kruger Day")
+
+        # As of 1994, not anymore
+        for year in (1994, 2000, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            kruger_day = date(year, 10, 10)
+            self.assertNotIn(kruger_day, holidays_dates)
+
+    def test_december_16th(self):
+        # from 1910 to 1951, it's "Dingaan's Day"
+        for year in (1910, 1930, 1951):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_16th = date(year, 12, 16)
+            self.assertIn(december_16th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[december_16th], "Dingaan's Day")
+
+        # from 1952 to 1979 it's the "Day of the Covenant"
+        for year in (1952, 1960, 1979):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_16th = date(year, 12, 16)
+            self.assertIn(december_16th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(
+                holidays_dict[december_16th], "Day of the Covenant")
+
+        # from 1980 to 1994 it's the "Day of the Vow"
+        # NOTE: wikipedia states it starts at year 1979, but that would mean
+        # there were two labels on the same year, which would be wrong.
+        # We may wait to see if this error is fixed one day.
+        for year in (1980, 1990, 1994):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_16th = date(year, 12, 16)
+            self.assertIn(december_16th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(
+                holidays_dict[december_16th], "Day of the Vow")
+
+        # As of 1995, it's the "Day of Reconciliation"
+        for year in (1995, 2000, 2010, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_16th = date(year, 12, 16)
+            self.assertIn(december_16th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(
+                holidays_dict[december_16th], "Day of Reconciliation")
+
+    def test_december_26th(self):
+        # from 1910 to 1979, it's "Boxing Day"
+        # Year 1910 is excluded, since Christmas was on a Sunday, and shift
+        # rules apply
+        for year in (1911, 1930, 1951, 1979):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_26th = date(year, 12, 26)
+            self.assertIn(december_26th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[december_26th], "Boxing Day", year)
+
+        # As of 1980, it's "Day of Goodwill"
+        for year in (1980, 1990, 1995, 2000, 2018):
+            holidays = self.cal.holidays(year)
+            holidays_dates = [item[0] for item in holidays]
+            december_26th = date(year, 12, 26)
+            self.assertIn(december_26th, holidays_dates)
+            holidays_dict = dict(holidays)
+            self.assertEqual(holidays_dict[december_26th], "Day of Goodwill")
+
     def test_special_1999(self):
-        # National and provincial government elections – 2 June 1999[8]
+        # National and provincial government elections – 2 June 1999
         holidays = self.cal.holidays_set(1999)
         self.assertIn(date(1999, 6, 2), holidays)
+        # December 31st was a "Y2K" holiday
+        self.assertIn(date(1999, 12, 31), holidays)
 
     def test_special_2000(self):
         holidays = self.cal.holidays_set(2000)
+        # Holiday added to celebrate Y2K
         self.assertIn(date(2000, 1, 2), holidays)
+        # Shift day because Jan 2nd was a sunday
         self.assertIn(date(2000, 1, 3), holidays)
 
     def test_special_2004(self):
-        # National and provincial government elections – 14 April 2004[9]
+        # National and provincial government elections – 14 April 2004
         holidays = self.cal.holidays_set(2004)
         self.assertIn(date(2004, 4, 14), holidays)
 
     def test_special_2006(self):
-        # Local government elections – 1 March 2006[10]
+        # Local government elections – 1 March 2006
         holidays = self.cal.holidays_set(2006)
         self.assertIn(date(2006, 3, 1), holidays)
 
@@ -103,63 +434,29 @@ class SouthAfricaTest(GenericCalendarTest):
         self.assertIn(date(2008, 5, 2), holidays)
 
     def test_special_2009(self):
-        # National and provincial government elections – 22 April 2009[11]
+        # National and provincial government elections – 22 April 2009
         holidays = self.cal.holidays_set(2009)
         self.assertIn(date(2009, 4, 22), holidays)
 
     def test_special_2011(self):
-        # Local government elections – 18 May 2011[12]
+        # Local government elections – 18 May 2011
         holidays = self.cal.holidays_set(2011)
         self.assertIn(date(2011, 5, 18), holidays)
         # 27 December 2011 was declared a holiday by president Motlanthe
         self.assertIn(date(2011, 12, 27), holidays)
 
     def test_special_2014(self):
-        # National and provincial government elections – 7 May 2014[13]
+        # National and provincial government elections – 7 May 2014
         holidays = self.cal.holidays_set(2014)
         self.assertIn(date(2014, 5, 7), holidays)
 
     def test_special_2016(self):
-        # Local government elections – 3 August 2016[14]
+        # Local government elections – 3 August 2016
         holidays = self.cal.holidays_set(2016)
         self.assertIn(date(2016, 8, 3), holidays)
 
-    def test_historical_1973(self):
-        # Ascension Day	1910–1993
-        holidays = self.cal.holidays_set(1973)
-        self.assertIn(self.cal.get_ascension_thursday(1973), holidays)
-
-    def test_historical_1974(self):
-        holidays = self.cal.holidays_set(1974)
-        # 6 April	Van Riebeeck's Day / Founder's Day
-        self.assertIn(date(1974, 4, 6), holidays)
-        # 31 May	Union Day / Republic Day
-        self.assertIn(date(1974, 5, 31), holidays)
-        # 10 July	Family Day	1961–1974
-        self.assertIn(date(1974, 7, 10), holidays)
-        # 1st Monday in September	Settlers' Day	1952–1979
-        self.assertIn(self.cal.get_nth_weekday_in_month(1974, 9, MON, 1),
-                      holidays)
-        # 10 October	Kruger Day	1952–1993
-        self.assertIn(date(1974, 10, 10), holidays)
-
-    def test_historical_empire(self):
-        holidays = self.cal.holidays_set(1951)
-        # 24 May	Victoria Day / Empire Day	1910–1951
-        self.assertIn(date(1951, 5, 24), holidays)
-
-    def test_queens_birthday(self):
-        # 2nd Monday in July	Queen's Birthday	1952–1960
-        holidays = self.cal.holidays_set(1960)
-        self.assertIn(date(1960, 5, 2), holidays)
-
-    def test_remove_duplicates(self):
-        holidays = self.cal.holidays(2014)
-        dates = ["{} {}".format(x, y) for x, y in holidays]
-        self.assertEqual(len(dates), len(set(dates)))
-
 
-class Madagascar(GenericCalendarTest):
+class MadagascarTest(GenericCalendarTest):
     cal_class = Madagascar
 
     def test_year_2013(self):