Repository: peopledoc/workalendar (python)

Issue:
New agreed public holiday in Russia
Dear workalendar team,

We were notified, that recently, the Russian government agreed on the occupational calendar for 2021, which brings additional logic to some of the holidays. 

### Year 2021
Is it possible to adjust the holidays for Russia since 2021 accordingly?

The current result:
```python
from workalendar.europe import Russia
Russia().holidays(2021)
[(datetime.date(2021, 1, 1), 'New year'),
 (datetime.date(2021, 1, 2), 'Day After New Year'),
 (datetime.date(2021, 1, 7), 'Christmas'),
 (datetime.date(2021, 2, 23), 'Defendence of the Fatherland'),
 (datetime.date(2021, 3, 8), "International Women's Day"),
 (datetime.date(2021, 5, 1), 'Labour Day'),
 (datetime.date(2021, 5, 9), 'Victory Day'),
 (datetime.date(2021, 6, 12), 'National Day'),
 (datetime.date(2021, 11, 4), 'Day of Unity')]
```

The expected result:
_Note: Saturday 2020-02-20 becomes a working day_
```python
from workalendar.europe import Russia
Russia().holidays(2021)
[(datetime.date(2021, 1, 1, "New Year"),
(datetime.date(2021, 1, 2, "Day After New Year"),
(datetime.date(2021, 1, 3, "Another Day After New Year"),
(datetime.date(2021, 1, 4, "Third Day after New Year"),
(datetime.date(2021, 1, 5, "Fourth Day after New Year"),
(datetime.date(2021, 1, 6, "Fifth Day after New Year"),
(datetime.date(2021, 1, 7, "Christmas"),
(datetime.date(2021, 1, 8, "Day After Christmas"),
#(datetime.date(2021, 2,20, "working day, Saturday"),
(datetime.date(2021, 2, 22, "Day Before Defendence of the Fatherland"),
(datetime.date(2021, 2, 23, "Defendence of the Fatherland"),
(datetime.date(2021, 3, 8, "International Women's Day"),
(datetime.date(2021, 5, 1, "International Workers' Day"),
(datetime.date(2021, 5, 3, "Compensation holiday because International Workers' Day was Saturday"),
(datetime.date(2021, 5, 9, "Victory Day"),
(datetime.date(2021, 5, 10, "Compensation holiday because Victory Day was Sunday"),
(datetime.date(2021, 6, 12, "National Day"),
(datetime.date(2021, 6, 14, "Compensation holiday because National Day was Saturday"),
(datetime.date(2021, 11, 4, "Day of Unity"),
(datetime.date(2021, 11, 5, "Day After Day of Unity"), #just because it is a bridge Friday
(datetime.date(2021, 12, 31, "31st December")]
```

