Skip to content

Commit

Permalink
Update Portugal holidays: add holiday categories (#1529)
Browse files Browse the repository at this point in the history
  • Loading branch information
KJhellico committed Oct 26, 2023
1 parent 8595eba commit 1ba2709
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 52 deletions.
4 changes: 2 additions & 2 deletions README.rst
Expand Up @@ -669,9 +669,9 @@ The list of supported countries, their subdivisions, supported languages and cat
-
* - Portugal
- PT
- Districts: 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 30, Ext; Use subdiv='Ext' to include holidays most people have off
- Districts: 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 30
- en_US, **pt_PT**
-
- OPTIONAL, **PUBLIC**
* - Puerto Rico
- PR
- Can also be loaded as country US, subdivision PR
Expand Down
95 changes: 48 additions & 47 deletions holidays/countries/portugal.py
Expand Up @@ -12,6 +12,7 @@
from datetime import timedelta as td
from gettext import gettext as tr

from holidays.constants import OPTIONAL, PUBLIC
from holidays.groups import ChristianHolidays, InternationalHolidays
from holidays.holiday_base import HolidayBase

Expand Down Expand Up @@ -46,9 +47,9 @@ class Portugal(HolidayBase, ChristianHolidays, InternationalHolidays):

country = "PT"
default_language = "pt_PT"
supported_categories = {OPTIONAL, PUBLIC}

# https://en.wikipedia.org/wiki/ISO_3166-2:PT
# `Ext` represents the national holidays most people have off
subdivisions = (
"01",
"02",
Expand All @@ -70,18 +71,16 @@ class Portugal(HolidayBase, ChristianHolidays, InternationalHolidays):
"18",
"20",
"30",
"Ext",
)
_deprecated_subdivisions = ("Ext",)
supported_languages = ("en_US", "pt_PT")

def __init__(self, *args, **kwargs) -> None:
ChristianHolidays.__init__(self)
InternationalHolidays.__init__(self)
super().__init__(*args, **kwargs)

def _populate(self, year):
super()._populate(year)

def _populate_public_holidays(self):
self._add_new_years_day(tr("Ano Novo"))

# Carnival is no longer a holiday, but some companies let workers off.
Expand All @@ -94,21 +93,22 @@ def _populate(self, year):
self._add_easter_sunday(tr("Páscoa"))

# Revoked holidays in 2013–2015.
if year <= 2012 or year >= 2016:
if self._year <= 2012 or self._year >= 2016:
self._add_corpus_christi_day(tr("Corpo de Deus"))
if year >= 1910:
if self._year >= 1910:
self._add_holiday_oct_5(tr("Implantação da República"))
self._add_all_saints_day(tr("Dia de Todos os Santos"))
if year >= 1823:
if self._year >= 1823:
self._add_holiday_dec_1(tr("Restauração da Independência"))

if year >= 1974:
if self._year >= 1974:
self._add_holiday_apr_25(tr("Dia da Liberdade"))
self._add_labor_day(tr("Dia do Trabalhador"))
if year >= 1911:
if 1933 <= year <= 1973:

if self._year >= 1911:
if 1933 <= self._year <= 1973:
self._add_holiday_jun_10(tr("Dia de Camões, de Portugal e da Raça"))
elif year >= 1978:
elif self._year >= 1978:
self._add_holiday_jun_10(
tr("Dia de Portugal, de Camões e das Comunidades Portuguesas")
)
Expand All @@ -119,11 +119,7 @@ def _populate(self, year):
self._add_immaculate_conception_day(tr("Imaculada Conceição"))
self._add_christmas_day(tr("Dia de Natal"))

def _add_subdiv_holidays(self):
if self._year >= 1911:
super()._add_subdiv_holidays()

def _add_subdiv_ext_holidays(self):
def _populate_optional_holidays(self):
"""
Adds extended days that most people have as a bonus from their
companies:
Expand All @@ -139,83 +135,88 @@ def _add_subdiv_ext_holidays(self):
# - get Holidays that occur on Thursday and add Friday (+1 day)

self._add_carnival_monday(tr("Carnaval"))
self._add_holiday_jun_13(tr("Dia de Santo António"))
self._add_christmas_eve(tr("Véspera de Natal"))
self._add_christmas_day_two(tr("26 de Dezembro"))
self._add_new_years_eve(tr("Véspera de Ano Novo"))
self._add_holiday_jun_13(tr("Dia de Santo António"))

def _add_subdiv_01_holidays(self):
def _add_subdiv_holidays(self):
if self._year >= 1911:
super()._add_subdiv_holidays()

if self.subdiv == "Ext":
self._populate_optional_holidays()

def _add_subdiv_01_public_holidays(self):
self._add_holiday_may_12(tr("Dia de Santa Joana"))

def _add_subdiv_02_holidays(self):
def _add_subdiv_02_public_holidays(self):
self._add_ascension_thursday(tr("Quinta-feira da Ascensão"))

def _add_subdiv_03_holidays(self):
self._add_holiday_jun_24(tr("Dia de São João"))
def _add_subdiv_03_public_holidays(self):
self._add_saint_johns_day(tr("Dia de São João"))

def _add_subdiv_04_holidays(self):
def _add_subdiv_04_public_holidays(self):
self._add_holiday_aug_22(tr("Dia de Nossa Senhora das Graças"))

def _add_subdiv_05_holidays(self):
def _add_subdiv_05_public_holidays(self):
self._add_holiday(
tr("Dia de Nossa Senhora de Mércoles"), self._easter_sunday + td(days=+16)
)

def _add_subdiv_06_holidays(self):
def _add_subdiv_06_public_holidays(self):
self._add_holiday_jul_4(tr("Dia de Santa Isabel"))

def _add_subdiv_07_holidays(self):
def _add_subdiv_07_public_holidays(self):
self._add_holiday_jun_29(tr("Dia de São Pedro"))

def _add_subdiv_08_holidays(self):
def _add_subdiv_08_public_holidays(self):
self._add_holiday_sep_7(tr("Dia do Município de Faro"))

def _add_subdiv_09_holidays(self):
def _add_subdiv_09_public_holidays(self):
self._add_holiday_nov_27(tr("Dia do Município da Guarda"))

def _add_subdiv_10_holidays(self):
def _add_subdiv_10_public_holidays(self):
self._add_holiday_may_22(tr("Dia do Município de Leiria"))

def _add_subdiv_11_holidays(self):
def _add_subdiv_11_public_holidays(self):
self._add_holiday_jun_13(tr("Dia de Santo António"))

def _add_subdiv_12_holidays(self):
def _add_subdiv_12_public_holidays(self):
self._add_holiday_may_23(tr("Dia do Município de Portalegre"))

def _add_subdiv_13_holidays(self):
self._add_holiday_jun_24(tr("Dia de São João"))
def _add_subdiv_13_public_holidays(self):
self._add_saint_johns_day(tr("Dia de São João"))

def _add_subdiv_14_holidays(self):
def _add_subdiv_14_public_holidays(self):
self._add_saint_josephs_day(tr("Dia de São José"))

def _add_subdiv_15_holidays(self):
def _add_subdiv_15_public_holidays(self):
self._add_holiday_sep_15(tr("Dia de Bocage"))

def _add_subdiv_16_holidays(self):
def _add_subdiv_16_public_holidays(self):
self._add_holiday_aug_20(tr("Dia de Nossa Senhora da Agonia"))

def _add_subdiv_17_holidays(self):
def _add_subdiv_17_public_holidays(self):
self._add_holiday_jun_13(tr("Dia de Santo António"))

def _add_subdiv_18_holidays(self):
def _add_subdiv_18_public_holidays(self):
self._add_holiday_sep_21(tr("Dia de São Mateus"))

def _add_subdiv_20_holidays(self):
def _add_subdiv_20_public_holidays(self):
if self._year >= 1981:
self._add_holiday(
tr("Dia da Região Autónoma dos Açores"), self._easter_sunday + td(days=+50)
)
self._add_whit_monday(tr("Dia da Região Autónoma dos Açores"))

def _add_subdiv_30_holidays(self):
if 1979 <= self._year <= 1988:
self._add_holiday_jul_1(tr("Dia da Região Autónoma da Madeira"))
elif self._year >= 1989:
def _add_subdiv_30_public_holidays(self):
if self._year >= 1979:
self._add_holiday_jul_1(
tr("Dia da Região Autónoma da Madeira e das Comunidades Madeirenses")
if self._year >= 1989
else tr("Dia da Região Autónoma da Madeira")
)

if self._year >= 2002:
self._add_holiday_dec_26(tr("Primeira Oitava"))
self._add_christmas_day_two(tr("Primeira Oitava"))


class PT(Portugal):
Expand Down
38 changes: 35 additions & 3 deletions tests/countries/test_portugal.py
Expand Up @@ -9,6 +9,9 @@
# Website: https://github.com/dr-prodigy/python-holidays
# License: MIT (see LICENSE file)

import warnings

from holidays.constants import OPTIONAL, PUBLIC
from holidays.countries.portugal import Portugal, PT, PRT
from tests.common import TestCase

Expand All @@ -18,9 +21,16 @@ class TestPortugal(TestCase):
def setUpClass(cls):
super().setUpClass(Portugal, years=range(1910, 2050))

def setUp(self):
super().setUp()
warnings.simplefilter("ignore", category=DeprecationWarning)

def test_country_aliases(self):
self.assertCountryAliases(Portugal, PT, PRT)

def test_subdiv_deprecation(self):
self.assertDeprecatedSubdivisions("This subdivision is deprecated and will be removed")

def test_2014(self):
# http://www.officeholidays.com/countries/portugal/2014.php
self.assertHolidays(
Expand Down Expand Up @@ -138,21 +148,33 @@ def test_primeira_oitava(self):
(f"{year}-12-26" for year in range(2016, 2024)),
)

def test_ext(self):
# Christmas's Eve, S. Stephen & New Year's Eve
def test_optional_holidays(self):
holidays = Portugal(categories=(OPTIONAL,), years=range(2017, 2020))
self.assertHoliday(
Portugal(years=range(2017, 2020), subdiv="Ext"),
holidays,
"2017-02-27",
"2017-06-13",
"2017-12-24",
"2017-12-26",
"2017-12-31",
"2018-02-12",
"2018-06-13",
"2018-12-24",
"2018-12-26",
"2018-12-31",
"2019-03-04",
"2019-06-13",
"2019-12-24",
"2019-12-26",
"2019-12-31",
)

def test_deprecated(self):
self.assertEqual(
Portugal(subdiv="Ext", years=2022).keys(),
Portugal(categories=(OPTIONAL, PUBLIC), years=2022).keys(),
)

def test_corpus_christi(self):
name = "Corpo de Deus"
self.assertNoHolidayName(name, range(2013, 2016))
Expand Down Expand Up @@ -220,34 +242,44 @@ def test_portugal_day(self):
def test_l10n_default(self):
self.assertLocalizedHolidays(
("2018-01-01", "Ano Novo"),
("2018-02-12", "Carnaval"),
("2018-03-30", "Sexta-feira Santa"),
("2018-04-01", "Páscoa"),
("2018-04-25", "Dia da Liberdade"),
("2018-05-01", "Dia do Trabalhador"),
("2018-05-31", "Corpo de Deus"),
("2018-06-10", "Dia de Portugal, de Camões e das Comunidades Portuguesas"),
("2018-06-13", "Dia de Santo António"),
("2018-08-15", "Assunção de Nossa Senhora"),
("2018-10-05", "Implantação da República"),
("2018-11-01", "Dia de Todos os Santos"),
("2018-12-01", "Restauração da Independência"),
("2018-12-08", "Imaculada Conceição"),
("2018-12-24", "Véspera de Natal"),
("2018-12-25", "Dia de Natal"),
("2018-12-26", "26 de Dezembro"),
("2018-12-31", "Véspera de Ano Novo"),
)

def test_l10n_en_us(self):
self.assertLocalizedHolidays(
"en_US",
("2018-01-01", "New Year's Day"),
("2018-02-12", "Carnival"),
("2018-03-30", "Good Friday"),
("2018-04-01", "Easter Sunday"),
("2018-04-25", "Freedom Day"),
("2018-05-01", "Labour Day"),
("2018-05-31", "Corpus Christi"),
("2018-06-10", "Day of Portugal, Camões, and the Portuguese Communities"),
("2018-06-13", "St. Anthony's Day"),
("2018-08-15", "Assumption Day"),
("2018-10-05", "Republic Day"),
("2018-11-01", "All Saints Day"),
("2018-12-01", "Restoration of Independence Day"),
("2018-12-08", "Immaculate Conception"),
("2018-12-24", "Christmas Eve"),
("2018-12-25", "Christmas"),
("2018-12-26", "Boxing Day"),
("2018-12-31", "New Year's Eve"),
)

0 comments on commit 1ba2709

Please sign in to comment.