Skip to content

Commit

Permalink
Redo library (#4)
Browse files Browse the repository at this point in the history
* Redo DateRange implementation

Implement State pattern to control ranges objects.
Remove mutable object, leave only immutable.
Change serialization format.
Remove implementation of Serializable interface.

* Update change log
  • Loading branch information
slavcodev authored Nov 17, 2017
1 parent 35fe2c9 commit cfa2d22
Show file tree
Hide file tree
Showing 13 changed files with 805 additions and 671 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ Security - in case of vulnerabilities.

_TBD_

## [0.1.1] 2017-11-17

### Changed
- Implement `State` pattern to control ranges objects.
- Change JSON representation to array instead of string in previous version.

### Changed
- Remove mutable object, leave only immutable.
- Remove implementation of Serializable interface.

## [0.0.1] 2017-11-16

Initial release.
145 changes: 59 additions & 86 deletions src/DateRange.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,44 +10,48 @@

namespace Zee\DateRange;

use DateTimeImmutable;
use DateTimeInterface;
use JsonSerializable;
use Serializable;
use Zee\DateRange\States\RangeState;
use Zee\DateRange\States\UndefinedRange;

/**
* Date range implementation.
* Implementation of date range value object.
*/
final class DateRange implements DateRangeInterface, Serializable, JsonSerializable
final class DateRange implements DateRangeInterface, JsonSerializable
{
/**
* @var DateTimeInterface
* @var RangeState
*/
private $begin;
private $state;

/**
* @var DateTimeInterface
* @param DateTimeInterface|null $startTime
* @param DateTimeInterface|null $endTime
*/
private $end;

/**
* @param DateTimeInterface $begin
* @param DateTimeInterface $end
*/
public function __construct(DateTimeInterface $begin, DateTimeInterface $end = null)
public function __construct(DateTimeInterface $startTime = null, DateTimeInterface $endTime = null)
{
$this->guardDateSequence($begin, $end);
$state = new UndefinedRange();

if (isset($startTime)) {
$state = $state->setStartTime($startTime);
}

if (isset($endTime)) {
$state = $state->setEndTime($endTime);
}

$this->begin = $begin;
$this->end = $end;
$this->state = $state;
}

/**
* Returns string representation of range.
*
* {@inheritdoc}
*/
public function __toString()
public function __toString(): string
{
return $this->serialize();
return (string) $this->state;
}

/**
Expand All @@ -56,141 +60,110 @@ public function __toString()
public function __debugInfo()
{
return [
'begin' => $this->getBegin()->format('c'),
'end' => $this->isFinite()
? $this->getEnd()->format('c')
: '-',
'startTime' => $this->state->hasStartTime()
? $this->state->getStartTime()
: null,
'endTime' => $this->state->hasEndTime()
? $this->state->getEndTime()
: null,
];
}

/**
* Returns value ready to be encoded as JSON.
*
* The ISO-8601 range format is used for times.
*
* {@inheritdoc}
*/
public function getBegin(): DateTimeInterface
public function jsonSerialize(): array
{
return $this->begin;
return $this->state->jsonSerialize();
}

/**
* {@inheritdoc}
*/
public function getEnd(): DateTimeInterface
public function hasStartTime(): bool
{
return $this->end;
return $this->state->hasStartTime();
}

/**
* {@inheritdoc}
*/
public function isFinite(): bool
public function hasEndTime(): bool
{
return $this->end instanceof DateTimeInterface;
return $this->state->hasEndTime();
}

/**
* {@inheritdoc}
*/
public function isBeginAt(DateTimeInterface $time): bool
public function getStartTime(): DateTimeInterface
{
return $this->begin->getTimestamp() === $time->getTimestamp();
return $this->state->getStartTime();
}

/**
* {@inheritdoc}
*/
public function isEndAt(DateTimeInterface $time): bool
public function getEndTime(): DateTimeInterface
{
return $this->end->getTimestamp() === $time->getTimestamp();
return $this->state->getEndTime();
}

/**
* {@inheritdoc}
*/
public function isStarted(): bool
public function setStartTime(DateTimeInterface $time): DateRangeInterface
{
return $this->begin <= new DateTimeImmutable();
}
$clone = clone $this;
$clone->state = $clone->state->setStartTime($time);

/**
* {@inheritdoc}
*/
public function isEnded(): bool
{
return $this->isFinite() && $this->end <= new DateTimeImmutable();
return $clone;
}

/**
* {@inheritdoc}
*/
public function beginAt(DateTimeInterface $time): DateRangeInterface
public function setEndTime(DateTimeInterface $time): DateRangeInterface
{
$this->guardDateSequence($time, $this->end);
$clone = clone $this;
$clone->state = $clone->state->setEndTime($time);

$this->begin = $time;

return $this;
return $clone;
}

/**
* {@inheritdoc}
*/
public function endAt(DateTimeInterface $time): DateRangeInterface
public function isStartAt(DateTimeInterface $time): bool
{
$this->guardDateSequence($this->begin, $time);

$this->end = $time;

return $this;
return $this->state->isStartAt($time);
}

/**
* {@inheritdoc}
*/
public function serialize()
public function isEndAt(DateTimeInterface $time): bool
{
return sprintf(
'%s/%s',
$this->getBegin()->format('c'),
$this->isFinite()
? $this->getEnd()->format('c')
: '-'
);
return $this->state->isEndAt($time);
}

/**
* {@inheritdoc}
*/
public function unserialize($serialized)
public function isStarted(): bool
{
$times = explode('/', $serialized, 2);

if (count($times) !== 2) {
throw new DateRangeException('Invalid range format');
}

$this->begin = new DateTimeImmutable($times[0]);

if ($times[1] !== '-') {
$this->end = new DateTimeImmutable($times[1]);
}
return $this->state->isStarted();
}

/**
* {@inheritdoc}
*/
public function jsonSerialize()
{
return $this->serialize();
}

/**
* @param DateTimeInterface $begin
* @param DateTimeInterface|null $end
*/
private function guardDateSequence(DateTimeInterface $begin, DateTimeInterface $end = null)
public function isEnded(): bool
{
if ($end && $end <= $begin) {
throw new DateRangeException('Invalid end, must be after begin');
}
return $this->state->isEnded();
}
}
Loading

0 comments on commit cfa2d22

Please sign in to comment.