### Past years
Could you also fix the past years (e.g. the year [2020](https://www.timeanddate.com/calendar/custom.html?year=2020&country=20&cols=3&hol=1&df=1) having some missing holidays)? Even though this is past information, it is relevant for the machine learning models during the fitting time.

### Related sources
http://www.consultant.ru/law/ref/calendar/proizvodstvennye/2021/
https://www.timeanddate.com/calendar/custom.html?year=2021&country=20&cols=3&hol=1&df=1


Pull request description:
Fix Russia Holidays for the year 2021
closes #578


- [x] Tests with a significant number of years to be tested for your calendar.
- [x] Changelog amended with a mention describing your changes. **Note** *Please do NOT change the version number here. It's the project maintainers' duty.*


Patch:
diff --git a/Changelog.md b/Changelog.md
index 819b8af..44c2a67 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,7 +2,7 @@
 
 ## master (unreleased)
 
-Nothing here yet.
+- Fix Russia 2021 holidays, thx @MichalChromcak for the bug report (#578).
 
 ## v14.0.0 (2020-11-27)
 
diff --git a/workalendar/europe/russia.py b/workalendar/europe/russia.py
index be12e44..fd21743 100644
--- a/workalendar/europe/russia.py
+++ b/workalendar/europe/russia.py
@@ -1,6 +1,6 @@
 from datetime import date
 
-from ..core import OrthodoxCalendar, MON, daterange
+from ..core import OrthodoxCalendar, MON, daterange, cleaned_date
 from ..registry_tools import iso_register
 
 
@@ -26,6 +26,12 @@ class Russia(OrthodoxCalendar):
     covid19_2020_end = date(2020, 4, 30)
 
     def get_fixed_holidays(self, year):
+
+        if year >= 1992:
+            self.labour_day_label = "The Day of Spring and Labour"
+        else:
+            self.labour_day_label = "International Workers' Day"
+
         days = super().get_fixed_holidays(year)
 
         if year >= 2005:
@@ -61,6 +67,12 @@ class Russia(OrthodoxCalendar):
 
             # Constitution Vote Public Holiday
             days.append((date(year, 7, 1), "Constitution Vote Public Holiday"))
+        elif year == 2021:
+            days.extend([
+                (date(year, 2, 22), "Day Before Defendence of the Fatherland"),
+                (date(year, 11, 5), 'Day After Day of Unity'),
+                (date(year, 12, 31), "New Year's Eve"),
+            ])
         return days
 
     def get_calendar_holidays(self, year):
@@ -79,3 +91,14 @@ class Russia(OrthodoxCalendar):
                 ))
         holidays.extend(shifts)
         return holidays
+
+    def is_working_day(self, day,
+                       extra_working_days=None, extra_holidays=None):
+        day = cleaned_date(day)
+        if day == date(2021, 2, 20):
+            return True
+        return super().is_working_day(
+            day,
+            extra_working_days=extra_working_days,
+            extra_holidays=extra_holidays
+        )


Test patch:
diff --git a/workalendar/tests/test_europe.py b/workalendar/tests/test_europe.py
index ccaf9fb..7c01732 100644
--- a/workalendar/tests/test_europe.py
+++ b/workalendar/tests/test_europe.py
@@ -1,4 +1,4 @@
-from datetime import date, timedelta
+from datetime import date, timedelta, datetime
 from collections import Counter
 
 from . import GenericCalendarTest
@@ -1518,6 +1518,39 @@ class RussiaTest(GenericCalendarTest):
         holidays = self.cal.holidays_set(2020)
         self.assertNotIn(date(2020, 12, 25), holidays)
 
+    def test_holidays_2021(self):
+        holidays = self.cal.holidays(2021)
+        holidays_2021 = [
+            (date(2021, 1, 1), "New year"),
+            (date(2021, 1, 2), "Day After New Year"),  # SAT
+            (date(2021, 1, 3), "Third Day after New Year"),  # SUN
+            (date(2021, 1, 4), "Fourth Day after New Year"),
+            (date(2021, 1, 5), "Fifth Day after New Year"),
+            (date(2021, 1, 6), "Sixth Day after New Year"),
+            (date(2021, 1, 7), "Christmas"),
+            (date(2021, 1, 8),  "Eighth Day after New Year"),
+            (date(2021, 2, 22), "Day Before Defendence of the Fatherland"),
+            (date(2021, 2, 23), "Defendence of the Fatherland"),
+            (date(2021, 3, 8), "International Women's Day"),
+            (date(2021, 5, 1), "The Day of Spring and Labour"),
+            (date(2021, 5, 3), "The Day of Spring and Labour shift"),
+            (date(2021, 5, 9), "Victory Day"),
+            (date(2021, 5, 10), "Victory Day shift"),
+            (date(2021, 6, 12), "National Day"),
+            (date(2021, 6, 14), "National Day shift"),
+            (date(2021, 11, 4), "Day of Unity"),
+            (date(2021, 11, 5), "Day After Day of Unity"),
+            (date(2021, 12, 31), "New Year's Eve")
+        ]
+        self.assertEqual(holidays, holidays_2021)
+
+    def test_year_2021_extra_working_day(self):
+        self.assertTrue(self.cal.is_working_day(date(2021, 2, 20)))
+        self.assertTrue(self.cal.is_working_day(datetime(2021, 2, 20)))
+
+        self.assertTrue(self.cal.is_working_day(date(2021, 2, 19)))
+        self.assertTrue(self.cal.is_working_day(datetime(2020, 2, 19)))
+
 
 class UkraineTest(GenericCalendarTest):
     cal_class = Ukraine