1010
1111namespace Zee \DateRange ;
1212
13- use DateTimeImmutable ;
1413use DateTimeInterface ;
1514use 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