Skip to content

Add Holiday Provider for Peru 🇵🇪 #400

@giovanny07

Description

@giovanny07

Summary

Peru is missing from Yasumi's list of supported countries. This issue proposes adding a full Peru holiday provider covering all 15 official public holidays established by Peruvian law, along with translations and unit tests.

Country details

Field Value
ISO 3166-1 alpha-2 PE
Timezone America/Lima
Default locale es_PE
Total public holidays 15
Legal source Ley 26331 and amendments; Supreme Decree 009-2011-MINCETUR

No movable-Monday rule exists in Peru. All holidays fall on their calendar date.

Proposed implementation

src/Yasumi/Provider/Peru.php

<?php

declare(strict_types = 1);

namespace Yasumi\Provider;

use Yasumi\Exception\UnknownLocaleException;
use Yasumi\Holiday;

/**

  • Provider for all holidays in Peru.

  • Peru observes 15 public holidays established by Law 26331 and its amendments.

  • @see https://en.wikipedia.org/wiki/Public_holidays_in_Peru
    */
    class Peru extends AbstractProvider
    {
    use CommonHolidays;
    use ChristianHolidays;

    public const INDEPENDENCE_YEAR = 1821;
    public const ID = 'PE';

    /**

    • @throws \InvalidArgumentException

    • @throws UnknownLocaleException

    • @throws \Exception
      */
      public function initialize(): void
      {
      $this->timezone = 'America/Lima';

      $this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale));
      $this->addHoliday($this->internationalWorkersDay($this->year, $this->timezone, $this->locale));
      $this->addHoliday($this->christmasDay($this->year, $this->timezone, $this->locale));
      $this->addHoliday($this->maundyThursday($this->year, $this->timezone, $this->locale));
      $this->addHoliday($this->goodFriday($this->year, $this->timezone, $this->locale));

      $this->addIndependenceDay();
      $this->addDayOfArmedForces();
      $this->addBattleOfAngamosDay();
      $this->addFeastOfSaintRoseOfLima();
      $this->addAllSaintsDay();
      $this->addImmaculateConceptionDay();
      $this->addNationalDayOfPeruvianCuisine();
      }

    public function getSources(): array
    {
    return [
    'https://en.wikipedia.org/wiki/Public_holidays_in_Peru',
    'https://www.gob.pe/feriados',
    ];
    }

    /**

    • Independence Day — July 28 (since 1821).
    • @see https://en.wikipedia.org/wiki/Peruvian_War_of_Independence
      */
      protected function addIndependenceDay(): void
      {
      if ($this->year >= self::INDEPENDENCE_YEAR) {
      $this->addHoliday(new Holiday('independenceDay',
      ['en' => 'Independence Day', 'es' => 'Día de la Independencia'],
      new \DateTime("{$this->year}-07-28", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
      $this->locale));
      }
      }

    /**

    • Day of the Armed Forces — July 29 (since 1821).
    • Second national holiday, commemorating independence and the armed forces.
      */
      protected function addDayOfArmedForces(): void
      {
      if ($this->year >= self::INDEPENDENCE_YEAR) {
      $this->addHoliday(new Holiday('grandMilitaryParadeDay',
      ['en' => 'Day of the Armed Forces', 'es' => 'Día de las Fuerzas Armadas'],
      new \DateTime("{$this->year}-07-29", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
      $this->locale));
      }
      }

    /**

    • Battle of Angamos Day — October 8 (since 1879).
    • Commemorates the 1879 naval battle during the War of the Pacific.
    • @see https://en.wikipedia.org/wiki/Battle_of_Angamos
      */
      protected function addBattleOfAngamosDay(): void
      {
      if ($this->year >= 1879) {
      $this->addHoliday(new Holiday('battleOfAngamosDay',
      ['en' => 'Battle of Angamos Day', 'es' => 'Combate de Angamos'],
      new \DateTime("{$this->year}-10-08", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
      $this->locale));
      }
      }

    /**

    • Feast of Saint Rose of Lima — August 30.
    • Patron saint of Peru; first person born in the Americas to be canonized.
    • @see https://en.wikipedia.org/wiki/Rose_of_Lima
      */
      protected function addFeastOfSaintRoseOfLima(): void
      {
      $this->addHoliday(new Holiday('feastOfSaintRoseOfLima',
      ['en' => 'Feast of Saint Rose of Lima', 'es' => 'Santa Rosa de Lima'],
      new \DateTime("{$this->year}-08-30", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
      $this->locale));
      }

    /** All Saints' Day — November 1 (fixed). */
    protected function addAllSaintsDay(): void
    {
    $this->addHoliday(new Holiday('allSaintsDay',
    ['en' => "All Saints' Day", 'es' => 'Día de Todos los Santos'],
    new \DateTime("{$this->year}-11-01", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
    $this->locale));
    }

    /** Immaculate Conception — December 8 (fixed). */
    protected function addImmaculateConceptionDay(): void
    {
    $this->addHoliday(new Holiday('immaculateConception',
    ['en' => 'Immaculate Conception', 'es' => 'Inmaculada Concepción'],
    new \DateTime("{$this->year}-12-08", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
    $this->locale));
    }

    /**

    • National Day of Peruvian Cuisine — November 16 (since 2011).
    • Established by Supreme Decree 009-2011-MINCETUR.
      */
      protected function addNationalDayOfPeruvianCuisine(): void
      {
      if ($this->year >= 2011) {
      $this->addHoliday(new Holiday('nationalDayOfPeruvianCuisine',
      ['en' => 'National Day of Peruvian Cuisine', 'es' => 'Día de la Gastronomía Peruana'],
      new \DateTime("{$this->year}-11-16", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
      $this->locale,
      Holiday::TYPE_OTHER));
      }
      }
      }

New translation files

src/Yasumi/data/translations/feastOfSaintRoseOfLima.php

<?php declare(strict_types = 1);
return ['en' => 'Feast of Saint Rose of Lima', 'es' => 'Santa Rosa de Lima'];

src/Yasumi/data/translations/battleOfAngamosDay.php

<?php declare(strict_types = 1);
return ['en' => 'Battle of Angamos Day', 'es' => 'Combate de Angamos'];

src/Yasumi/data/translations/grandMilitaryParadeDay.php

<?php declare(strict_types = 1);
return ['en' => 'Day of the Armed Forces', 'es' => 'Día de las Fuerzas Armadas'];

tests/Peru/PeruBaseTestCase.php

<?php
declare(strict_types = 1);

namespace Yasumi\Tests\Peru;

use PHPUnit\Framework\TestCase;
use Yasumi\Tests\YasumiBase;

abstract class PeruBaseTestCase extends TestCase
{
use YasumiBase;

public const REGION         = 'Peru';
public const TIMEZONE       = 'America/Lima';
public const LOCALE         = 'es_PE';
public const TOTAL_HOLIDAYS = 15;

}

tests/Peru/PeruTest.php

<?php
declare(strict_types = 1);

namespace Yasumi\Tests\Peru;

use PHPUnit\Framework\Attributes\DataProvider;
use Yasumi\Tests\HolidayTestInterface;
use Yasumi\Yasumi;

class PeruTest extends PeruBaseTestCase implements HolidayTestInterface
{
public function testTotalHolidays(): void
{
$this->assertCount(self::TOTAL_HOLIDAYS, Yasumi::create(self::REGION, 2025));
}

public function testCountryCode(): void
{
    $this-&gt;assertEquals('PE', Yasumi::create(self::REGION, 2025)-&gt;getCountry());
}

#[DataProvider('independenceDayDataProvider')]
public function testIndependenceDay(int $year, \DateTime $expected): void
{
    $this-&gt;assertHoliday(self::REGION, 'independenceDay', $year, $expected);
}
public static function independenceDayDataProvider(): array
{
    return [
        [2023, new \DateTime('2023-07-28', new \DateTimeZone(self::TIMEZONE))],
        [2024, new \DateTime('2024-07-28', new \DateTimeZone(self::TIMEZONE))],
        [2025, new \DateTime('2025-07-28', new \DateTimeZone(self::TIMEZONE))],
    ];
}
public function testIndependenceDayBeforeEstablishment(): void
{
    $this-&gt;assertNotHoliday(self::REGION, 'independenceDay', 1820);
}

#[DataProvider('dayOfArmedForcesDataProvider')]
public function testDayOfArmedForces(int $year, \DateTime $expected): void
{
    $this-&gt;assertHoliday(self::REGION, 'grandMilitaryParadeDay', $year, $expected);
}
public static function dayOfArmedForcesDataProvider(): array
{
    return [
        [2023, new \DateTime('2023-07-29', new \DateTimeZone(self::TIMEZONE))],
        [2024, new \DateTime('2024-07-29', new \DateTimeZone(self::TIMEZONE))],
        [2025, new \DateTime('2025-07-29', new \DateTimeZone(self::TIMEZONE))],
    ];
}

#[DataProvider('feastOfSaintRoseDataProvider')]
public function testFeastOfSaintRoseOfLima(int $year, \DateTime $expected): void
{
    $this-&gt;assertHoliday(self::REGION, 'feastOfSaintRoseOfLima', $year, $expected);
}
public static function feastOfSaintRoseDataProvider(): array
{
    return [
        [2023, new \DateTime('2023-08-30', new \DateTimeZone(self::TIMEZONE))],
        [2024, new \DateTime('2024-08-30', new \DateTimeZone(self::TIMEZONE))],
        [2025, new \DateTime('2025-08-30', new \DateTimeZone(self::TIMEZONE))],
    ];
}

#[DataProvider('battleOfAngamosDataProvider')]
public function testBattleOfAngamosDay(int $year, \DateTime $expected): void
{
    $this-&gt;assertHoliday(self::REGION, 'battleOfAngamosDay', $year, $expected);
}
public static function battleOfAngamosDataProvider(): array
{
    return [
        [2023, new \DateTime('2023-10-08', new \DateTimeZone(self::TIMEZONE))],
        [2024, new \DateTime('2024-10-08', new \DateTimeZone(self::TIMEZONE))],
        [2025, new \DateTime('2025-10-08', new \DateTimeZone(self::TIMEZONE))],
    ];
}

#[DataProvider('goodFridayDataProvider')]
public function testGoodFriday(int $year, \DateTime $expected): void
{
    $this-&gt;assertHoliday(self::REGION, 'goodFriday', $year, $expected);
}
public static function goodFridayDataProvider(): array
{
    return [
        [2023, new \DateTime('2023-04-07', new \DateTimeZone(self::TIMEZONE))],
        [2024, new \DateTime('2024-03-29', new \DateTimeZone(self::TIMEZONE))],
        [2025, new \DateTime('2025-04-18', new \DateTimeZone(self::TIMEZONE))],
    ];
}

public function testNationalDayOfPeruvianCuisineNotBeforeEstablishment(): void
{
    $this-&gt;assertNotHoliday(self::REGION, 'nationalDayOfPeruvianCuisine', 2010);
}

}

References

# Add Holiday Provider for Peru 🇵🇪

Summary

Peru is missing from Yasumi's list of supported countries. This issue proposes adding a full Peru holiday provider covering all 15 official public holidays established by Peruvian law, along with translations and unit tests.

Country details

Field Value
ISO 3166-1 alpha-2 PE
Timezone America/Lima
Default locale es_PE
Total public holidays 15
Legal source Ley 26331 and amendments; Supreme Decree 009-2011-MINCETUR

Complete holiday list

Key Name (es) Name (en) Date Type Since
newYearsDay Año Nuevo New Year's Day Jan 1 Official
maundyThursday Jueves Santo Maundy Thursday Easter − 3d Official
goodFriday Viernes Santo Good Friday Easter − 2d Official
internationalWorkersDay Día del Trabajo International Workers' Day May 1 Official
feastOfSaintRoseOfLima Santa Rosa de Lima Feast of Saint Rose of Lima Aug 30 Official
independenceDay Día de la Independencia Independence Day Jul 28 Official 1821
grandMilitaryParadeDay Día de las Fuerzas Armadas Day of the Armed Forces Jul 29 Official 1821
battleOfAngamosDay Combate de Angamos Battle of Angamos Day Oct 8 Official 1879
allSaintsDay Día de Todos los Santos All Saints' Day Nov 1 Official
immaculateConception Inmaculada Concepción Immaculate Conception Dec 8 Official
christmasDay Navidad Christmas Day Dec 25 Official
nationalDayOfPeruvianCuisine Día de la Gastronomía Peruana National Day of Peruvian Cuisine Nov 16 Other 2011

No movable-Monday rule exists in Peru. All holidays fall on their calendar date.

Proposed implementation

src/Yasumi/Provider/Peru.php

<?php

declare(strict_types = 1);

namespace Yasumi\Provider;

use Yasumi\Exception\UnknownLocaleException;
use Yasumi\Holiday;

/**
 * Provider for all holidays in Peru.
 *
 * Peru observes 15 public holidays established by Law 26331 and its amendments.
 *
 * @see https://en.wikipedia.org/wiki/Public_holidays_in_Peru
 */
class Peru extends AbstractProvider
{
    use CommonHolidays;
    use ChristianHolidays;

    public const INDEPENDENCE_YEAR = 1821;
    public const ID = 'PE';

    /**
     * @throws \InvalidArgumentException
     * @throws UnknownLocaleException
     * @throws \Exception
     */
    public function initialize(): void
    {
        $this->timezone = 'America/Lima';

        $this->addHoliday($this->newYearsDay($this->year, $this->timezone, $this->locale));
        $this->addHoliday($this->internationalWorkersDay($this->year, $this->timezone, $this->locale));
        $this->addHoliday($this->christmasDay($this->year, $this->timezone, $this->locale));
        $this->addHoliday($this->maundyThursday($this->year, $this->timezone, $this->locale));
        $this->addHoliday($this->goodFriday($this->year, $this->timezone, $this->locale));

        $this->addIndependenceDay();
        $this->addDayOfArmedForces();
        $this->addBattleOfAngamosDay();
        $this->addFeastOfSaintRoseOfLima();
        $this->addAllSaintsDay();
        $this->addImmaculateConceptionDay();
        $this->addNationalDayOfPeruvianCuisine();
    }

    public function getSources(): array
    {
        return [
            'https://en.wikipedia.org/wiki/Public_holidays_in_Peru',
            'https://www.gob.pe/feriados',
        ];
    }

    /**
     * Independence Day — July 28 (since 1821).
     *
     * @see https://en.wikipedia.org/wiki/Peruvian_War_of_Independence
     */
    protected function addIndependenceDay(): void
    {
        if ($this->year >= self::INDEPENDENCE_YEAR) {
            $this->addHoliday(new Holiday('independenceDay',
                ['en' => 'Independence Day', 'es' => 'Día de la Independencia'],
                new \DateTime("{$this->year}-07-28", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
                $this->locale));
        }
    }

    /**
     * Day of the Armed Forces — July 29 (since 1821).
     *
     * Second national holiday, commemorating independence and the armed forces.
     */
    protected function addDayOfArmedForces(): void
    {
        if ($this->year >= self::INDEPENDENCE_YEAR) {
            $this->addHoliday(new Holiday('grandMilitaryParadeDay',
                ['en' => 'Day of the Armed Forces', 'es' => 'Día de las Fuerzas Armadas'],
                new \DateTime("{$this->year}-07-29", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
                $this->locale));
        }
    }

    /**
     * Battle of Angamos Day — October 8 (since 1879).
     *
     * Commemorates the 1879 naval battle during the War of the Pacific.
     *
     * @see https://en.wikipedia.org/wiki/Battle_of_Angamos
     */
    protected function addBattleOfAngamosDay(): void
    {
        if ($this->year >= 1879) {
            $this->addHoliday(new Holiday('battleOfAngamosDay',
                ['en' => 'Battle of Angamos Day', 'es' => 'Combate de Angamos'],
                new \DateTime("{$this->year}-10-08", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
                $this->locale));
        }
    }

    /**
     * Feast of Saint Rose of Lima — August 30.
     *
     * Patron saint of Peru; first person born in the Americas to be canonized.
     *
     * @see https://en.wikipedia.org/wiki/Rose_of_Lima
     */
    protected function addFeastOfSaintRoseOfLima(): void
    {
        $this->addHoliday(new Holiday('feastOfSaintRoseOfLima',
            ['en' => 'Feast of Saint Rose of Lima', 'es' => 'Santa Rosa de Lima'],
            new \DateTime("{$this->year}-08-30", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
            $this->locale));
    }

    /** All Saints' Day — November 1 (fixed). */
    protected function addAllSaintsDay(): void
    {
        $this->addHoliday(new Holiday('allSaintsDay',
            ['en' => "All Saints' Day", 'es' => 'Día de Todos los Santos'],
            new \DateTime("{$this->year}-11-01", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
            $this->locale));
    }

    /** Immaculate Conception — December 8 (fixed). */
    protected function addImmaculateConceptionDay(): void
    {
        $this->addHoliday(new Holiday('immaculateConception',
            ['en' => 'Immaculate Conception', 'es' => 'Inmaculada Concepción'],
            new \DateTime("{$this->year}-12-08", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
            $this->locale));
    }

    /**
     * National Day of Peruvian Cuisine — November 16 (since 2011).
     *
     * Established by Supreme Decree 009-2011-MINCETUR.
     */
    protected function addNationalDayOfPeruvianCuisine(): void
    {
        if ($this->year >= 2011) {
            $this->addHoliday(new Holiday('nationalDayOfPeruvianCuisine',
                ['en' => 'National Day of Peruvian Cuisine', 'es' => 'Día de la Gastronomía Peruana'],
                new \DateTime("{$this->year}-11-16", DateTimeZoneFactory::getDateTimeZone($this->timezone)),
                $this->locale,
                Holiday::TYPE_OTHER));
        }
    }
}

New translation files

src/Yasumi/data/translations/feastOfSaintRoseOfLima.php

<?php declare(strict_types = 1);
return ['en' => 'Feast of Saint Rose of Lima', 'es' => 'Santa Rosa de Lima'];

src/Yasumi/data/translations/battleOfAngamosDay.php

<?php declare(strict_types = 1);
return ['en' => 'Battle of Angamos Day', 'es' => 'Combate de Angamos'];

src/Yasumi/data/translations/grandMilitaryParadeDay.php

<?php declare(strict_types = 1);
return ['en' => 'Day of the Armed Forces', 'es' => 'Día de las Fuerzas Armadas'];

tests/Peru/PeruBaseTestCase.php

<?php
declare(strict_types = 1);

namespace Yasumi\Tests\Peru;

use PHPUnit\Framework\TestCase;
use Yasumi\Tests\YasumiBase;

abstract class PeruBaseTestCase extends TestCase
{
    use YasumiBase;

    public const REGION         = 'Peru';
    public const TIMEZONE       = 'America/Lima';
    public const LOCALE         = 'es_PE';
    public const TOTAL_HOLIDAYS = 15;
}

tests/Peru/PeruTest.php

<?php
declare(strict_types = 1);

namespace Yasumi\Tests\Peru;

use PHPUnit\Framework\Attributes\DataProvider;
use Yasumi\Tests\HolidayTestInterface;
use Yasumi\Yasumi;

class PeruTest extends PeruBaseTestCase implements HolidayTestInterface
{
    public function testTotalHolidays(): void
    {
        $this->assertCount(self::TOTAL_HOLIDAYS, Yasumi::create(self::REGION, 2025));
    }

    public function testCountryCode(): void
    {
        $this->assertEquals('PE', Yasumi::create(self::REGION, 2025)->getCountry());
    }

    #[DataProvider('independenceDayDataProvider')]
    public function testIndependenceDay(int $year, \DateTime $expected): void
    {
        $this->assertHoliday(self::REGION, 'independenceDay', $year, $expected);
    }
    public static function independenceDayDataProvider(): array
    {
        return [
            [2023, new \DateTime('2023-07-28', new \DateTimeZone(self::TIMEZONE))],
            [2024, new \DateTime('2024-07-28', new \DateTimeZone(self::TIMEZONE))],
            [2025, new \DateTime('2025-07-28', new \DateTimeZone(self::TIMEZONE))],
        ];
    }
    public function testIndependenceDayBeforeEstablishment(): void
    {
        $this->assertNotHoliday(self::REGION, 'independenceDay', 1820);
    }

    #[DataProvider('dayOfArmedForcesDataProvider')]
    public function testDayOfArmedForces(int $year, \DateTime $expected): void
    {
        $this->assertHoliday(self::REGION, 'grandMilitaryParadeDay', $year, $expected);
    }
    public static function dayOfArmedForcesDataProvider(): array
    {
        return [
            [2023, new \DateTime('2023-07-29', new \DateTimeZone(self::TIMEZONE))],
            [2024, new \DateTime('2024-07-29', new \DateTimeZone(self::TIMEZONE))],
            [2025, new \DateTime('2025-07-29', new \DateTimeZone(self::TIMEZONE))],
        ];
    }

    #[DataProvider('feastOfSaintRoseDataProvider')]
    public function testFeastOfSaintRoseOfLima(int $year, \DateTime $expected): void
    {
        $this->assertHoliday(self::REGION, 'feastOfSaintRoseOfLima', $year, $expected);
    }
    public static function feastOfSaintRoseDataProvider(): array
    {
        return [
            [2023, new \DateTime('2023-08-30', new \DateTimeZone(self::TIMEZONE))],
            [2024, new \DateTime('2024-08-30', new \DateTimeZone(self::TIMEZONE))],
            [2025, new \DateTime('2025-08-30', new \DateTimeZone(self::TIMEZONE))],
        ];
    }

    #[DataProvider('battleOfAngamosDataProvider')]
    public function testBattleOfAngamosDay(int $year, \DateTime $expected): void
    {
        $this->assertHoliday(self::REGION, 'battleOfAngamosDay', $year, $expected);
    }
    public static function battleOfAngamosDataProvider(): array
    {
        return [
            [2023, new \DateTime('2023-10-08', new \DateTimeZone(self::TIMEZONE))],
            [2024, new \DateTime('2024-10-08', new \DateTimeZone(self::TIMEZONE))],
            [2025, new \DateTime('2025-10-08', new \DateTimeZone(self::TIMEZONE))],
        ];
    }

    #[DataProvider('goodFridayDataProvider')]
    public function testGoodFriday(int $year, \DateTime $expected): void
    {
        $this->assertHoliday(self::REGION, 'goodFriday', $year, $expected);
    }
    public static function goodFridayDataProvider(): array
    {
        return [
            [2023, new \DateTime('2023-04-07', new \DateTimeZone(self::TIMEZONE))],
            [2024, new \DateTime('2024-03-29', new \DateTimeZone(self::TIMEZONE))],
            [2025, new \DateTime('2025-04-18', new \DateTimeZone(self::TIMEZONE))],
        ];
    }

    public function testNationalDayOfPeruvianCuisineNotBeforeEstablishment(): void
    {
        $this->assertNotHoliday(self::REGION, 'nationalDayOfPeruvianCuisine', 2010);
    }
}

References

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions