Merge pull request #508 from peopledoc/carnaval-into-core

Moving Fat Tuesday calculation into the `workalendar.core` module
This commit is contained in:
Bruno Bord 2020-06-08 09:29:56 +02:00 committed by GitHub
commit faa4764de3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 87 additions and 63 deletions

View File

@ -3,6 +3,7 @@
## master (unreleased)
- Small fixes (docstrings, use of extends, etc) on Cayman Islands calendar (#507).
- Moving Carnaval / Mardi Gras / Fat Tuesday calculation into the `workalendar.core` module, because it's used in at least 3 countries and some States / Counties in the USA.
## v10.0.0 (2020-06-05)

View File

@ -1,12 +1,13 @@
from datetime import timedelta
from ..core import WesternCalendar, ChristianMixin
from ..registry_tools import iso_register
@iso_register('AO')
class Angola(WesternCalendar, ChristianMixin):
"""Angola"""
"Angola"
include_fat_tuesday = True
fat_tuesday_label = "Dia de Carnaval"
include_good_friday = True
include_easter_sunday = True
include_christmas = True
@ -20,12 +21,3 @@ class Angola(WesternCalendar, ChristianMixin):
(9, 17, "Dia do Fundador da Nação e do Herói Nacional"),
(11, 11, "Dia da Independência Nacional"),
)
def get_variable_entrudo(self, year):
easter_sunday = self.get_easter_sunday(year)
return easter_sunday - timedelta(days=47)
def get_variable_days(self, year):
days = super().get_variable_days(year)
days.append((self.get_variable_entrudo(year), "Dia de Carnaval"))
return days

View File

@ -10,6 +10,8 @@ from ..registry_tools import iso_register
class Argentina(WesternCalendar, ChristianMixin):
'Argentina'
include_fat_tuesday = True
fat_tuesday_label = "Carnival"
include_good_friday = True
include_easter_saturday = True
include_easter_sunday = True
@ -130,10 +132,6 @@ class Argentina(WesternCalendar, ChristianMixin):
(self.get_easter_sunday(year) - timedelta(days=48),
"Carnival Lunes"))
days.append(
(self.get_easter_sunday(year) - timedelta(days=47),
"Carnival"))
days.append(
self.get_malvinas_day(year))

View File

