Repository: peopledoc/workalendar
Pull request #306 (2019-01-04 03:51:08)

Add New Zealand Calendar
refs #247 

For information, read and make sure you're okay with the [CONTRIBUTING document](https://github.com/novafloss/workalendar/blob/master/CONTRIBUTING.rst#adding-new-calendars).

- [x] Tests with a significant number of years to be tested for your calendar.
- [x] Docstrings for the Calendar class and specific methods.
- [x] Calendar country / label added to the README.rst file,
- [x] Changelog amended with a mention like: "Added ``<country>`` by ``@pseudo`` (#)"


brunobord: Thank you a lot for your contribution.

I see in this PR that there's an issue with pandas ; so I'll try to find a way to solve this incompatibility.
I'll keep you posted.
brunobord: All right, so master is now Python 3.4 - ready, so you can **rebase** your branch from master (or you may checkout the upstream repository, and cherry-pick your commits and make another pull-request if you prefer).
This way, I'm almost sure that we may add NZ calendars as soon as possible!

Patch:
diff --git a/Changelog.md b/Changelog.md
index dd352ad..b3c7f68 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,10 @@
 
 * Solved the incompatibility between `pandas` latest version and Python 3.4. Upgraded travis distro to Xenial/16.04 LTS (#307).
 
+### New Calendars
+
+- Added New Zealand, by @johnguant (#306)
+
 ## v3.2.1 (2018-12-06)
 
 ### Bugfixes
diff --git a/README.rst b/README.rst
index c145662..19b035a 100644
--- a/README.rst
+++ b/README.rst
@@ -140,6 +140,7 @@ Oceania
 
 * Australia (incl. its different states)
 * Marshall Islands
+* New Zealand
 
 Africa
 ------
diff --git a/workalendar/oceania/__init__.py b/workalendar/oceania/__init__.py
index fb247a1..788b40d 100644
--- a/workalendar/oceania/__init__.py
+++ b/workalendar/oceania/__init__.py
@@ -12,6 +12,7 @@ from .australia import (
     WesternAustralia
 )
 from .marshall_islands import MarshallIslands
+from .new_zealand import NewZealand
 
 
 __all__ = (
@@ -28,4 +29,5 @@ __all__ = (
     'WesternAustralia',
     # Other oceanian countries
     'MarshallIslands',
+    'NewZealand',
 )
diff --git a/workalendar/oceania/new_zealand.py b/workalendar/oceania/new_zealand.py
new file mode 100644
index 0000000..dc1d3a2
--- /dev/null
+++ b/workalendar/oceania/new_zealand.py
@@ -0,0 +1,87 @@
+# -*- coding: utf-8 -*-
+from datetime import date, timedelta
+
+from workalendar.core import WesternCalendar, ChristianMixin
+from workalendar.core import MON, SAT, SUN
+from workalendar.registry import iso_register
+
+
+@iso_register("NZ")
+class NewZealand(WesternCalendar, ChristianMixin):
+    "New Zealand"
+    include_good_friday = True
+    include_easter_monday = True
+    include_boxing_day = True
+
+    FIXED_HOLIDAYS = WesternCalendar.FIXED_HOLIDAYS + (
+        (1, 2, "Day after New Year's Day"),
+        (2, 6, "Waitangi Day"),
+        (4, 25, "ANZAC Day")
+    )
+
+    def get_queens_birthday(self, year):
+        return (
+            NewZealand.get_nth_weekday_in_month(year, 6, MON, 1),
+            "Queen's Birthday"
+        )
+
+    def get_labour_day(self, year):
+        return (
+            NewZealand.get_nth_weekday_in_month(year, 10, MON, 4),
+            "Labour Day"
+        )
+
+    def get_variable_days(self, year):
+        # usual variable days
+        days = super(NewZealand, self).get_variable_days(year)
+        days.append(self.get_queens_birthday(year))
+        days.append(self.get_labour_day(year))
+
+        waitangi_day = date(year, 2, 6)
+        if waitangi_day.weekday() in self.get_weekend_days():
+            days.append((
+                self.find_following_working_day(waitangi_day),
+                "Waitangi Day Shift")
+            )
+
+        anzac_day = date(year, 4, 25)
+        if anzac_day.weekday() in self.get_weekend_days():
+            days.append((
+                self.find_following_working_day(anzac_day),
+                "ANZAC Day Shift")
+            )
+
+        christmas = date(year, 12, 25)
+        boxing_day = date(year, 12, 26)
+        if christmas.weekday() is SAT:
+            shift = self.find_following_working_day(christmas)
+            days.append((shift, "Christmas Shift"))
+        elif christmas.weekday() is SUN:
+            shift = self.find_following_working_day(christmas)
+            days.append((shift + timedelta(days=1), "Christmas Shift"))
+
+        if boxing_day.weekday() is SAT:
+            shift = self.find_following_working_day(boxing_day)
+            days.append((shift, "Boxing Day Shift"))
+        elif boxing_day.weekday() is SUN:
+            shift = self.find_following_working_day(boxing_day)
+            days.append((shift + timedelta(days=1), "Boxing Day Shift"))
+
+        new_year = date(year, 1, 1)
+        day_after_new_year = date(year, 1, 2)
+        if new_year.weekday() is SAT:
+            shift = self.find_following_working_day(new_year)
+            days.append((shift, "New Year Shift"))
+        elif new_year.weekday() is SUN:
+            shift = self.find_following_working_day(new_year)
+            days.append((shift + timedelta(days=1), "New Year Shift"))
+
+        if day_after_new_year.weekday() is SAT:
+            shift = self.find_following_working_day(day_after_new_year)
+            days.append((shift, "Day after New Year's Day Shift"))
+        elif day_after_new_year.weekday() is SUN:
+            shift = self.find_following_working_day(day_after_new_year)
+            days.append((shift + timedelta(days=1),
+                         "Day after New Year's Day Shift"))
+
+        return days


Test patch:
diff --git a/workalendar/tests/test_oceania.py b/workalendar/tests/test_oceania.py
index a5409fd..b18abeb 100644
--- a/workalendar/tests/test_oceania.py
+++ b/workalendar/tests/test_oceania.py
@@ -13,6 +13,7 @@ from workalendar.oceania import (
     Victoria,
     WesternAustralia,
     MarshallIslands,
+    NewZealand
 )
 
 
@@ -238,3 +239,60 @@ class MarshallIslandsTest(GenericCalendarTest):
         self.assertIn(date(2013, 12, 6), holidays)  # gospel day
         self.assertIn(date(2013, 12, 25), holidays)  # Xmas
         self.assertIn(date(2013, 12, 31), holidays)  # new year's eve
+
+
+class NewZealandTest(GenericCalendarTest):
+    cal_class = NewZealand
+
+    def test_year_2018(self):
+        holidays = self.cal.holidays_set(2018)
+        self.assertIn(date(2018, 1, 1), holidays)  # New Year's Day
+        self.assertIn(date(2018, 1, 2), holidays)  # Day after New Year's Day
+        self.assertIn(date(2018, 2, 6), holidays)  # Waitangi Day
+        self.assertIn(date(2018, 3, 30), holidays)  # Good Friday
+        self.assertIn(date(2018, 4, 2), holidays)  # Easter Monday
+        self.assertIn(date(2018, 4, 25), holidays)  # ANZAC Day
+        self.assertIn(date(2018, 6, 4), holidays)  # Queen's Birthday
+        self.assertIn(date(2018, 10, 22), holidays)  # Labour Day
+        self.assertIn(date(2018, 12, 25), holidays)  # Christmas Day
+        self.assertIn(date(2018, 12, 26), holidays)  # Boxing Day
+
+    def test_new_year_shift(self):
+        holidays = self.cal.holidays_set(2012)
+        # New Years was on a sunday
+        # Day After New Years is on the 2nd
+        self.assertIn(date(2012, 1, 2), holidays)
+        # New Years Shift is on the 3rd
+        self.assertIn(date(2012, 1, 3), holidays)
+
+    def test_anzac_shift(self):
+        holidays = self.cal.holidays_set(2010)
+        # 25th was a sunday
+        # ANZAC Day is on 25th
+        self.assertIn(date(2010, 4, 25), holidays)
+        # ANZAC Day Shift is on 26th
+        self.assertIn(date(2010, 4, 26), holidays)
+
+    def test_waitangi_shift(self):
+        holidays = self.cal.holidays_set(2016)
+        # 6th was a saturday
+        # Waitangi Day is on 6th
+        self.assertIn(date(2016, 2, 6), holidays)
+        # Waitangi Day Shift is on 7th
+        self.assertIn(date(2016, 2, 8), holidays)
+
+    def test_oceania_shift_2016(self):
+        holidays = self.cal.holidays_set(2016)
+        # Christmas day is on sunday in 2016
+        # Boxing day is on 26th
+        self.assertIn(date(2016, 12, 26), holidays)
+        # Christmas day shift on 27th
+        self.assertIn(date(2016, 12, 27), holidays)
+
+    def test_oceania_shift_2009(self):
+        holidays = self.cal.holidays_set(2009)
+        # Boxing day is on saturday in 2009
+        # Boxing day is on 26th
+        self.assertIn(date(2009, 12, 26), holidays)
+        # Boxing day shift on 28th
+        self.assertIn(date(2009, 12, 28), holidays)
diff --git a/workalendar/tests/test_registry_oceania.py b/workalendar/tests/test_registry_oceania.py
index 44a6d52..cb15c63 100644
--- a/workalendar/tests/test_registry_oceania.py
+++ b/workalendar/tests/test_registry_oceania.py
@@ -4,6 +4,7 @@ from unittest import TestCase
 from workalendar.oceania import (
     Australia,
     MarshallIslands,
+    NewZealand,
     # Australian territories
     AustralianCapitalTerritory,
     NewSouthWales,
@@ -37,6 +38,7 @@ class RegistryOceania(TestCase):
         classes = list(classes)
         self.assertIn(Australia, classes)
         self.assertIn(MarshallIslands, classes)
+        self.assertIn(NewZealand, classes)
         for klass in AUSTRALIAN_TERRITORIES:
             self.assertIn(klass, classes)