Skip to content

Commit

Permalink
Merge pull request #214 from spatie/refactor/islamic-calendar
Browse files Browse the repository at this point in the history
Implement Islamic calendar
  • Loading branch information
Nielsvanpach authored Mar 22, 2024
2 parents ee306ae + 69ed981 commit e0cf796
Show file tree
Hide file tree
Showing 18 changed files with 485 additions and 315 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/phpstan.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
php-version: '8.1'
coverage: none

- name: Install composer dependencies
Expand All @@ -21,4 +21,4 @@ jobs:
COMPOSER_AUTH: ${{ secrets.COMPOSER_AUTH }}

- name: Run PHPStan
run: ./vendor/bin/phpstan --error-format=github
run: ./vendor/bin/phpstan
28 changes: 28 additions & 0 deletions lang/turkey/tr/holidays.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"New Year's Day": "Yılbaşı",
"Eid al-Fitr Eve": "Ramazan Bayramı Arifesi",
"Eid al-Fitr": "Ramazan Bayramı 1. Gün",
"Eid al-Fitr Day 2": "Ramazan Bayramı 2. Gün",
"Eid al-Fitr Day 3": "Ramazan Bayramı 3. Gün",
"National Sovereignty and Children's Day": "Ulusal Egemenlik ve Çocuk Bayramı",
"Labor and Solidarity Day": "Emek ve Dayanışma Günü",
"Commemoration of Atatürk, Youth and Sports Day": "Atatürk'ü Anma, Gençlik ve Spor Bayramı",
"Eid al-Adha Eve": "Kurban Bayramı Arifesi",
"Eid al-Adha": "Kurban Bayramı 1. Gün",
"Eid al-Adha Day 2": "Kurban Bayramı 2. Gün",
"Eid al-Adha Day 3": "Kurban Bayramı 3. Gün",
"Eid al-Adha Day 4": "Kurban Bayramı 4. Gün",
"Democracy and National Unity Day": "Demokrasi ve Millî Birlik Günü",
"Victory Day": "Zafer Bayramı",
"Republic Day Eve": "Cumhuriyet Bayramı Arifesi",
"Republic Day": "Cumhuriyet Bayramı",
"2. Eid al-Fitr Eve": "2. Ramazan Bayramı Arifesi",
"2. Eid al-Fitr": "2. Ramazan Bayramı 1. Gün",
"2. Eid al-Fitr Day 2": "2. Ramazan Bayramı 2. Gün",
"2. Eid al-Fitr Day 3": "2. Ramazan Bayramı 3. Gün",
"2. Eid al-Adha Eve": "2. Kurban Bayramı Arifesi",
"2. Eid al-Adha": "2. Kurban Bayramı 1. Gün",
"2. Eid al-Adha Day 2": "2. Kurban Bayramı 2. Gün",
"2. Eid al-Adha Day 3": "2. Kurban Bayramı 3. Gün",
"2. Eid al-Adha Day 4": "2. Kurban Bayramı 4. Gün"
}
49 changes: 47 additions & 2 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -1,13 +1,58 @@
parameters:
ignoreErrors:
-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Albania\\:\\:arafat\\.$#"
count: 1
path: src/Countries/Albania.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Albania\\:\\:ashura\\.$#"
count: 1
path: src/Countries/Albania.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Albania\\:\\:islamicNewYear\\.$#"
count: 1
path: src/Countries/Albania.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Albania\\:\\:prophetMuhammadBirthday\\.$#"
count: 1
path: src/Countries/Albania.php

-
message: "#^Argument of an invalid type Carbon\\\\CarbonPeriod supplied for foreach, only iterables are supported\\.$#"
count: 1
path: src/Countries/Country.php

-
message: "#^Argument of an invalid type array\\<int, string\\>\\|false supplied for foreach, only iterables are supported\\.$#"
count: 1
path: src/Countries/Country.php

-
message: "#^Ternary operator condition is always true\\.$#"
count: 3
message: "#^Binary operation \"\\+\" between non\\-falsy\\-string and 1 results in an error\\.$#"
count: 1
path: src/Countries/Country.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Turkey\\:\\:arafat\\.$#"
count: 1
path: src/Countries/Turkey.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Turkey\\:\\:ashura\\.$#"
count: 1
path: src/Countries/Turkey.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Turkey\\:\\:islamicNewYear\\.$#"
count: 1
path: src/Countries/Turkey.php

-
message: "#^Access to undefined constant Spatie\\\\Holidays\\\\Countries\\\\Turkey\\:\\:prophetMuhammadBirthday\\.$#"
count: 1
path: src/Countries/Turkey.php

-
Expand Down
2 changes: 2 additions & 0 deletions phpstan.neon.dist
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ parameters:

ignoreErrors:
- '#Unsafe usage of new static#'
- '#Cannot call method startOfDay\(\) on Carbon\\CarbonImmutable\|null#'
- '#Cannot call method addDays\(\) on Carbon\\CarbonImmutable\|null#'
141 changes: 141 additions & 0 deletions src/Calendars/IslamicCalendar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<?php

