Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/switzerland with regions #173

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
eb53eab
Add Slovakia holidays
patressz Jan 18, 2024
bff08d2
Add Slovakia test
patressz Jan 18, 2024
8ec6965
Fix typo
patressz Jan 19, 2024
ee8e9e1
Fix typo
patressz Jan 19, 2024
56cac55
Update Slovakia.php
patressz Jan 19, 2024
9e22955
Update it_can_calculate_slovak_holidays.snap
patressz Jan 19, 2024
751da09
Add return type docblock
patressz Jan 19, 2024
5dbe890
Merge branch 'main' of https://github.com/patressz/holidays
patressz Jan 19, 2024
b586ebd
feat: add switzerland
Martin-Welte Jan 22, 2024
685ab66
test: add switzerland test
Martin-Welte Jan 22, 2024
773a758
PoC canton and multi-language support
herpaderpaldent Jan 22, 2024
0936074
Add latvian holidays
IvarsSaudinis Jan 23, 2024
5526451
Merge remote-tracking branch 'upstream/main'
patressz Jan 23, 2024
d66e375
Use `easter()` method to calculate easter date from parent class
patressz Jan 23, 2024
3c77638
Extend PoC with test
herpaderpaldent Jan 23, 2024
e96aab3
check on null instead of object
Nielsvanpach Jan 24, 2024
b600a44
add locale to api
Nielsvanpach Jan 24, 2024
1ec5d8d
remove locale setter
Nielsvanpach Jan 24, 2024
f12d09f
Merge pull request #102 from patressz/main
Nielsvanpach Jan 24, 2024
28ac292
add translations in french for Belgium
Nielsvanpach Jan 24, 2024
bf14f45
cleanup
Nielsvanpach Jan 24, 2024
cb5cfec
Fix styling
Nielsvanpach Jan 24, 2024
1a3b136
cleanup
Nielsvanpach Jan 24, 2024
59cca7b
update readme and throw exception when needed
Nielsvanpach Jan 24, 2024
52aef70
Fix styling
Nielsvanpach Jan 24, 2024
faf22be
remove snapshot
Nielsvanpach Jan 24, 2024
93bd4f6
Merge pull request #177 from spatie/feature/localization
Nielsvanpach Jan 24, 2024
12131ff
Merge pull request #169 from IvarsSaudinis/main
Nielsvanpach Jan 24, 2024
eb85b1f
Fix styling
Nielsvanpach Jan 24, 2024
82afddc
Added Colombia Holidays (#55)
alvleont Jan 24, 2024
cefdbae
Fix styling
Nielsvanpach Jan 24, 2024
72c1280
Add Finnish Holidays (#85)
ConnySjoblom Jan 24, 2024
915f16a
Add Japan support (#160)
mkokio Jan 24, 2024
964e741
Fix styling
Nielsvanpach Jan 24, 2024
95f9772
Add US Holidays (#26)
arcdigital Jan 24, 2024
e82a37e
Add Serbian holidays (#107)
knubbe82 Jan 24, 2024
3fe1835
Fix styling
Nielsvanpach Jan 24, 2024
8648337
fix Serbia
Nielsvanpach Jan 24, 2024
a47637e
Add El Salvador Holidays (#93)
vlltr Jan 24, 2024
076b619
Fix styling
Nielsvanpach Jan 24, 2024
c1ad5ea
feat: add switzerland
Martin-Welte Jan 22, 2024
0b94548
test: add switzerland test
Martin-Welte Jan 22, 2024
b6db086
PoC canton and multi-language support
herpaderpaldent Jan 22, 2024
92ab6ef
Extend PoC with test
herpaderpaldent Jan 23, 2024
f866e82
use native translation
herpaderpaldent Jan 24, 2024
ea74be9
Merge remote-tracking branch 'herp/feature/switzerland-with-regions' …
herpaderpaldent Jan 24, 2024
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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ use Spatie\Holidays\Holidays;
$holidays = Holidays::for(country: 'be', year: 2024))->get();
```

### Getting holidays in a specific language

```php
use Spatie\Holidays\Holidays;

$holidays = Holidays::for(country: 'be', locale: 'fr'))->get();
```

If the locale is not supported for a country, an exception will be thrown.

### Determining if a date is a holiday

If you need to see if a date is a holiday, you can use the `isHoliday` method.
Expand Down Expand Up @@ -112,6 +122,7 @@ This is a community driven package. If you find any errors, please create an iss
2. Add a test for the new country in the `tests` directory.
3. Run the tests so a snapshot gets created.
4. Verify the result in the newly created snapshot is correct.
5. If the country has multiple languages, add a file in the `lang/` directory.

In case your country has specific rules for calculating holidays,
for example region specific holidays, you can pass this to the constructor of your country class.
Expand Down
12 changes: 12 additions & 0 deletions lang/belgium/fr/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"Nieuwjaar": "Jour de l'An",
"Dag van de Arbeid": "Fête du Travail",
"Nationale Feestdag": "Fête nationale",
"OLV Hemelvaart": "Assomption",
"Allerheiligen": "Toussaint",
"Wapenstilstand": "Armistice",
"Kerstmis": "Noël",
"Paasmaandag": "Lundi de Pâques",
"OLH Hemelvaart": "Ascension",
"Pinkstermaandag": "Lundi de Pentecôte"
}
15 changes: 15 additions & 0 deletions lang/finland/sv/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"Uudenvuodenpäivä": "Nyårsdagen",
"Loppiainen": "Trettondagen",
"Pitkäperjantai": "Långfredagen",
"Pääsiäispäivä": "Påskdagen",
"Toinen pääsiäispäivä": "Annandag påsk",
"Vappu": "Första maj",
"Helatorstai": "Kristi himmelsfärdsdag",
"Helluntaipäivä": "Pingst",
"Juhannuspäivä": "Midsommardagen",
"Pyhäinpäivä": "Alla helgons dag",
"Itsenäisyyspäivä": "Självständighetsdagen",
"Joulupäivä": "Juldagen",
"Tapaninpäivä": "Annandag jul"
}
16 changes: 16 additions & 0 deletions lang/switzerland/de/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"New Year's Day" : "Neujahrstag",
"Berchtold's Day" : "Berchtoldstag",
"St. Joseph's Day" : "Josefstag",
"Good Friday" : "Karfreitag",
"Easter Monday" : "Ostermontag",
"Ascension Day" : "Auffahrt",
"Whit Monday" : "Pfingstmontag",
"Corpus Christi" : "Fronleichnam",
"Swiss National Day" : "Bundesfeier",
"Assumption Day" : "Mariä Himmelfahrt",
"All Saints' Day" : "Allerheiligen",
"Immaculate Conception" : "Mariä Empfängnis",
"Christmas Day" : "Weihnachtstag",
"St. Stephen's Day" : "Stephanstag"
}
16 changes: 16 additions & 0 deletions lang/switzerland/fr/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"New Year's Day": "Nouvel an",
"Berchtold's Day": "2 janvier",
"St. Joseph's Day": "Saint-Joseph",
"Good Friday": "Vendredi saint",
"Easter Monday": "Lundi de Pâques",
"Ascension Day": "Ascension",
"Whit Monday": "Lundi de Pentecôte",
"Corpus Christi": "Fête-Dieu",
"Swiss National Day": "Fête nationale",
"Assumption Day": "Assomption",
"All Saints' Day": "Toussaint",
"Immaculate Conception": "Immaculée Conception",
"Christmas Day": "Noël",
"St. Stephen's Day": "Saint-Étienne"
}
16 changes: 16 additions & 0 deletions lang/switzerland/it/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"New Year's Day": "Capodanno",
"Berchtold's Day": "Giorno di Berchtold",
"St. Joseph's Day": "Giorno di San Giuseppe",
"Good Friday": "Venerdì santo",
"Easter Monday": "Lunedì di Pasqua",
"Ascension Day": "Ascensione",
"Whit Monday": "Glindesdi da Pentecosta",
"Corpus Christi": "Corpus Domini",
"Swiss National Day": "Festa nazionale",
"Assumption Day": "Assunta",
"All Saints' Day": "Ognissanti",
"Immaculate Conception": "Immacolata Concezione",
"Christmas Day": "Natale",
"St. Stephen's Day": "San Steffan"
}
16 changes: 16 additions & 0 deletions lang/switzerland/rm/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"New Year's Day": "Bun di bun onn",
"Berchtold's Day": "Bun di San Berchtold",
"St. Joseph's Day": "Bun di San Giusep",
"Good Friday": "Venerdi San",
"Easter Monday": "Lun di Pasca",
"Ascension Day": "Ascensiun",
"Whit Monday": "Lun di Pentecoste",
"Corpus Christi": "Corpus Christi",
"Swiss National Day": "Festa naziunala",
"Assumption Day": "Assunziun",
"All Saints' Day": "Ognissanti",
"Immaculate Conception": "Immaculada Conceziun",
"Christmas Day": "Nadal",
"St. Stephen's Day": "San Stefaun"
}
32 changes: 32 additions & 0 deletions src/Concerns/Translatable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace Spatie\Holidays\Concerns;

use Spatie\Holidays\Exceptions\InvalidLocale;

trait Translatable
{
protected function translate(string $country, string $name, ?string $locale = null): string
{
if ($locale === null) {
return $name;
}

$countryName = strtolower($country);

$content = file_get_contents(__DIR__."/../../lang/{$countryName}/{$locale}/holidays.json");

if ($content === false) {
throw InvalidLocale::notFound($country, $locale);
}

/** @var array<string, string> $data */
$data = json_decode($content, true);

if (! isset($data[$name])) {
return $name;
}

return $data[$name];
}
}
57 changes: 57 additions & 0 deletions src/Countries/Colombia.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

namespace Spatie\Holidays\Countries;

use Carbon\CarbonImmutable;

class Colombia extends Country
{
public function countryCode(): string
{
return 'co';
}

protected function allHolidays(int $year): array
{
return array_merge([
'Año Nuevo' => '01-01',
'Día del Trabajo' => '05-01',
'Día de la independencia' => '07-20',
'Batalla de Boyacá' => '08-07',
'Inmaculada Concepción' => '12-08',
'Navidad' => '12-25',
], $this->variableHolidays($year));
}

/** @return array<string, CarbonImmutable> */
protected function variableHolidays(int $year): array
{
$easter = $this->easter($year);

return [
'Jueves Santo' => $easter->subDays(3),
'Viernes Santo' => $easter->subDays(2),
'Ascención de Jesús' => $easter->addDays(43),
'Corpus Christi' => $easter->addDays(64),
'Sagrado corazón de Jesús' => $easter->addDays(71),
'Reyes Magos' => $this->emilianiHoliday($year, 1, 6),
'Día de San José' => $this->emilianiHoliday($year, 3, 19),
'San Pedro y San Pablo' => $this->emilianiHoliday($year, 6, 29),
'Asunción de la Virgen' => $this->emilianiHoliday($year, 8, 15),
'Día de la raza' => $this->emilianiHoliday($year, 10, 12),
'Todos los santos' => $this->emilianiHoliday($year, 11, 1),
'Independencia de Cartagena' => $this->emilianiHoliday($year, 11, 11),

];
}

private function emilianiHoliday(int $year, int $month, int $day): CarbonImmutable
{
$dateObj = CarbonImmutable::createFromDate($year, $month, $day, 'America/Bogota')->startOfDay();
if ($dateObj->is('Monday')) {
return $dateObj;
} else {
return $dateObj->next('Monday');
}
}
}
18 changes: 12 additions & 6 deletions src/Countries/Country.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,42 @@
namespace Spatie\Holidays\Countries;

use Carbon\CarbonImmutable;
use Spatie\Holidays\Concerns\Translatable;
use Spatie\Holidays\Exceptions\InvalidYear;
use Spatie\Holidays\Exceptions\UnsupportedCountry;

abstract class Country
{
use Translatable;

abstract public function countryCode(): string;

/** @return array<string, string|CarbonImmutable> */
abstract protected function allHolidays(int $year): array;

/** @return array<string, CarbonImmutable|string> */
public function get(int $year): array
public function get(int $year, ?string $locale = null): array
{
$this->ensureYearCanBeCalculated($year);

$allHolidays = $this->allHolidays($year);

$allHolidays = array_map(function ($date) use ($year) {
$translatedHolidays = [];
foreach ($allHolidays as $name => $date) {
if (is_string($date)) {
$date = CarbonImmutable::createFromFormat('Y-m-d', "{$year}-{$date}");
}

return $date;
}, $allHolidays);
$name = $this->translate(basename(str_replace('\\', '/', static::class)), $name, $locale);

$translatedHolidays[$name] = $date;
}

uasort($allHolidays,
uasort($translatedHolidays,
fn (CarbonImmutable $a, CarbonImmutable $b) => $a->timestamp <=> $b->timestamp
);

return $allHolidays;
return $translatedHolidays;
}

public static function make(): static
Expand Down
40 changes: 40 additions & 0 deletions src/Countries/ElSalvador.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Spatie\Holidays\Countries;

use Carbon\CarbonImmutable;

class ElSalvador extends Country
{
public function countryCode(): string
{
return 'sv';
}

protected function allHolidays(int $year): array
{
return array_merge([
'Año Nuevo' => '01-01',
'Día del Trabajo' => '05-01',
'Día de la Madre' => '05-10',
'Día del Padre' => '06-17',
'Fiesta Divino Salvador del Mundo' => '08-06',
'Día de la Independencia' => '09-15',
'Día de Los Difuntos' => '11-02',
'Navidad' => '12-25',
], $this->variableHolidays($year));
}

/** @return array<string, CarbonImmutable> */
protected function variableHolidays(int $year): array
{
$easter = CarbonImmutable::createFromTimestamp(easter_date($year))
->setTimezone('America/El_Salvador');

return [
'Jueves Santo' => $easter->subDays(3),
'Viernes Santo' => $easter->subDays(2),
'Sábado de Gloria' => $easter->subDays(1),
];
}
}
54 changes: 54 additions & 0 deletions src/Countries/Finland.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

namespace Spatie\Holidays\Countries;

use Carbon\CarbonImmutable;

class Finland extends Country
{
public function countryCode(): string
{
return 'fi';
}

protected function allHolidays(int $year): array
{
return array_merge($this->fixedHolidays($year), $this->variableHolidays($year));
}

/** @return array<string, CarbonImmutable> */
protected function fixedHolidays(int $year): array
{
return [
'Uudenvuodenpäivä' => CarbonImmutable::createFromDate($year, 1, 1),
'Loppiainen' => CarbonImmutable::createFromDate($year, 1, 6),
'Vappu' => CarbonImmutable::createFromDate($year, 5, 1),
'Itsenäisyyspäivä' => CarbonImmutable::createFromDate($year, 12, 6),
'Joulupäivä' => CarbonImmutable::createFromDate($year, 12, 25),
'Tapaninpäivä' => CarbonImmutable::createFromDate($year, 12, 26),
];
}

/** @return array<string, CarbonImmutable> */
protected function variableHolidays(int $year): array
{
$easter = CarbonImmutable::createFromTimestamp(easter_date($year))
->setTimezone('Europe/Helsinki');

$midsummerDay = CarbonImmutable::createFromDate($year, 6, 20)
->next(CarbonImmutable::SATURDAY);

return [
'Pitkäperjantai' => $easter->subDays(2),
'Pääsiäispäivä' => $easter,
'Toinen pääsiäispäivä' => $easter->addDay(),
'Helatorstai' => $easter->addDays(39),
'Helluntaipäivä' => $easter->addDays(49),
'Juhannuspäivä' => $midsummerDay->day > 26
? $midsummerDay->subWeek()
: $midsummerDay,
'Pyhäinpäivä' => CarbonImmutable::createFromDate($year, 10, 31)
->next(CarbonImmutable::SATURDAY),
];
}
}
Loading
Loading