Skip to content

Commit cfa2d22

Browse files
authored
Redo library (#4)
* 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
1 parent 35fe2c9 commit cfa2d22

13 files changed

+805
-671
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,16 @@ Security - in case of vulnerabilities.
1818

1919
_TBD_
2020

21+
## [0.1.1] 2017-11-17
22+
23+
### Changed
24+
- Implement `State` pattern to control ranges objects.
25+
- Change JSON representation to array instead of string in previous version.
26+
27+
### Changed
28+
- Remove mutable object, leave only immutable.
29+
- Remove implementation of Serializable interface.
30+
2131
## [0.0.1] 2017-11-16
2232

2333
Initial release.

src/DateRange.php

Lines changed: 59 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -10,44 +10,48 @@
1010

1111
namespace Zee\DateRange;
1212

13-
use DateTimeImmutable;
1413
use DateTimeInterface;
1514
use JsonSerializable;
16-
use Serializable;
15+
use Zee\DateRange\States\RangeState;
16+
use Zee\DateRange\States\UndefinedRange;
1717

1818
/**
19-
* Date range implementation.
19+
* Implementation of date range value object.
2020
*/
21-
final class DateRange implements DateRangeInterface, Serializable, JsonSerializable
21+
final class DateRange implements DateRangeInterface, JsonSerializable
2222
{
2323
/**
24-
* @var DateTimeInterface
24+
* @var RangeState
2525
*/
26-
private $begin;
26+
private $state;
2727

2828
/**
29-
* @var DateTimeInterface
29+
* @param DateTimeInterface|null $startTime
30+
* @param DateTimeInterface|null $endTime
3031
*/
31-
private $end;
32-
33-
/**
34-
* @param DateTimeInterface $begin
35-
* @param DateTimeInterface $end
36-
*/
37-
public function __construct(DateTimeInterface $begin, DateTimeInterface $end = null)
32+
public function __construct(DateTimeInterface $startTime = null, DateTimeInterface $endTime = null)
3833
{
39-
$this->guardDateSequence($begin, $end);
34+
$state = new UndefinedRange();
35+
36+
if (isset($startTime)) {
37+
$state = $state->setStartTime($startTime);
38+
}
39+
40+
if (isset($endTime)) {
41+
$state = $state->setEndTime($endTime);
42+
}
4043

41-
$this->begin = $begin;
42-
$this->end = $end;
44+
$this->state = $state;
4345
}
4446

4547
/**
48+
* Returns string representation of range.
49+
*
4650
* {@inheritdoc}
4751
*/
48-
public function __toString()
52+
public function __toString(): string
4953
{
50-
return $this->serialize();
54+
return (string) $this->state;
5155
}
5256

5357
/**
@@ -56,141 +60,110 @@ public function __toString()
5660
public function __debugInfo()
5761
{
5862
return [
59-
'begin' => $this->getBegin()->format('c'),
60-
'end' => $this->isFinite()
61-
? $this->getEnd()->format('c')
62-
: '-',
63+
'startTime' => $this->state->hasStartTime()
64+
? $this->state->getStartTime()
65+
: null,
66+
'endTime' => $this->state->hasEndTime()
67+
? $this->state->getEndTime()
68+
: null,
6369
];
6470
}
6571

6672
/**
73+
* Returns value ready to be encoded as JSON.
74+
*
75+
* The ISO-8601 range format is used for times.
76+
*
6777
* {@inheritdoc}
6878
*/
69-
public function getBegin(): DateTimeInterface
79+
public function jsonSerialize(): array
7080
{
71-
return $this->begin;
81+
return $this->state->jsonSerialize();
7282
}
7383

7484
/**
7585
* {@inheritdoc}
7686
*/
77-
public function getEnd(): DateTimeInterface
87+
public function hasStartTime(): bool
7888
{
79-
return $this->end;
89+
return $this->state->hasStartTime();
8090
}
8191

8292
/**
8393
* {@inheritdoc}
8494
*/
85-
public function isFinite(): bool
95+
public function hasEndTime(): bool
8696
{
87-
return $this->end instanceof DateTimeInterface;
97+
return $this->state->hasEndTime();
8898
}
8999

90100
/**
91101
* {@inheritdoc}
92102
*/
93-
public function isBeginAt(DateTimeInterface $time): bool
103+
public function getStartTime(): DateTimeInterface
94104
{
95-
return $this->begin->getTimestamp() === $time->getTimestamp();
105+
return $this->state->getStartTime();
96106
}
97107

98108
/**
99109
* {@inheritdoc}
100110
*/
101-
public function isEndAt(DateTimeInterface $time): bool
111+
public function getEndTime(): DateTimeInterface
102112
{
103-
return $this->end->getTimestamp() === $time->getTimestamp();
113+
return $this->state->getEndTime();
104114
}
105115

106116
/**
107117
* {@inheritdoc}
108118
*/
109-
public function isStarted(): bool
119+
public function setStartTime(DateTimeInterface $time): DateRangeInterface
110120
{
111-
return $this->begin <= new DateTimeImmutable();
112-
}
121+
$clone = clone $this;
122+
$clone->state = $clone->state->setStartTime($time);
113123

114-
/**
115-
* {@inheritdoc}
116-
*/
117-
public function isEnded(): bool
118-
{
119-
return $this->isFinite() && $this->end <= new DateTimeImmutable();
124+
return $clone;
120125
}
121126

122127
/**
123128
* {@inheritdoc}
124129
*/
125-
public function beginAt(DateTimeInterface $time): DateRangeInterface
130+
public function setEndTime(DateTimeInterface $time): DateRangeInterface
126131
{
127-
$this->guardDateSequence($time, $this->end);
132+
$clone = clone $this;
133+
$clone->state = $clone->state->setEndTime($time);
128134

129-
$this->begin = $time;
130-
131-
return $this;
135+
return $clone;
132136
}
133137

134138
/**
135139
* {@inheritdoc}
136140
*/
137-
public function endAt(DateTimeInterface $time): DateRangeInterface
141+
public function isStartAt(DateTimeInterface $time): bool
138142
{
139-
$this->guardDateSequence($this->begin, $time);
140-
141-
$this->end = $time;
142-
143-
return $this;
143+
return $this->state->isStartAt($time);
144144
}
145145

146146
/**
147147
* {@inheritdoc}
148148
*/
149-
public function serialize()
149+
public function isEndAt(DateTimeInterface $time): bool
150150
{
151-
return sprintf(
152-
'%s/%s',
153-
$this->getBegin()->format('c'),
154-
$this->isFinite()
155-
? $this->getEnd()->format('c')
156-
: '-'
157-
);
151+
return $this->state->isEndAt($time);
158152
}
159153

160154
/**
161155
* {@inheritdoc}
162156
*/
163-
public function unserialize($serialized)
157+
public function isStarted(): bool
164158
{
165-
$times = explode('/', $serialized, 2);
166-
167-
if (count($times) !== 2) {
168-
throw new DateRangeException('Invalid range format');
169-
}
170-
171-
$this->begin = new DateTimeImmutable($times[0]);
172-
173-
if ($times[1] !== '-') {
174-
$this->end = new DateTimeImmutable($times[1]);
175-
}
159+
return $this->state->isStarted();
176160
}
177161

178162
/**
179163
* {@inheritdoc}
180164
*/
181-
public function jsonSerialize()
182-
{
183-
return $this->serialize();
184-
}
185-
186-
/**
187-
* @param DateTimeInterface $begin
188-
* @param DateTimeInterface|null $end
189-
*/
190-
private function guardDateSequence(DateTimeInterface $begin, DateTimeInterface $end = null)
165+
public function isEnded(): bool
191166
{
192-
if ($end && $end <= $begin) {
193-
throw new DateRangeException('Invalid end, must be after begin');
194-
}
167+
return $this->state->isEnded();
195168
}
196169
}

0 commit comments

Comments
 (0)