Skip to content

Commit

Permalink
Provide dateTimeClass option (#175)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls authored Oct 13, 2021
1 parent b1f6561 commit 6a86c24
Show file tree
Hide file tree
Showing 6 changed files with 158 additions and 65 deletions.
11 changes: 11 additions & 0 deletions src/Exceptions/InvalidDateTimeClass.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Spatie\OpeningHours\Exceptions;

class InvalidDateTimeClass extends Exception
{
public static function forString(string $string): self
{
return new self("The string `{$string}` isn't a valid class implementing DateTimeInterface.");
}
}
3 changes: 1 addition & 2 deletions src/Helpers/DateTimeCopier.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
trait DateTimeCopier
{
/**
* @param DateTimeInterface $date
*
* @param DateTimeInterface $date
* @return \DateTime|\DateTimeImmutable
*/
protected function copyDateTime(DateTimeInterface $date): DateTimeInterface
Expand Down
30 changes: 12 additions & 18 deletions src/Helpers/DiffTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ private function diffInSeconds(string $stateCheckMethod, string $nextDateMethod,
/**
* Return the amount of open time (number of seconds as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInOpenSeconds(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand All @@ -46,9 +45,8 @@ public function diffInOpenSeconds(DateTimeInterface $startDate, DateTimeInterfac
/**
* Return the amount of open time (number of minutes as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInOpenMinutes(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand All @@ -59,9 +57,8 @@ public function diffInOpenMinutes(DateTimeInterface $startDate, DateTimeInterfac
/**
* Return the amount of open time (number of hours as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInOpenHours(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand All @@ -72,9 +69,8 @@ public function diffInOpenHours(DateTimeInterface $startDate, DateTimeInterface
/**
* Return the amount of closed time (number of seconds as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInClosedSeconds(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand All @@ -85,9 +81,8 @@ public function diffInClosedSeconds(DateTimeInterface $startDate, DateTimeInterf
/**
* Return the amount of closed time (number of minutes as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInClosedMinutes(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand All @@ -98,9 +93,8 @@ public function diffInClosedMinutes(DateTimeInterface $startDate, DateTimeInterf
/**
* Return the amount of closed time (number of hours as a floating number) between 2 dates/times.
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
*
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @return float
*/
public function diffInClosedHours(DateTimeInterface $startDate, DateTimeInterface $endDate): float
Expand Down
70 changes: 48 additions & 22 deletions src/OpeningHours.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
namespace Spatie\OpeningHours;

use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Generator;
use Spatie\OpeningHours\Exceptions\Exception;
use Spatie\OpeningHours\Exceptions\InvalidDate;
use Spatie\OpeningHours\Exceptions\InvalidDateTimeClass;
use Spatie\OpeningHours\Exceptions\InvalidDayName;
use Spatie\OpeningHours\Exceptions\InvalidTimezone;
use Spatie\OpeningHours\Exceptions\MaximumLimitExceeded;
Expand Down Expand Up @@ -40,6 +42,9 @@ class OpeningHours
/** @var int Number of days to try before abandoning the search of the next close/open time */
protected $dayLimit = null;

/** @var string */
protected $dateTimeClass = DateTime::class;

public function __construct($timezone = null)
{
if ($timezone instanceof DateTimeZone) {
Expand All @@ -56,9 +61,8 @@ public function __construct($timezone = null)
}

/**
* @param string[][] $data
* @param string|DateTimeZone|null $timezone
*
* @param string[][] $data
* @param string|DateTimeZone|null $timezone
* @return static
*/
public static function create(array $data, $timezone = null): self
Expand All @@ -67,9 +71,8 @@ public static function create(array $data, $timezone = null): self
}

/**
* @param array $data hours definition array or sub-array
* @param array $excludedKeys keys to ignore from parsing
*
* @param array $data hours definition array or sub-array
* @param array $excludedKeys keys to ignore from parsing
* @return array
*/
public static function mergeOverlappingRanges(array $data, array $excludedKeys = ['data', 'filters', 'overflow'])
Expand Down Expand Up @@ -116,9 +119,8 @@ public static function mergeOverlappingRanges(array $data, array $excludedKeys =
}

/**
* @param string[][] $data
* @param string|DateTimeZone|null $timezone
*
* @param string[][] $data
* @param string|DateTimeZone|null $timezone
* @return static
*/
public static function createAndMergeOverlappingRanges(array $data, $timezone = null)
Expand All @@ -127,8 +129,7 @@ public static function createAndMergeOverlappingRanges(array $data, $timezone =
}

/**
* @param array $data
*
* @param array $data
* @return bool
*/
public static function isValid(array $data): bool
Expand All @@ -142,14 +143,36 @@ public static function isValid(array $data): bool
}
}

/**
* Select the class to use to create new date-time instances.
*
* @param string|null $dateTimeClass
* @return $this
*
* @throws InvalidDateTimeClass if $dateTimeClass is set with a string that is not a valid DateTimeInterface.
*/
public function setDateTimeClass(string $dateTimeClass = null)
{
if ($dateTimeClass !== null && ! is_a($dateTimeClass, DateTimeInterface::class, true)) {
throw InvalidDateTimeClass::forString($dateTimeClass);
}

$this->dateTimeClass = $dateTimeClass ?? DateTime::class;

return $this;
}

/**
* Set the number of days to try before abandoning the search of the next close/open time.
*
* @param int $dayLimit number of days
* @param int $dayLimit number of days
* @return $this
*/
public function setDayLimit(int $dayLimit)
{
$this->dayLimit = $dayLimit;

return $this;
}

/**
Expand All @@ -176,7 +199,8 @@ public function getFilters(): array

public function fill(array $data)
{
list($openingHours, $exceptions, $metaData, $filters, $overflow) = $this->parseOpeningHoursAndExceptions($data);
list($openingHours, $exceptions, $metaData, $filters, $overflow, $dateTimeClass) = $this
->parseOpeningHoursAndExceptions($data);

$this->overflow = $overflow;

Expand All @@ -186,7 +210,7 @@ public function fill(array $data)

$this->setExceptionsFromStrings($exceptions);

return $this->setFilters($filters)->setData($metaData);
return $this->setDateTimeClass($dateTimeClass)->setFilters($filters)->setData($metaData);
}

public function forWeek(): array
Expand Down Expand Up @@ -261,8 +285,7 @@ public function forDate(DateTimeInterface $date): OpeningHoursForDay
}

/**
* @param DateTimeInterface $date
*
* @param DateTimeInterface $date
* @return TimeRange[]
*/
public function forDateTime(DateTimeInterface $date): array
Expand All @@ -286,7 +309,7 @@ public function isOpenOn(string $day): bool
list(, $year, $month, $day) = $match;
$year = $year ?: date('Y');

return count($this->forDate(new DateTime("$year-$month-$day", $this->timezone))) > 0;
return count($this->forDate(new DateTimeImmutable("$year-$month-$day", $this->timezone))) > 0;
}

