File manager - Edit - /home/premiey/www/wp-content/plugins/simply-schedule-appointments/vendor/league/period/src/Period.php
Back
<?php /** * League.Period (https://period.thephpleague.com) * * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare(strict_types=1); namespace League\Period; use DateInterval; use DatePeriod; use DateTimeImmutable; use DateTimeInterface; use DateTimeZone; use JsonSerializable; use function array_filter; use function array_keys; use function implode; use function sprintf; /** * A immutable value object class to manipulate Time interval. * * @package League.period * @author Ignace Nyamagana Butera <nyamsprod@gmail.com> * @since 1.0.0 */ final class Period implements JsonSerializable { private const ISO8601_FORMAT = 'Y-m-d\TH:i:s.u\Z'; private const BOUNDARY_TYPE = [ self::INCLUDE_START_EXCLUDE_END => 1, self::INCLUDE_ALL => 1, self::EXCLUDE_START_INCLUDE_END => 1, self::EXCLUDE_ALL => 1, ]; public const INCLUDE_START_EXCLUDE_END = '[)'; public const EXCLUDE_START_INCLUDE_END = '(]'; public const EXCLUDE_ALL = '()'; public const INCLUDE_ALL = '[]'; /** @var DateTimeImmutable */ private $startDate; /** @var DateTimeImmutable */ private $endDate; /** @var string */ private $boundaryType; /** * Creates a new instance. * * @param Datepoint|DateTimeInterface|int|string $startDate the starting datepoint * @param Datepoint|DateTimeInterface|int|string $endDate the ending datepoint * * @throws Exception If $startDate is greater than $endDate */ public function __construct($startDate, $endDate, string $boundaryType = self::INCLUDE_START_EXCLUDE_END) { $startDate = self::filterDatepoint($startDate); $endDate = self::filterDatepoint($endDate); if ($startDate > $endDate) { throw new Exception('The ending datepoint must be greater or equal to the starting datepoint'); } if (!isset(self::BOUNDARY_TYPE[$boundaryType])) { throw new Exception(sprintf( 'The boundary type `%s` is invalid. The only valid values are %s', $boundaryType, '`'.implode('`, `', array_keys(self::BOUNDARY_TYPE)).'`' )); } $this->startDate = $startDate; $this->endDate = $endDate; $this->boundaryType = $boundaryType; } /** * Returns a DateTimeImmutable instance. * * @param Datepoint|DateTimeInterface|int|string $datepoint a Datepoint */ private static function filterDatepoint($datepoint): DateTimeImmutable { if ($datepoint instanceof DateTimeImmutable) { return $datepoint; } if ($datepoint instanceof DateTimeInterface) { return new DateTimeImmutable($datepoint->format('Y-m-d H:i:s.u'), $datepoint->getTimezone()); } $timestamp = $datepoint; if (is_int($timestamp) || false !== ($timestamp = filter_var($datepoint, FILTER_VALIDATE_INT))) { return new DateTimeImmutable('@'.$timestamp); } return new DateTimeImmutable($datepoint); } /** * Returns a DateInterval instance. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ private static function filterDuration($duration): DateInterval { if ($duration instanceof DateInterval) { return $duration; } if ($duration instanceof self) { return $duration->dateInterval(); } return Duration::create($duration); } /************************************************** * Named constructors **************************************************/ /** * @inheritDoc */ public static function __set_state(array $interval) { return new self( $interval['startDate'], $interval['endDate'], $interval['boundaryType'] ?? self::INCLUDE_START_EXCLUDE_END ); } /** * Creates new instance from a starting date endpoint and a duration. * * @param Datepoint|DateTimeInterface|int|string $startDate the starting date endpoint * @param DateInterval|Duration|string|int $duration a Duration */ public static function after($startDate, $duration, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $startDate = self::filterDatepoint($startDate); return new self($startDate, $startDate->add(self::filterDuration($duration)), $boundaryType); } /** * Creates new instance from a ending date endpoint and a duration. * * @param Datepoint|DateTimeInterface|int|string $endDate the ending date endpoint * @param DateInterval|Duration|string|int $duration a Duration */ public static function before($endDate, $duration, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $endDate = self::filterDatepoint($endDate); return new self($endDate->sub(self::filterDuration($duration)), $endDate, $boundaryType); } /** * Creates new instance where the given duration is simultaneously * subtracted from and added to the date endpoint. * * @param Datepoint|DateTimeInterface|int|string $datepoint a Date endpoint * @param DateInterval|Duration|string|int $duration a Duration */ public static function around($datepoint, $duration, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $datepoint = self::filterDatepoint($datepoint); $duration = self::filterDuration($duration); return new self($datepoint->sub($duration), $datepoint->add($duration), $boundaryType); } /** * Creates new instance from a DatePeriod. */ public static function fromDatePeriod(DatePeriod $datePeriod, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { return new self($datePeriod->getStartDate(), $datePeriod->getEndDate(), $boundaryType); } /** * Creates new instance for a specific year. */ public static function fromYear(int $year, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $startDate = (new DateTimeImmutable())->setDate($year, 1, 1)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P1Y')), $boundaryType); } /** * Creates new instance for a specific ISO year. */ public static function fromIsoYear(int $year, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { return new self( (new DateTimeImmutable())->setISODate($year, 1)->setTime(0, 0), (new DateTimeImmutable())->setISODate(++$year, 1)->setTime(0, 0), $boundaryType ); } /** * Creates new instance for a specific year and semester. */ public static function fromSemester(int $year, int $semester = 1, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $month = (($semester - 1) * 6) + 1; $startDate = (new DateTimeImmutable())->setDate($year, $month, 1)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P6M')), $boundaryType); } /** * Creates new instance for a specific year and quarter. */ public static function fromQuarter(int $year, int $quarter = 1, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $month = (($quarter - 1) * 3) + 1; $startDate = (new DateTimeImmutable())->setDate($year, $month, 1)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P3M')), $boundaryType); } /** * Creates new instance for a specific year and month. */ public static function fromMonth(int $year, int $month = 1, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $startDate = (new DateTimeImmutable())->setDate($year, $month, 1)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P1M')), $boundaryType); } /** * Creates new instance for a specific ISO8601 week. */ public static function fromIsoWeek(int $year, int $week = 1, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $startDate = (new DateTimeImmutable())->setISODate($year, $week, 1)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P7D')), $boundaryType); } /** * Creates new instance for a specific year, month and day. */ public static function fromDay(int $year, int $month = 1, int $day = 1, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { $startDate = (new DateTimeImmutable())->setDate($year, $month, $day)->setTime(0, 0); return new self($startDate, $startDate->add(new DateInterval('P1D')), $boundaryType); } /** * Creates new instance for Datepoint. */ public static function fromDatepoint(DateTimeInterface $startDate, DateTimeInterface $endDate, string $boundaryType = self::INCLUDE_START_EXCLUDE_END): self { return new self($startDate, $endDate, $boundaryType); } /************************************************** * Basic getters **************************************************/ /** * Returns the starting date endpoint. */ public function getStartDate(): DateTimeImmutable { return $this->startDate; } /** * Returns the ending date endpoint. */ public function getEndDate(): DateTimeImmutable { return $this->endDate; } /** * Returns the instance boundary type. */ public function getBoundaryType(): string { return $this->boundaryType; } /** * Returns the instance duration as expressed in seconds. */ public function timeDuration(): float { return $this->endDate->getTimestamp() - $this->startDate->getTimestamp(); } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::timeDuration() * * Returns the instance duration as expressed in seconds. */ public function getTimestampInterval(): float { return $this->timeDuration(); } /** * Returns the instance duration as a DateInterval object. */ public function dateInterval(): DateInterval { return $this->startDate->diff($this->endDate); } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::dateInterval() * * Returns the instance duration as a DateInterval object. */ public function getDateInterval(): DateInterval { return $this->dateInterval(); } /************************************************** * String representation **************************************************/ /** * Returns the string representation as a ISO8601 interval format. * * @deprecated 4.10.0 This method will be removed in the next major point release * @see ::toIso8601() */ public function __toString() { return $this->toIso8601(); } /** * Returns the string representation as a ISO8601 interval format. * * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals * @param ?string $format */ public function toIso8601(?string $format = null): string { $utc = new DateTimeZone('UTC'); $format = $format ?? self::ISO8601_FORMAT; $startDate = $this->startDate->setTimezone($utc)->format($format); $endDate = $this->endDate->setTimezone($utc)->format($format); return $startDate.'/'.$endDate; } /** * Returns the JSON representation of an instance. * * Based on the JSON representation of dates as * returned by Javascript Date.toJSON() method. * * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toJSON * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString * * @return array<string> */ public function jsonSerialize(): array { [$startDate, $endDate] = explode('/', $this->toIso8601(), 2); return ['startDate' => $startDate, 'endDate' => $endDate]; } /** * Returns the mathematical representation of an instance as a left close, right open interval. * * @see https://en.wikipedia.org/wiki/Interval_(mathematics)#Notations_for_intervals * @see https://php.net/manual/en/function.date.php * @see https://www.postgresql.org/docs/9.3/static/rangetypes.html * * @param string $format the format of the outputted date string */ public function toIso80000(string $format): string { return $this->boundaryType[0] .$this->startDate->format($format) .', ' .$this->endDate->format($format) .$this->boundaryType[1]; } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::toIso80000() * * @param string $format the format of the outputted date string * * Returns the mathematical representation of an instance as a left close, right open interval. * * @see https://en.wikipedia.org/wiki/Interval_(mathematics)#Notations_for_intervals * @see https://php.net/manual/en/function.date.php * @see https://www.postgresql.org/docs/9.3/static/rangetypes.html */ public function format(string $format): string { return $this->toIso80000($format); } /************************************************** * Boundary related methods **************************************************/ /** * Tells whether the start datepoint is included in the boundary. */ public function isStartIncluded(): bool { return '[' === $this->boundaryType[0]; } /** * Tells whether the start datepoint is excluded from the boundary. */ public function isStartExcluded(): bool { return '(' === $this->boundaryType[0]; } /** * Tells whether the end datepoint is included in the boundary. */ public function isEndIncluded(): bool { return ']' === $this->boundaryType[1]; } /** * Tells whether the end datepoint is excluded from the boundary. */ public function isEndExcluded(): bool { return ')' === $this->boundaryType[1]; } /************************************************** * Duration comparison methods **************************************************/ /** * Compares two instances according to their duration. * * Returns: * <ul> * <li> -1 if the current Interval is lesser than the submitted Interval object</li> * <li> 1 if the current Interval is greater than the submitted Interval object</li> * <li> 0 if both Interval objects have the same duration</li> * </ul> */ public function durationCompare(self $interval): int { return $this->startDate->add($this->dateInterval()) <=> $this->startDate->add($interval->dateInterval()); } /** * Tells whether the current instance duration is equal to the submitted one. */ public function durationEquals(self $interval): bool { return 0 === $this->durationCompare($interval); } /** * Tells whether the current instance duration is greater than the submitted one. */ public function durationGreaterThan(self $interval): bool { return 1 === $this->durationCompare($interval); } /** * Tells whether the current instance duration is less than the submitted one. */ public function durationLessThan(self $interval): bool { return -1 === $this->durationCompare($interval); } /************************************************** * Relation methods **************************************************/ /** * Tells whether an instance is entirely before the specified index. * * The index can be a DateTimeInterface object or another Period object. * * [--------------------) * [--------------------) * * @param Period|Datepoint|\DateTimeInterface|int|string $index a datepoint or a Period object */ public function isBefore($index): bool { if ($index instanceof self) { return $this->endDate < $index->startDate || ($this->endDate == $index->startDate && $this->boundaryType[1] !== $index->boundaryType[0]); } $datepoint = self::filterDatepoint($index); return $this->endDate < $datepoint || ($this->endDate == $datepoint && ')' === $this->boundaryType[1]); } /** * Tells whether the current instance end date meets the interval start date. * * [--------------------) * [--------------------) */ public function bordersOnStart(self $interval): bool { return $this->endDate == $interval->startDate && '][' !== $this->boundaryType[1].$interval->boundaryType[0]; } /** * Tells whether two intervals share the same start datepoint * and the same starting boundary type. * * [----------) * [--------------------) * * or * * [--------------------) * [---------) * * @param Period|Datepoint|\DateTimeInterface|int|string $index a datepoint or a Period object */ public function isStartedBy($index): bool { if ($index instanceof self) { return $this->startDate == $index->startDate && $this->boundaryType[0] === $index->boundaryType[0]; } $index = self::filterDatepoint($index); return $index == $this->startDate && '[' === $this->boundaryType[0]; } /** * Tells whether an instance is fully contained in the specified interval. * * [----------) * [--------------------) */ public function isDuring(self $interval): bool { return $interval->containsInterval($this); } /** * Tells whether an instance fully contains the specified index. * * The index can be a DateTimeInterface object or another Period object. * * @param Period|Datepoint|\DateTimeInterface|int|string $index a datepoint or a Period object */ public function contains($index): bool { if ($index instanceof self) { return $this->containsInterval($index); } return $this->containsDatepoint(self::filterDatepoint($index), $this->boundaryType); } /** * Tells whether an instance fully contains another instance. * * [--------------------) * [----------) */ private function containsInterval(self $interval): bool { if ($this->startDate < $interval->startDate && $this->endDate > $interval->endDate) { return true; } if ($this->startDate == $interval->startDate && $this->endDate == $interval->endDate) { return $this->boundaryType === $interval->boundaryType || '[]' === $this->boundaryType; } if ($this->startDate == $interval->startDate) { return ($this->boundaryType[0] === $interval->boundaryType[0] || '[' === $this->boundaryType[0]) && $this->containsDatepoint($this->startDate->add($interval->getDateInterval()), $this->boundaryType); } if ($this->endDate == $interval->endDate) { return ($this->boundaryType[1] === $interval->boundaryType[1] || ']' === $this->boundaryType[1]) && $this->containsDatepoint($this->endDate->sub($interval->getDateInterval()), $this->boundaryType); } return false; } /** * Tells whether an instance contains a date endpoint. * * [------|------------) */ private function containsDatepoint(DateTimeInterface $datepoint, string $boundaryType): bool { switch ($boundaryType) { case self::EXCLUDE_ALL: return $datepoint > $this->startDate && $datepoint < $this->endDate; case self::INCLUDE_ALL: return $datepoint >= $this->startDate && $datepoint <= $this->endDate; case self::EXCLUDE_START_INCLUDE_END: return $datepoint > $this->startDate && $datepoint <= $this->endDate; case self::INCLUDE_START_EXCLUDE_END: default: return $datepoint >= $this->startDate && $datepoint < $this->endDate; } } /** * Tells whether two intervals share the same datepoints. * * [--------------------) * [--------------------) */ public function equals(self $interval): bool { return $this->startDate == $interval->startDate && $this->endDate == $interval->endDate && $this->boundaryType === $interval->boundaryType; } /** * Tells whether two intervals share the same end datepoint * and the same ending boundary type. * * [----------) * [--------------------) * * or * * [--------------------) * [---------) * * @param Period|Datepoint|\DateTimeInterface|int|string $index a datepoint or a Period object */ public function isEndedBy($index): bool { if ($index instanceof self) { return $this->endDate == $index->endDate && $this->boundaryType[1] === $index->boundaryType[1]; } $index = self::filterDatepoint($index); return $index == $this->endDate && ']' === $this->boundaryType[1]; } /** * Tells whether the current instance start date meets the interval end date. * * [--------------------) * [--------------------) */ public function bordersOnEnd(self $interval): bool { return $interval->bordersOnStart($this); } /** * Tells whether an interval is entirely after the specified index. * The index can be a DateTimeInterface object or another Period object. * * [--------------------) * [--------------------) * * @param Period|Datepoint|\DateTimeInterface|int|string $index a datepoint or a Period object */ public function isAfter($index): bool { if ($index instanceof self) { return $index->isBefore($this); } $datepoint = self::filterDatepoint($index); return $this->startDate > $datepoint || ($this->startDate == $datepoint && '(' === $this->boundaryType[0]); } /** * Tells whether two intervals abuts. * * [--------------------) * [--------------------) * or * [--------------------) * [--------------------) */ public function abuts(self $interval): bool { return $this->bordersOnStart($interval) || $this->bordersOnEnd($interval); } /** * Tells whether two intervals overlaps. * * [--------------------) * [--------------------) */ public function overlaps(self $interval): bool { return !$this->abuts($interval) && $this->startDate < $interval->endDate && $this->endDate > $interval->startDate; } /************************************************** * Manipulating instance duration **************************************************/ /** * Returns the difference between two instances expressed in seconds. */ public function timeDurationDiff(self $interval): float { return $this->timeDuration() - $interval->timeDuration(); } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::timeDurationDiff() * * Returns the difference between two instances expressed in seconds. */ public function timestampIntervalDiff(self $interval): float { return $this->timeDurationDiff($interval); } /** * Returns the difference between two instances expressed with a DateInterval object. */ public function dateIntervalDiff(self $interval): DateInterval { return $this->endDate->diff($this->startDate->add($interval->dateInterval())); } /** * Allows iteration over a set of dates and times, * recurring at regular intervals, over the instance. * * @see http://php.net/manual/en/dateperiod.construct.php * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function dateRangeForward($duration, int $option = 0): DatePeriod { return new DatePeriod($this->startDate, self::filterDuration($duration), $this->endDate, $option); } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::dateRangeForward() * * @param Period|DateInterval|Duration|string|int $duration a Duration * * Allows iteration over a set of dates and times, * recurring at regular intervals, over the instance. * * @see http://php.net/manual/en/dateperiod.construct.php */ public function getDatePeriod($duration, int $option = 0): DatePeriod { return $this->dateRangeForward($duration, $option); } /** * Allows iteration over a set of dates and times, * recurring at regular intervals, over the instance backwards starting from * the instance ending date endpoint. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function dateRangeBackwards($duration, int $option = 0): iterable { $duration = self::filterDuration($duration); $date = $this->endDate; if ((bool) ($option & DatePeriod::EXCLUDE_START_DATE)) { $date = $this->endDate->sub($duration); } while ($date > $this->startDate) { yield $date; $date = $date->sub($duration); } } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::dateRangeBackwards() * * @param Period|DateInterval|Duration|string|int $duration a Duration * * Allows iteration over a set of dates and times, * recurring at regular intervals, over the instance backwards starting from * the instance ending date endpoint. */ public function getDatePeriodBackwards($duration, int $option = 0): iterable { return $this->dateRangeBackwards($duration, $option); } /** * Allows splitting an instance in smaller Period objects according to a given interval. * * The returned iterable Interval set is ordered so that: * <ul> * <li>The first returned object MUST share the starting datepoint of the parent object.</li> * <li>The last returned object MUST share the ending datepoint of the parent object.</li> * <li>The last returned object MUST have a duration equal or lesser than the submitted interval.</li> * <li>All returned objects except for the first one MUST start immediately after the previously returned object</li> * </ul> * * @param Period|DateInterval|Duration|string|int $duration a Duration * * @return iterable<Period> */ public function splitForward($duration): iterable { $duration = self::filterDuration($duration); /** @var DateTimeImmutable $startDate */ foreach ($this->dateRangeForward($duration) as $startDate) { $endDate = $startDate->add($duration); if ($endDate > $this->endDate) { $endDate = $this->endDate; } yield new self($startDate, $endDate, $this->boundaryType); } } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @see Period::splitForward() * * Allows splitting an instance in smaller Period objects according to a given interval. * * The returned iterable Interval set is ordered so that: * <ul> * <li>The first returned object MUST share the starting datepoint of the parent object.</li> * <li>The last returned object MUST share the ending datepoint of the parent object.</li> * <li>The last returned object MUST have a duration equal or lesser than the submitted interval.</li> * <li>All returned objects except for the first one MUST start immediately after the previously returned object</li> * </ul> * * @param Period|DateInterval|Duration|string|int $duration a Duration * * @return iterable<Period> */ public function split($duration): iterable { return $this->splitForward($duration); } /** * Allows splitting an instance in smaller Period objects according to a given interval. * * The returned iterable Period set is ordered so that: * <ul> * <li>The first returned object MUST share the ending datepoint of the parent object.</li> * <li>The last returned object MUST share the starting datepoint of the parent object.</li> * <li>The last returned object MUST have a duration equal or lesser than the submitted interval.</li> * <li>All returned objects except for the first one MUST end immediately before the previously returned object</li> * </ul> * * @param Period|DateInterval|Duration|string|int $duration a Duration * * @return iterable<Period> */ public function splitBackwards($duration): iterable { $endDate = $this->endDate; $duration = self::filterDuration($duration); do { $startDate = $endDate->sub($duration); if ($startDate < $this->startDate) { $startDate = $this->startDate; } yield new self($startDate, $endDate, $this->boundaryType); $endDate = $startDate; } while ($endDate > $this->startDate); } /************************************************** * Manipulation instance endpoints and bounds **************************************************/ /** * Returns the computed intersection between two instances as a new instance. * * [--------------------) * ∩ * [----------) * = * [----) * * @throws Exception If both objects do not overlaps */ public function intersect(self $interval): self { if (!$this->overlaps($interval)) { throw new Exception('Both '.self::class.' objects should overlaps'); } $startDate = $this->startDate; $endDate = $this->endDate; $boundaryType = $this->boundaryType; if ($interval->startDate > $this->startDate) { $boundaryType[0] = $interval->boundaryType[0]; $startDate = $interval->startDate; } if ($interval->endDate < $this->endDate) { $boundaryType[1] = $interval->boundaryType[1]; $endDate = $interval->endDate; } $intersect = new self($startDate, $endDate, $boundaryType); if ($intersect->equals($this)) { return $this; } return $intersect; } /** * Returns the computed difference between two overlapping instances as * an array containing Period objects or the null value. * * The array will always contains 2 elements: * * <ul> * <li>an NULL filled array if both objects have the same datepoints</li> * <li>one Period object and NULL if both objects share one datepoint</li> * <li>two Period objects if both objects share no datepoint</li> * </ul> * * [--------------------) * \ * [-----------) * = * [--------------) + [-----) * * @return array<null|Period> */ public function diff(self $interval): array { if ($interval->equals($this)) { return [null, null]; } $intersect = $this->intersect($interval); $merge = $this->merge($interval); if ($merge->startDate == $intersect->startDate) { $first = ')' === $intersect->boundaryType[1] ? '[' : '('; $boundary = $first.$merge->boundaryType[1]; return [$merge->startingOn($intersect->endDate)->boundedBy($boundary), null]; } if ($merge->endDate == $intersect->endDate) { $last = '(' === $intersect->boundaryType[0] ? ']' : ')'; $boundary = $merge->boundaryType[0].$last; return [$merge->endingOn($intersect->startDate)->boundedBy($boundary), null]; } $last = '(' === $intersect->boundaryType[0] ? ']' : ')'; $lastBoundary = $merge->boundaryType[0].$last; $first = ')' === $intersect->boundaryType[1] ? '[' : '('; $firstBoundary = $first.$merge->boundaryType[1]; return [ $merge->endingOn($intersect->startDate)->boundedBy($lastBoundary), $merge->startingOn($intersect->endDate)->boundedBy($firstBoundary), ]; } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.9.0 This method will be removed in the next major point release * @see Period::subtract */ public function substract(self $interval): Sequence { return $this->subtract($interval); } /** * Returns the difference set operation between two intervals as a Sequence. * The Sequence can contain from 0 to 2 Periods depending on the result of * the operation. * * [--------------------) * - * [-----------) * = * [--------------) */ public function subtract(self $interval): Sequence { if (!$this->overlaps($interval)) { return new Sequence($this); } $filter = function ($item): bool { return null !== $item && $this->overlaps($item); }; return new Sequence(...array_filter($this->diff($interval), $filter)); } /** * Returns the computed gap between two instances as a new instance. * * [--------------------) * + * [----------) * = * [---) * * @throws Exception If both instance overlaps */ public function gap(self $interval): self { if ($this->overlaps($interval)) { throw new Exception('Both '.self::class.' objects must not overlaps'); } $bounds = $this->isEndIncluded() ? '(' : '['; $bounds .= $interval->isStartIncluded() ? ')' : ']'; if ($interval->startDate > $this->startDate) { return new self($this->endDate, $interval->startDate, $bounds); } return new self($interval->endDate, $this->startDate, $this->boundaryType); } /** * Merges one or more instances to return a new instance. * The resulting instance represents the largest duration possible. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified new datepoints. * * [--------------------) * + * [----------) * = * [--------------------------) * * * @param Period ...$intervals */ public function merge(self ...$intervals): self { $carry = $this; foreach ($intervals as $period) { if ($carry->startDate > $period->startDate) { $carry = new self( $period->startDate, $carry->endDate, $period->boundaryType[0].$carry->boundaryType[1] ); } if ($carry->endDate < $period->endDate) { $carry = new self( $carry->startDate, $period->endDate, $carry->boundaryType[0].$period->boundaryType[1] ); } } return $carry; } /************************************************** * Mutation methods **************************************************/ /** * Returns an instance with the specified starting date endpoint. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified starting date endpoint. * * @param Datepoint|DateTimeInterface|int|string $startDate the new starting date endpoint */ public function startingOn($startDate): self { $startDate = self::filterDatepoint($startDate); if ($startDate == $this->startDate) { return $this; } return new self($startDate, $this->endDate, $this->boundaryType); } /** * Returns an instance with the specified ending date endpoint. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified ending date endpoint. * * @param Datepoint|DateTimeInterface|int|string $endDate the new ending date endpoint */ public function endingOn($endDate): self { $endDate = self::filterDatepoint($endDate); if ($endDate == $this->endDate) { return $this; } return new self($this->startDate, $endDate, $this->boundaryType); } /** * Returns an instance with the specified boundary type. * * This method MUST retain the state of the current instance, and return * an instance with the specified range type. */ public function boundedBy(string $bounds): self { if ($bounds === $this->boundaryType) { return $this; } return new self($this->startDate, $this->endDate, $bounds); } /** * DEPRECATION WARNING! This method will be removed in the next major point release. * * @deprecated 4.12.0 This method will be removed in the next major point release * @see Period::boundedBy() * * Returns an instance with the specified boundary type. * * This method MUST retain the state of the current instance, and return * an instance with the specified range type. */ public function withBoundaryType(string $boundaryType): self { return $this->boundedBy($boundaryType); } /** * Returns a new instance with a new ending date endpoint. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified ending date endpoint. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function withDurationAfterStart($duration): self { return $this->endingOn($this->startDate->add(self::filterDuration($duration))); } /** * Returns a new instance with a new starting date endpoint. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified starting date endpoint. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function withDurationBeforeEnd($duration): self { return $this->startingOn($this->endDate->sub(self::filterDuration($duration))); } /** * Returns a new instance with a new starting datepoint * moved forward or backward by the given interval. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified starting date endpoint. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function moveStartDate($duration): self { return $this->startingOn($this->startDate->add(self::filterDuration($duration))); } /** * Returns a new instance with a new ending datepoint * moved forward or backward by the given interval. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified ending date endpoint. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function moveEndDate($duration): self { return $this->endingOn($this->endDate->add(self::filterDuration($duration))); } /** * Returns a new instance where the date endpoints * are moved forwards or backward simultaneously by the given DateInterval. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified new date endpoints. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function move($duration): self { $duration = self::filterDuration($duration); $interval = new self($this->startDate->add($duration), $this->endDate->add($duration), $this->boundaryType); if ($this->equals($interval)) { return $this; } return $interval; } /** * Returns an instance where the given DateInterval is simultaneously * subtracted from the starting date endpoint and added to the ending date endpoint. * * Depending on the duration value, the resulting instance duration will be expanded or shrinked. * * This method MUST retain the state of the current instance, and return * an instance that contains the specified new date endpoints. * * @param Period|DateInterval|Duration|string|int $duration a Duration */ public function expand($duration): self { $duration = self::filterDuration($duration); $interval = new self($this->startDate->sub($duration), $this->endDate->add($duration), $this->boundaryType); if ($this->equals($interval)) { return $this; } return $interval; } }
| ver. 1.4 |
Github
|
.
| PHP 5.4.45 | Generation time: 0 |
proxy
|
phpinfo
|
Settings