namespace Spatie\Holidays\Calendars;

use Carbon\CarbonImmutable;
use Carbon\CarbonPeriod;
use Carbon\Exceptions\InvalidFormatException;
use Spatie\Holidays\Countries\Country;
use Spatie\Holidays\Exceptions\InvalidYear;

/** @mixin Country */
trait IslamicCalendar
{
/** @return array<CarbonPeriod> */
public function eidAlFitr(int $year, int $totalDays = 3): array
{
return $this->getMultiDayHoliday(self::eidAlFitr, $year, $totalDays);
}

/** @return array<CarbonPeriod> */
public function eidAlAdha(int $year, int $totalDays = 4): array
{
return $this->getMultiDayHoliday(self::eidAlAdha, $year, $totalDays);
}

/** @return array<CarbonPeriod> */
protected function ashura(int $year, int $totalDays = 2): array
{
return $this->getMultiDayHoliday(self::ashura, $year, $totalDays);
}

protected function arafat(int $year): CarbonImmutable
{
return $this->getSingleDayHoliday(self::arafat, $year);
}

protected function islamicNewYear(int $year): CarbonImmutable
{
return $this->getSingleDayHoliday(self::islamicNewYear, $year);
}

protected function prophetMuhammadBirthday(int $year): CarbonImmutable
{
return $this->getSingleDayHoliday(self::prophetMuhammadBirthday, $year);
}

/** @param array<string> $collection */
protected function getSingleDayHoliday(array $collection, int $year): CarbonImmutable
{
$date = $collection[$year] ?? null;

if ($date === null) {
throw InvalidYear::range($this->countryCode(), 1970, 2037);
}

$date = CarbonImmutable::createFromFormat('Y-m-d', "{$year}-{$date}")?->startOfDay();

if ($date === null) {
throw new InvalidFormatException('Invalid date for holiday');
}

return $date;
}

/**
* @param array<string|array<string>> $collection
* @return array<CarbonPeriod>
*/
protected function getMultiDayHoliday(array $collection, int $year, int $totalDays): array
{
$date = $collection[$year] ?? null;

if ($date === null) {
throw InvalidYear::range($this->countryCode(), 1970, 2037);
}

$overlap = $this->getOverlapping($collection, $year, $totalDays);

if ($overlap) {
$period = $this->createPeriod($overlap, $year - 1, $totalDays);

$date = [$period, $date];
}

if (! is_array($date)) {
return [$this->createPeriod($date, $year, $totalDays)];
}

// Twice a year
$periods = [];
$dates = $date;

/** @var CarbonPeriod|string $date */
foreach ($dates as $date) {
if ($date instanceof CarbonPeriod) {
$periods[] = $date;

continue;
}

$periods[] = $this->createPeriod($date, $year, $totalDays);
}

return $periods;
}

protected function createPeriod(string $date, int $year, int $totalDays): CarbonPeriod
{
$start = CarbonImmutable::createFromFormat('Y-m-d', "{$year}-{$date}")?->startOfDay();
$end = $start->addDays($totalDays - 1)->startOfDay();

return CarbonPeriod::create($start, '1 day', $end);
}

/** @param array<string|array<string>> $collection */
protected function getOverlapping(array $collection, int $year, int $totalDays): ?string
{
if ($year === 1970) {
return null;
}

$date = $collection[$year - 1] ?? null;

if ($date === null) {
throw InvalidYear::range($this->countryCode(), 1970, 2037);
}

if (is_array($date)) {
$date = end($date);
}

$start = CarbonImmutable::createFromFormat('Y-m-d', "{$year}-{$date}")?->startOfDay();
$end = $start->addDays($totalDays - 1)->startOfDay();

if ($end->year !== $year) {
return (string) $date;
}

return null;
}
}
15 changes: 4 additions & 11 deletions src/Concerns/Translatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,19 @@ trait Translatable
{
public function translate(string $country, string $name, ?string $locale = null): string
{
if ($locale === null) {
return $name;

}

if ($locale === $this->defaultLocale()) {
return $name;
}

$locale = $locale ?? $this->defaultLocale();

$countryName = strtolower($country);
$filePath = __DIR__."/../../lang/{$countryName}/{$locale}/holidays.json";

if (file_exists($filePath)) {
$content = file_get_contents($filePath);
} else {
throw InvalidLocale::notFound($country, $locale);
return $name;
}

if ($content === false) {
Expand All @@ -33,10 +30,6 @@ public function translate(string $country, string $name, ?string $locale = null)
/** @var array<string, string> $data */
$data = json_decode($content, true);

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

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

namespace Spatie\Holidays\Contracts;

use Carbon\CarbonImmutable;
use Carbon\CarbonPeriod;

interface Islamic
{
/** @return array<string, string|CarbonImmutable|CarbonPeriod> */
public function islamicHolidays(int $year): array;
}
Loading

0 comments on commit e0cf796

Please sign in to comment.