@ -33,14 +33,6 @@ class Brazil(WesternCalendar, ChristianMixin):
include_nossa_senhora_conceicao = False
include_easter_sunday = True
def get_carnaval(self, year):
"""
Return the third day of Carnaval (Tuesday)
This day is shared holidays by several Brazil states.
"""
return self.get_easter_sunday(year) - timedelta(days=47)
def get_variable_days(self, year):
days = super().get_variable_days(year)
if self.include_sao_jose:
@ -231,6 +223,8 @@ class BrazilRioDeJaneiro(Brazil):
(4, 23, "Dia de São Jorge"),
(3, 1, "Aniversário da Cidade do Rio de Janeiro"),
)
include_fat_tuesday = True
fat_tuesday_label = "Carnaval"
include_servidor_publico = True
servidor_publico_label = "Dia do Funcionário Público"
include_consciencia_negra = True
@ -247,7 +241,6 @@ class BrazilRioDeJaneiro(Brazil):
def get_variable_days(self, year):
days = super().get_variable_days(year)
days.append((self.get_carnaval(year), "Carnaval"))
days.append((self.get_dia_do_comercio(year), "Dia do Comércio"))
return days
@ -309,6 +302,8 @@ class BrazilSaoPauloCity(BrazilSaoPauloState):
FIXED_HOLIDAYS = BrazilSaoPauloState.FIXED_HOLIDAYS + (
(1, 25, "Anniversary of the city of São Paulo"),
)
include_fat_tuesday = True
fat_tuesday_label = "Carnaval"
include_easter_sunday = True
include_corpus_christi = True
include_good_friday = True
@ -316,11 +311,6 @@ class BrazilSaoPauloCity(BrazilSaoPauloState):
include_consciencia_negra = True
consciencia_negra_label = "Dia da Consciência Negra"
def get_variable_days(self, year):
days = super().get_variable_days(year)
days.append((self.get_carnaval(year), "Carnaval"))
return days
@iso_register('BR-SE')
class BrazilSergipe(Brazil):
@ -388,6 +378,8 @@ class BrazilSerraCity(BrazilEspiritoSanto):
FIXED_HOLIDAYS = BrazilEspiritoSanto.FIXED_HOLIDAYS + (
(12, 26, "Dia do Serrano"),
)
include_fat_tuesday = True
fat_tuesday_label = "Carnaval"
include_ash_wednesday = True
ash_wednesday_label = "Quarta-feira de cinzas"
include_good_friday = True
@ -397,9 +389,8 @@ class BrazilSerraCity(BrazilEspiritoSanto):
def get_variable_days(self, year):
days = super().get_variable_days(year)
carnaval_tuesday = self.get_carnaval(year)
carnaval_tuesday = self.get_fat_tuesday(year)
days.append((carnaval_tuesday - timedelta(days=1), "Carnaval Monday"))
days.append((carnaval_tuesday, "Carnaval"))
return days
@ -583,6 +574,8 @@ class BrazilBankCalendar(Brazil):
Calendar that considers only working days for bank transactions
for companies and the general public
"""
include_fat_tuesday = True
fat_tuesday_label = "Tuesday carnaval"
include_good_friday = True
include_ash_wednesday = True
include_corpus_christi = True
@ -610,22 +603,17 @@ class BrazilBankCalendar(Brazil):
day for only internal bank transactions
"""
days = super().get_variable_days(year)
tuesday_carnaval = self.get_carnaval(year)
tuesday_carnaval = self.get_fat_tuesday(year)
monday_carnaval = tuesday_carnaval - timedelta(days=1)
carnaval_days = [
(monday_carnaval, "Monday carnaval"),
(tuesday_carnaval, "Tuesday carnaval"),
]
days.append((monday_carnaval, "Monday carnaval"))
non_working_days = [
(
self.get_last_day_of_year_for_only_internal_bank_trans(year),
"Last day of year for only internal bank transactions"
)
]
days.append((
self.get_last_day_of_year_for_only_internal_bank_trans(year),
"Last day of year for only internal bank transactions"
))
return days + carnaval_days + non_working_days
return days
def find_following_working_day(self, day):
"""

View File

@ -10,7 +10,7 @@ from calverter import Calverter
from dateutil import easter
from lunardate import LunarDate
from .exceptions import UnsupportedDateType
from .exceptions import UnsupportedDateType, CalendarError
MON, TUE, WED, THU, FRI, SAT, SUN = range(7)
@ -373,6 +373,10 @@ class ChristianMixin(Calendar):
include_epiphany = False
include_clean_monday = False
include_annunciation = False
include_fat_tuesday = False
# Fat tuesday forced to `None` to make sure this value is always set
# We've seen that there was a wide variety of labels.
fat_tuesday_label = None
include_ash_wednesday = False
ash_wednesday_label = "Ash Wednesday"
include_palm_sunday = False
@ -398,6 +402,14 @@ class ChristianMixin(Calendar):
boxing_day_label = "Boxing Day"
include_all_souls = False
def get_fat_tuesday(self, year):
if not self.fat_tuesday_label:
raise CalendarError(
"Improperly configured: please provide a "
"`fat_tuesday_label` value")
sunday = self.get_easter_sunday(year)
return sunday - timedelta(days=47)
def get_ash_wednesday(self, year):
sunday = self.get_easter_sunday(year)
return sunday - timedelta(days=46)
@ -476,6 +488,10 @@ class ChristianMixin(Calendar):
days.append((self.get_clean_monday(year), "Clean Monday"))
if self.include_annunciation:
days.append((date(year, 3, 25), "Annunciation"))
if self.include_fat_tuesday:
days.append(
(self.get_fat_tuesday(year), self.fat_tuesday_label)
)
if self.include_ash_wednesday:
days.append(
(self.get_ash_wednesday(year), self.ash_wednesday_label)

View File

@ -549,6 +549,12 @@ class AngolaTest(GenericCalendarTest):
# Dia do Natal 25 de Dezembro
self.assertIn(date(2018, 12, 25), holidays) # Natal
def test_carnaval_label(self):
holidays = self.cal.holidays(2018)
holidays_dict = dict(holidays)
label_carnaval = holidays_dict[date(2018, 2, 13)]
self.assertEqual(label_carnaval, "Dia de Carnaval")
class KenyaTest(GenericCalendarTest):
cal_class = Kenya

View File

@ -118,6 +118,12 @@ class ArgentinaTest(GenericCalendarTest):
"Día Nacional de la Memoria por la Verdad y la Justicia"
)
def test_carnival_label(self):
holidays = self.cal.holidays(2020)
holidays = dict(holidays)
label_carnival = holidays[date(2020, 2, 25)]
self.assertEqual(label_carnival, "Carnival")
class ChileTest(GenericCalendarTest):
cal_class = Chile

View File

@ -246,6 +246,12 @@ class BrazilRioDeJaneiroTest(BrazilTest):
# Dia de Nossa Senhora da Conceição
self.assertIn(date(2017, 12, 8), holidays)
def test_carnaval_label(self):
holidays = self.cal.holidays(2017)
holidays_dict = dict(holidays)
label_carnaval = holidays_dict[date(2017, 2, 28)]
self.assertEqual(label_carnaval, "Carnaval")
class BrazilRioGrandeDoNorteTest(BrazilTest):
cal_class = BrazilRioGrandeDoNorte
@ -338,6 +344,12 @@ class SaoPauloCityTest(SaoPauloStateTest):
"Sexta-feira da Paixão",
)
def test_carnaval_label(self):
holidays = self.cal.holidays(2013)
holidays_dict = dict(holidays)
label_carnaval = holidays_dict[date(2013, 2, 12)]
self.assertEqual(label_carnaval, "Carnaval")
class BrazilSergipeTest(BrazilTest):
cal_class = BrazilSergipe
@ -481,6 +493,12 @@ class BrazilSerraCityTest(BrazilEspiritoSantoTest):
"Paixão do Cristo",
)
def test_carnaval_label(self):
holidays = self.cal.holidays(2017)
holidays_dict = dict(holidays)
label_carnaval = holidays_dict[date(2017, 2, 28)]
self.assertEqual(label_carnaval, "Carnaval")
class BrazilRioBrancoCityTest(BrazilAcreTest):
"""
@ -899,6 +917,12 @@ class BrazilBankCalendarTest(BrazilTest):
working_day = self.cal.find_following_working_day(already_working_day)
self.assertEquals(working_day, date(2017, 7, 25))
def test_carnaval_label(self):
holidays = self.cal.holidays(2017)
holidays_dict = dict(holidays)
label_carnaval = holidays_dict[date(2017, 2, 28)]
self.assertEqual(label_carnaval, "Tuesday carnaval")
class TestIBGERegister(TestCase):

