Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ Czech CZ None
Denmark DK None
England None
EuropeanCentralBank ECB,TAR Trans-European Automated Real-time Gross Settlement (TARGET2)
France FRA **Métropole** (default), Alsace-Moselle, Guadeloupe, Guyane,
Martinique, Mayotte, Nouvelle-Calédonie, La Réunion,
Polynésie Française, Saint-Barthélémy, Saint-Martin,
Wallis-et-Futuna
Germany DE BW, BY, BE, BB, HB, HH, HE, MV, NI, NW, RP, SL, SN, ST,
SH, TH
Ireland None
Expand Down
107 changes: 107 additions & 0 deletions holidays.py
Original file line number Diff line number Diff line change
Expand Up @@ -2224,3 +2224,110 @@ def _populate(self, year):

class NO(Norway):
pass


class France(HolidayBase):
"""Official French holidays.

Some provinces have specific holidays, only those are included in the
PROVINCES, because these provinces have different administrative status,
which makes it difficult to enumerate.

For religious holidays usually happening on Sundays (Easter, Pentecost),
only the following Monday is considered a holiday.

Primary sources:
https://fr.wikipedia.org/wiki/Fêtes_et_jours_fériés_en_France
https://www.service-public.fr/particuliers/vosdroits/F2405
"""

PROVINCES = ['Métropole', 'Alsace-Moselle', 'Guadeloupe', 'Guyane',
'Martinique', 'Mayotte', 'Nouvelle-Calédonie', 'La Réunion',
'Polynésie Française', 'Saint-Barthélémy', 'Saint-Martin',
'Wallis-et-Futuna']

def __init__(self, **kwargs):
self.country = 'FR'
self.prov = kwargs.pop('prov', 'Métropole')
HolidayBase.__init__(self, **kwargs)

def _populate(self, year):
# Civil holidays
if year > 1810:
self[date(year, 1, 1)] = "Jour de l'an"

if year > 1919:
name = 'Fête du Travail'
if year <= 1948:
name += ' et de la Concorde sociale'
self[date(year, 5, 1)] = name

if (year >= 1953 and year <= 1959) or year > 1981:
self[date(year, 5, 8)] = 'Armistice 1945'

if year >= 1880:
self[date(year, 7, 14)] = 'Fête nationale'

if year >= 1918:
self[date(year, 11, 11)] = 'Armistice 1918'

# Religious holidays
if self.prov in ['Alsace-Moselle', 'Guadeloupe', 'Guyane',
'Martinique', 'Polynésie Française']:
self[easter(year) - rd(days=2)] = 'Vendredi saint'

if self.prov == 'Alsace-Moselle':
self[date(year, 12, 26)] = 'Deuxième jour de Noël'

if year >= 1886:
self[easter(year) + rd(days=1)] = 'Lundi de Pâques'
self[easter(year) + rd(days=50)] = 'Lundi de Pentecôte'

if year >= 1802:
self[easter(year) + rd(days=39)] = 'Ascension'
self[date(year, 8, 15)] = 'Assomption'
self[date(year, 11, 1)] = 'Toussaint'

name = 'Noël'
if self.prov == 'Alsace-Moselle':
name = 'Premier jour de ' + name
self[date(year, 12, 25)] = name

# Non-metropolitan holidays (starting dates missing)
if self.prov == 'Mayotte':
self[date(year, 4, 27)] = "Abolition de l'esclavage"

if self.prov == 'Wallis-et-Futuna':
self[date(year, 4, 28)] = 'Saint Pierre Chanel'

if self.prov == 'Martinique':
self[date(year, 5, 22)] = "Abolition de l'esclavage"

if self.prov in ['Guadeloupe', 'Saint-Martin']:
self[date(year, 5, 27)] = "Abolition de l'esclavage"

if self.prov == 'Guyane':
self[date(year, 6, 10)] = "Abolition de l'esclavage"

if self.prov == 'Polynésie Française':
self[date(year, 6, 29)] = "Fête de l'autonomie"

if self.prov in ['Guadeloupe', 'Martinique']:
self[date(year, 7, 21)] = 'Fête Victor Schoelcher'

if self.prov == 'Wallis-et-Futuna':
self[date(year, 7, 29)] = 'Fête du Territoire'

if self.prov == 'Nouvelle-Calédonie':
self[date(year, 9, 24)] = 'Fête de la Citoyenneté'

if self.prov == 'Saint-Barthélémy':
self[date(year, 10, 9)] = "Abolition de l'esclavage"

if self.prov == 'La Réunion' and year >= 1981:
self[date(year, 12, 20)] = "Abolition de l'esclavage"


# FR already exists (Friday), we don't want to mess it up
class FRA(France):
pass
26 changes: 26 additions & 0 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3000,5 +3000,31 @@ def test_not_holiday(self):
self.assertFalse('2016-12-28' in self.holidays_with_sundays)


class TestFR(unittest.TestCase):

def setUp(self):
self.holidays = holidays.France()
self.prov_holidays = dict((prov, holidays.France(prov=prov))
for prov in holidays.France.PROVINCES)

def test_2017(self):
self.assertTrue(date(2017, 1, 1) in self.holidays)
self.assertTrue(date(2017, 4, 17) in self.holidays)
self.assertTrue(date(2017, 5, 1) in self.holidays)
self.assertTrue(date(2017, 5, 8) in self.holidays)
self.assertTrue(date(2017, 5, 25) in self.holidays)
self.assertTrue(date(2017, 6, 5) in self.holidays)
self.assertTrue(date(2017, 7, 14) in self.holidays)
self.assertTrue(date(2017, 8, 15) in self.holidays)
self.assertTrue(date(2017, 11, 1) in self.holidays)
self.assertTrue(date(2017, 11, 11) in self.holidays)
self.assertTrue(date(2017, 12, 25) in self.holidays)

def test_alsace_moselle(self):
am_holidays = self.prov_holidays['Alsace-Moselle']
self.assertTrue(date(2017, 4, 14) in am_holidays)
self.assertTrue(date(2017, 12, 26) in am_holidays)


if __name__ == "__main__":
unittest.main()