Skip to content

Commit

Permalink
Merge pull request #57 from hughgrigg/iteration-limit
Browse files Browse the repository at this point in the history
Limit business time iterations
  • Loading branch information
hughgrigg authored Jul 27, 2019
2 parents 694157e + 7887857 commit 6340418
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 30 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.PHONY: test
test: src tests vendor/autoload.php
./vendor/phpmd/phpmd/src/bin/phpmd src text \
controversial,design,naming,unusedcode
controversial,naming,unusedcode
./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=PSR2 --colors src
./vendor/phpunit/phpunit/phpunit

Expand All @@ -13,7 +13,7 @@ coverage: src tests vendor/autoload.php
mkdir -p build
rm -rf build/*
./vendor/phpmd/phpmd/src/bin/phpmd src text \
controversial,design,naming,unusedcode \
controversial,naming,unusedcode \
--reportfile ./build/phpmd.xml
./vendor/squizlabs/php_codesniffer/bin/phpcs --standard=PSR2 --colors src \
--report-file=./build/phpcs.xml
Expand Down
76 changes: 48 additions & 28 deletions src/BusinessTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ class BusinessTime extends Carbon
/** @var Interval */
private $precision;

/** @var int */
private $iterationLimit = LimitedIterator::DEFAULT_ITERATION_LIMIT;

/**
* Is it business time?
*
Expand All @@ -54,11 +57,15 @@ public function isBusinessDay(): bool
// Iterate from the beginning of the day until we hit business time.
$time = $this->copy()->startOfDay();
$end = $this->copy()->endOfDay();

$limit = new LimitedIterator($this->iterationLimit);
while ($time->lt($end)) {
if ($time->isBusinessTime()) {
return true;
}
$time = $time->add($this->precision());

$limit->next();
}

return false;
Expand All @@ -69,8 +76,6 @@ public function isBusinessDay(): bool
*
* @see AddBusinessDaysTest
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function addBusinessDay(): self
Expand All @@ -88,8 +93,6 @@ public function addBusinessDay(): self
*
* @param float $businessDaysToAdd
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function addBusinessDays(float $businessDaysToAdd): self
Expand All @@ -113,12 +116,15 @@ public function addBusinessDays(float $businessDaysToAdd): self
$decrement = $this->precision()->inDays()
/ $this->lengthOfBusinessDay()->inDays();

$limit = new LimitedIterator($this->iterationLimit);
while ($businessDaysToAdd > 0) {
/* @scrutinizer ignore-call */
if ($next->isBusinessTime()) {
$businessDaysToAdd -= $decrement;
}
$next = $next->add($this->precision());

$limit->next();
}

// Ensure we always end on a business day.
Expand All @@ -134,8 +140,6 @@ public function addBusinessDays(float $businessDaysToAdd): self
*
* @see SubBusinessDaysTest
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function subBusinessDay(): self
Expand All @@ -150,8 +154,6 @@ public function subBusinessDay(): self
*
* @param float $businessDaysToSub
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function subBusinessDays(float $businessDaysToSub): self
Expand All @@ -174,11 +176,14 @@ public function subBusinessDays(float $businessDaysToSub): self
$decrement = $this->precision()->inDays()
/ $this->lengthOfBusinessDay()->inDays();

$limit = new LimitedIterator($this->iterationLimit);
while ($businessDaysToSub > 0) {
$prev = $prev->sub($this->precision());
if ($prev->isBusinessTime()) {
$businessDaysToSub -= $decrement;
}

$limit->next();
}

// Ensure we always end on a business day.
Expand All @@ -194,8 +199,6 @@ public function subBusinessDays(float $businessDaysToSub): self
*
* @see AddBusinessHoursTest
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function addBusinessHour(): self
Expand All @@ -210,8 +213,6 @@ public function addBusinessHour(): self
*
* @see AddBusinessHoursTest
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function addBusinessHours(float $businessHoursToAdd): self
Expand All @@ -223,12 +224,16 @@ public function addBusinessHours(float $businessHoursToAdd): self
/** @var BusinessTime $next */
$next = $this->copy();
$decrement = $this->precision()->inHours();

$limit = new LimitedIterator($this->iterationLimit);
while ($businessHoursToAdd > 0) {
/* @scrutinizer ignore-call */
if ($next->isBusinessTime()) {
$businessHoursToAdd -= $decrement;
}
$next = $next->add($this->precision());

$limit->next();
}

return $next;
Expand All @@ -239,8 +244,6 @@ public function addBusinessHours(float $businessHoursToAdd): self
*
* @see SubBusinessHoursTest
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function subBusinessHour(): self
Expand All @@ -255,8 +258,6 @@ public function subBusinessHour(): self
*
* @param float $businessHoursToSub
*
* @throws \InvalidArgumentException
*
* @return BusinessTime
*/
public function subBusinessHours(float $businessHoursToSub): self
Expand All @@ -267,11 +268,15 @@ public function subBusinessHours(float $businessHoursToSub): self