View File

@ -207,7 +207,7 @@ class UnitedStatesTest(GenericCalendarTest):
def test_mardi_gras(self):
year = 2017
day, _ = self.cal.get_mardi_gras(year)
day = self.cal.get_fat_tuesday(year)
holidays = self.cal.holidays_set(year)
self.assertNotIn(day, holidays)
@ -316,9 +316,11 @@ class IncludeMardiGras:
"""
def test_mardi_gras(self):
year = 2017
day, _ = self.cal.get_mardi_gras(year)
holidays = self.cal.holidays_set(year)
self.assertIn(day, holidays)
day = self.cal.get_fat_tuesday(year)
holidays = self.cal.holidays(year)
holidays_dict = dict(holidays)
self.assertIn(day, holidays_dict)
self.assertEqual(holidays_dict[day], "Mardi Gras")
class AlabamaTest(UnitedStatesTest):

View File

@ -16,12 +16,12 @@ class Alabama(UnitedStates):
class AlabamaBaldwinCounty(Alabama):
"Baldwin County, Alabama"
include_mardi_gras = True
include_fat_tuesday = True
class AlabamaMobileCounty(Alabama):
"Mobile County, Alabama"
include_mardi_gras = True
include_fat_tuesday = True
class AlabamaPerryCounty(Alabama):

View File

@ -59,7 +59,8 @@ class UnitedStates(WesternCalendar, ChristianMixin):
national_memorial_day_label = "Memorial Day"
# Some regional variants
include_mardi_gras = False
include_fat_tuesday = False
fat_tuesday_label = "Mardi Gras"
# Shift day mechanism
# These days won't be shifted to next MON or previous FRI
@ -272,13 +273,6 @@ class UnitedStates(WesternCalendar, ChristianMixin):
self.national_memorial_day_label
)
def get_mardi_gras(self, year):
"""
Mardi Gras is the Tuesday happening 47 days before Easter
"""
sunday = self.get_easter_sunday(year)
return (sunday - timedelta(days=47), "Mardi Gras")
def get_variable_days(self, year):
# usual variable days
days = super().get_variable_days(year)
@ -295,9 +289,6 @@ class UnitedStates(WesternCalendar, ChristianMixin):
"Thanksgiving Day"),
])
if self.include_mardi_gras:
days.append(self.get_mardi_gras(year))
if self.include_federal_presidents_day:
days.append(self.get_presidents_day(year))

View File

@ -78,7 +78,7 @@ class FloridaLegal(Florida):
(4, 2, 'Pascua Florida Day'),
(6, 14, 'Flag Day'),
)
include_mardi_gras = True
include_fat_tuesday = True
include_lincoln_birthday = True
include_federal_presidents_day = True
include_good_friday = True

View File

@ -8,4 +8,4 @@ class Louisiana(UnitedStates):
include_good_friday = True
include_election_day_even = True
include_columbus_day = False
include_mardi_gras = True
include_fat_tuesday = True