From 971a8b5b99defdf98bd89ffc1ea141c315fbc36c Mon Sep 17 00:00:00 2001 From: Hazel Seanor Date: Mon, 19 Nov 2018 15:48:58 +0000 Subject: [PATCH] add 'on' filter --- src/Yasumi/Filters/OnFilter.php | 75 +++++++++++++++++++ src/Yasumi/Provider/AbstractProvider.php | 20 ++++++ tests/Base/HolidayOnFilterTest.php | 92 ++++++++++++++++++++++++ 3 files changed, 187 insertions(+) create mode 100644 src/Yasumi/Filters/OnFilter.php create mode 100644 tests/Base/HolidayOnFilterTest.php diff --git a/src/Yasumi/Filters/OnFilter.php b/src/Yasumi/Filters/OnFilter.php new file mode 100644 index 000000000..ed13cd785 --- /dev/null +++ b/src/Yasumi/Filters/OnFilter.php @@ -0,0 +1,75 @@ + + * @author Sacha Telgenhof + */ + +namespace Yasumi\Filters; + +use Countable; +use FilterIterator; +use Iterator; + +/** + * OnFilter is a class used for filtering holidays based on a given date. + * + * Filters for all holidays that happen on the given date. + * + * Note: this class can be used separately, however is implemented by the AbstractProvider::on method. + * + * @package Yasumi\Filters + */ +class OnFilter extends FilterIterator implements Countable +{ + /** + * @var string date to check for holidays + */ + private $date; + + + /** + * Construct the On FilterIterator Object + * + * @param \Iterator $iterator Iterator object of the Holidays Provider + * @param \DateTimeInterface $date Start date of the time frame to check against + */ + + public function __construct( + Iterator $iterator, + \DateTimeInterface $date + ) { + parent::__construct($iterator); + $this->date = $date->format('Y-m-d'); + } + + /** + * @return bool Check whether the current element of the iterator is acceptable + */ + public function accept(): bool + { + $holiday = $this->getInnerIterator()->current()->format('Y-m-d'); + return $holiday == $this->date; + } + + /** + * @return integer Returns the number of holidays that happen on the specified date + */ + public function count(): int + { + $days = \array_keys(\iterator_to_array($this)); + + \array_walk($days, function (&$day) { + $day = \str_replace('substituteHoliday:', '', $day); + }); + + return \count(\array_unique($days)); + } +} diff --git a/src/Yasumi/Provider/AbstractProvider.php b/src/Yasumi/Provider/AbstractProvider.php index b35b0747a..a66738925 100755 --- a/src/Yasumi/Provider/AbstractProvider.php +++ b/src/Yasumi/Provider/AbstractProvider.php @@ -17,6 +17,7 @@ use InvalidArgumentException; use IteratorAggregate; use Yasumi\Filters\BetweenFilter; +use Yasumi\Filters\OnFilter; use Yasumi\Holiday; use Yasumi\ProviderInterface; use Yasumi\TranslationsInterface; @@ -443,6 +444,25 @@ public function between(\DateTimeInterface $start_date, \DateTimeInterface $end_ return new BetweenFilter($this->getIterator(), $start_date, $end_date, $equals); } + + /** + * Retrieves a list of all holidays that happen on the given date. + * + * Yasumi only calculates holidays for a single year, so a date outside of the given year will not appear to + * contain any holidays. + * + * Please take care to use the appropriate timezone for the date parameters. If there is a different timezone used + * for these parameters versus the instantiated Holiday Provider, the outcome might be unexpected (but correct). + * + * @param \DateTimeInterface $date Date to check for holidays on. + * + * @return \Yasumi\Filters\OnFilter + */ + public function on(\DateTimeInterface $date): OnFilter + { + return new OnFilter($this->getIterator(), $date); + } + /** * Get an iterator for the holidays. * diff --git a/tests/Base/HolidayOnFilterTest.php b/tests/Base/HolidayOnFilterTest.php new file mode 100644 index 000000000..56b5795ae --- /dev/null +++ b/tests/Base/HolidayOnFilterTest.php @@ -0,0 +1,92 @@ + + * @author Sacha Telgenhof + */ + +namespace Yasumi\tests\Base; + +use DateTime; +use DateTimeZone; +use InvalidArgumentException; +use PHPUnit\Framework\TestCase; +use Yasumi\tests\YasumiBase; +use Yasumi\Yasumi; + +/** + * Class HolidayOnFilterTest. + * + * Contains tests for testing the OnFilter class + */ +class HolidayOnFilterTest extends TestCase +{ + use YasumiBase; + + /** + * Tests the basic usage of the OnFilter. + */ + public function testHolidaysOnDate() + { + $timezone = 'Europe/Amsterdam'; + $holidays = Yasumi::create('Netherlands', 2016); + + $holidayDates = [ + 'goodFriday' => new DateTime('03/25/2016', new DateTimeZone($timezone)), + 'easter' => new DateTime('03/27/2016', new DateTimeZone($timezone)), + 'summerTime' => new DateTime('03/27/2016', new DateTimeZone($timezone)) + ]; + + foreach ($holidayDates as $name => $date) { + $holidaysOnDate = $holidays->on( + $date + ); + + $this->assertArrayHasKey($name, \iterator_to_array($holidaysOnDate)); + } + } + + public function testHolidaysNotOnDate() + { + $timezone = 'Europe/Amsterdam'; + $holidays = Yasumi::create('Netherlands', 2016); + + $holidayWrongDates = [ + 'goodFriday' => new DateTime('04/25/2016', new DateTimeZone($timezone)), + 'easter' => new DateTime('03/22/2016', new DateTimeZone($timezone)), + 'summerTime' => new DateTime('12/27/2016', new DateTimeZone($timezone)) + ]; + + foreach ($holidayWrongDates as $name => $date) { + $holidaysOnDate = $holidays->on( + $date + ); + + $this->assertArrayNotHasKey($name, \iterator_to_array($holidaysOnDate)); + } + } + + public function testCorrectNumberOfHolidaysOnDate() + { + $timezone = 'Europe/Amsterdam'; + $holidays = Yasumi::create('Netherlands', 2016); + + // No holidays + $holidaysOnDate = $holidays->on(new \DateTime('11/19/2016', new DateTimeZone($timezone))); + $this->assertEquals(0, $holidaysOnDate->count()); + + // One holiday + $holidaysOnDate = $holidays->on(new \DateTime('12/25/2016', new DateTimeZone($timezone))); + $this->assertEquals(1, $holidaysOnDate->count()); + + // Multiple holidays + $holidaysOnDate = $holidays->on(new \DateTime('03/27/2016', new DateTimeZone($timezone))); + $this->assertGreaterThan(1, $holidaysOnDate->count()); + } +}