$prev = $this->copy();
$decrement = $this->precision()->inHours();

$limit = new LimitedIterator($this->iterationLimit);
while ($businessHoursToSub > 0) {
$prev = $prev->sub($this->precision());
if ($prev->isBusinessTime()) {
$businessHoursToSub -= $decrement;
}

$limit->next();
}

return $prev;
Expand All @@ -285,8 +290,6 @@ public function subBusinessHours(float $businessHoursToSub): self
* @param DateTimeInterface $time
* @param bool $absolute
*
* @throws \InvalidArgumentException
*
* @return int
*/
public function diffInBusinessDays(
Expand Down Expand Up @@ -322,8 +325,6 @@ public function diffInBusinessHours(
* @param DateTimeInterface $time
* @param bool $absolute
*
* @throws InvalidArgumentException
*
* @return float
*/
public function diffInPartialBusinessDays(
Expand Down Expand Up @@ -401,8 +402,12 @@ public function startOfBusinessDay(): self
{
// Iterate from the beginning of the day until we hit business time.
$start = $this->copy()->startOfDay();

$limit = new LimitedIterator($this->iterationLimit);
while (!$start->isBusinessTime()) {
$start = $start->add($this->precision());

$limit->next();
}

return $start;
Expand All @@ -417,8 +422,12 @@ public function endOfBusinessDay(): self
{
// Iterate back from the end of the day until we hit business time.
$end = $this->copy()->endOfDay();

$limit = new LimitedIterator($this->iterationLimit);
while (!$end->isBusinessTime()) {
$end = $end->sub($this->precision());

$limit->next();
}

// Add a second because we've iterated from 23:59:59.
Expand Down Expand Up @@ -523,8 +532,6 @@ public function ceilToPrecision(DateInterval $precision = null): self
}

/**
* @throws InvalidArgumentException
*
* @return Interval
*/
public function lengthOfBusinessDay(): Interval
Expand All @@ -541,8 +548,6 @@ public function lengthOfBusinessDay(): Interval
/**
* @param DateInterval $length
*
* @throws InvalidArgumentException
*
* @return BusinessTime
*/
public function setLengthOfBusinessDay(DateInterval $length): self
Expand Down Expand Up @@ -571,8 +576,6 @@ public function setLengthOfBusinessDay(DateInterval $length): self
/**
* @param DateTime $typicalDay
*
* @throws InvalidArgumentException
*
* @return BusinessTime
*/
public function determineLengthOfBusinessDay(
Expand Down Expand Up @@ -656,8 +659,6 @@ public function precision(): Interval
*
* @param DateInterval $precision
*
* @throws InvalidArgumentException
*
* @return BusinessTime
*/
public function setPrecision(DateInterval $precision): self
Expand Down Expand Up @@ -692,6 +693,21 @@ public static function fromDti(DateTimeInterface $dti): self
->setTimestamp($dti->getTimestamp());
}

/**
* Set the maximum number of loop iterations when doing business time
* operations.
*
* @param int $iterationLimit
*
* @return BusinessTime
*/
public function setIterationLimit(int $iterationLimit): self
{
$this->iterationLimit = $iterationLimit;

return $this;
}

/**
* Difference in business time measured in units of the current precision.
*
Expand Down Expand Up @@ -729,12 +745,16 @@ private function diffInBusinessTime(
/** @var BusinessTime $next */
/** @scrutinizer ignore-call */
$next = $start->copy();

$limit = new LimitedIterator($this->iterationLimit);
while ($next < $end) {
/* @scrutinizer ignore-call */
if ($next->isBusinessTime()) {
$diff++;
}
$next = $next->add($this->precision());

$limit->next();
}

return $diff * $sign;
Expand Down
16 changes: 16 additions & 0 deletions src/BusinessTimeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ class BusinessTimeFactory
/** @var Interval */
private $precision;

/** @var int */
private $iterationLimit = LimitedIterator::DEFAULT_ITERATION_LIMIT;

/**
* @param Interval|null $precision
* @param BusinessTimeConstraint ...$constraints
Expand All @@ -42,6 +45,7 @@ public function make(string $time): BusinessTime
$businessTime = new BusinessTime($time);
$businessTime->setBusinessTimeConstraints(...$this->constraints);
$businessTime->setPrecision($this->precision);
$businessTime->setIterationLimit($this->iterationLimit);

return $businessTime;
}
Expand Down Expand Up @@ -80,4 +84,16 @@ public function setPrecision(Interval $precision): self

return $this;
}

/**
* @param int $iterationLimit
*
* @return BusinessTimeFactory
*/
public function setIterationLimit(int $iterationLimit): self
{
$this->iterationLimit = $iterationLimit;

return $this;
}
}
Loading

0 comments on commit 6340418

Please sign in to comment.