return count($this->forDay($day)) > 0;
Expand Down Expand Up @@ -321,12 +344,12 @@ public function isClosedAt(DateTimeInterface $dateTime): bool

public function isOpen(): bool
{
return $this->isOpenAt(new DateTime());
return $this->isOpenAt(new $this->dateTimeClass());
}

public function isClosed(): bool
{
return $this->isClosedAt(new DateTime());
return $this->isClosedAt(new $this->dateTimeClass());
}

public function currentOpenRange(DateTimeInterface $dateTime)
Expand Down Expand Up @@ -376,8 +399,9 @@ public function currentOpenRangeEnd(DateTimeInterface $dateTime)
return $dateTime->setTime($nextDateTime->format('G'), $nextDateTime->format('i'), 0);
}

public function nextOpen(DateTimeInterface $dateTime): DateTimeInterface
public function nextOpen(DateTimeInterface $dateTime = null): DateTimeInterface
{
$dateTime = $dateTime ?? new $this->dateTimeClass();
$dateTime = $this->copyDateTime($dateTime);
$openingHoursForDay = $this->forDate($dateTime);
$nextOpen = $openingHoursForDay->nextOpen(Time::fromDateTime($dateTime));
Expand Down Expand Up @@ -413,8 +437,9 @@ public function nextOpen(DateTimeInterface $dateTime): DateTimeInterface
return $dateTime->setTime($nextDateTime->format('G'), $nextDateTime->format('i'), 0);
}

public function nextClose(DateTimeInterface $dateTime): DateTimeInterface
public function nextClose(DateTimeInterface $dateTime = null): DateTimeInterface
{
$dateTime = $dateTime ?? new $this->dateTimeClass();
$dateTime = $this->copyDateTime($dateTime);
$nextClose = null;
if ($this->overflow) {
Expand Down Expand Up @@ -569,6 +594,7 @@ public function setTimezone($timezone)

protected function parseOpeningHoursAndExceptions(array $data): array
{
$dateTimeClass = Arr::pull($data, 'dateTimeClass', null);
$metaData = Arr::pull($data, 'data', null);
$exceptions = [];
$filters = Arr::pull($data, 'filters', []);
Expand All @@ -590,7 +616,7 @@ protected function parseOpeningHoursAndExceptions(array $data): array
$openingHours[$this->normalizeDayName($day)] = $openingHoursData;
}

return [$openingHours, $exceptions, $metaData, $filters, $overflow];
return [$openingHours, $exceptions, $metaData, $filters, $overflow, $dateTimeClass];
}

protected function setOpeningHoursFromStrings(string $day, array $openingHours)
Expand Down
Loading

0 comments on commit 6a86c24

Please sign in to comment.