diff --git a/src/OpeningHours.php b/src/OpeningHours.php index ed7b509..f84fe94 100644 --- a/src/OpeningHours.php +++ b/src/OpeningHours.php @@ -4,6 +4,7 @@ use DateTime; use DateTimeInterface; +use DateTimeZone; use Spatie\OpeningHours\Exceptions\Exception; use Spatie\OpeningHours\Exceptions\InvalidDate; use Spatie\OpeningHours\Exceptions\InvalidDayName; @@ -17,8 +18,13 @@ class OpeningHours /** @var array */ protected $exceptions = []; - public function __construct() + /** @var DateTimeZone|null */ + protected $timezone; + + public function __construct($timezone = null) { + $this->timezone = $timezone ? new DateTimeZone($timezone) : null; + $this->openingHours = Day::mapDays(function () { return new OpeningHoursForDay(); }); @@ -77,6 +83,8 @@ public function forDay(string $day): OpeningHoursForDay public function forDate(DateTimeInterface $date): OpeningHoursForDay { + $date = $this->applyTimezone($date); + return $this->exceptions[$date->format('Y-m-d')] ?? $this->forDay(Day::onDateTime($date)); } @@ -97,6 +105,8 @@ public function isClosedOn(string $day): bool public function isOpenAt(DateTimeInterface $dateTime): bool { + $dateTime = $this->applyTimezone($dateTime); + $openingHoursForDay = $this->forDate($dateTime); return $openingHoursForDay->isOpenAt(Time::fromDateTime($dateTime)); @@ -117,6 +127,11 @@ public function isClosed(): bool return $this->isClosedAt(new DateTime()); } + public function setTimezone($timezone) + { + $this->timezone = new DateTimeZone($timezone); + } + protected function parseOpeningHoursAndExceptions(array $data): array { $exceptions = Arr::pull($data, 'exceptions', []); @@ -159,4 +174,13 @@ protected function normalizeDayName(string $day) return $day; } + + protected function applyTimezone(DateTimeInterface $date) + { + if ($this->timezone) { + $date = $date->setTimezone($this->timezone); + } + + return $date; + } } diff --git a/tests/OpeningHoursTest.php b/tests/OpeningHoursTest.php index 86784e6..c4bd651 100644 --- a/tests/OpeningHoursTest.php +++ b/tests/OpeningHoursTest.php @@ -3,6 +3,7 @@ namespace Spatie\OpeningHours\Test; use DateTime; +use DateTimeZone; use Spatie\OpeningHours\OpeningHours; class OpeningHoursTest extends \PHPUnit_Framework_TestCase @@ -136,4 +137,35 @@ public function it_can_determine_that_its_open_at_a_certain_date_and_time_on_an_ $this->assertFalse($openingHours->isOpenAt($shouldBeClosed)); $this->assertTrue($openingHours->isClosedAt($shouldBeClosed)); } + + /** @test */ + public function it_can_set_the_timezone_on_the_openings_hours_object() + { + $openingHours = new OpeningHours('Europe/Amsterdam'); + $openingHours->fill([ + 'monday' => ['09:00-18:00'], + 'exceptions' => [ + '2016-11-14' => ['09:00-13:00'], + ], + ]); + + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 10:00'))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 15:59'))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 08:00'))); + $this->assertFalse($openingHours->isOpenAt(new DateTime('2016-10-10 06:00'))); + + $this->assertFalse($openingHours->isOpenAt(new DateTime('2016-10-10 06:00', new DateTimeZone('Europe/Amsterdam')))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 09:00', new DateTimeZone('Europe/Amsterdam')))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 17:59', new DateTimeZone('Europe/Amsterdam')))); + + $this->assertFalse($openingHours->isOpenAt(new DateTime('2016-11-14 17:59', new DateTimeZone('Europe/Amsterdam')))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-11-14 12:59', new DateTimeZone('Europe/Amsterdam')))); + + $this->assertFalse($openingHours->isOpenAt(new DateTime('2016-11-14 15:59', new DateTimeZone('America/Denver')))); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 09:59', new DateTimeZone('America/Denver')))); + + date_default_timezone_set('America/Denver'); + $this->assertTrue($openingHours->isOpenAt(new DateTime('2016-10-10 09:59'))); + $this->assertFalse($openingHours->isOpenAt(new DateTime('2016-10-10 10:00'))); + } }