Skip to content

Commit 58e87b9

Browse files
committed
Add duration method to DateRange; Add exception if "to" value is lower than "from" value
1 parent 093e652 commit 58e87b9

File tree

4 files changed

+140
-39
lines changed

4 files changed

+140
-39
lines changed

README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ print $dateRange->getTo()?->format('Y-m-d H:i:s (e)');
145145
146146
* <sup>1)</sup> - excluding the given one
147147
* <sup>2)</sup> - including the given one
148-
*
148+
149149
#### Time is less than parser (`<to`)
150150
151151
* Imagine that now is the time: `2023-07-07 12:34:56`
@@ -197,15 +197,17 @@ print $dateRange->getTo()?->format('Y-m-d H:i:s (e)');
197197
198198
### Class `DateParser`
199199
200-
| method | description | type |
201-
|-------------------------------------------------------------------------------|--------------------------------------------------------|---------------------------|
202-
| <nobr>`->formatFrom(string $format, DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the formatted "from" date. | `string` |
203-
| <nobr>`->formatTo(string $format, DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the formatted "to" date. | `string` |
204-
| <nobr>`->getDateRange()`</nobr> | Returns the range as `DateRange` class. | `DateRange` |
205-
| <nobr>`->getFrom(DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the "from" date as `DateTime` object. | `DateTime\|null` |
206-
| <nobr>`->getTo(DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the "to" date as `DateTime` object. | `DateTime\|null` |
207-
| <nobr>`->getFromImmutable(DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the "from" date as `DateTimeImmutable` object. | `DateTimeImmutable\|null` |
208-
| <nobr>`->getToImmutable(DateTimeZone $dateTimeZoneOutput)`</nobr> | Returns the "to" date as `DateTimeImmutable` object. | `DateTimeImmutable\|null` |
200+
| method | description | type |
201+
|----------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------|---------------------------|
202+
| <nobr>`->getDateRange(DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the range as `DateRange` class. | `DateRange` |
203+
| <nobr>`->formatFrom(string $format, DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the formatted "from" date. | `string` |
204+
| <nobr>`->formatTo(string $format, DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the formatted "to" date. | `string` |
205+
| <nobr>`->getFrom(DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the "from" date as `DateTime` object. | `DateTime\|null` |
206+
| <nobr>`->getTo(DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the "to" date as `DateTime` object. | `DateTime\|null` |
207+
| <nobr>`->getFromImmutable(DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the "from" date as `DateTimeImmutable` object. | `DateTimeImmutable\|null` |
208+
| <nobr>`->getToImmutable(DateTimeZone\|string $dateTimeZone = null)`</nobr> | Returns the "to" date as `DateTimeImmutable` object. | `DateTimeImmutable\|null` |
209+
| <nobr>`->getDuration()`</nobr> | Returns the duration from "from" to "to" in seconds. | `int\|null` |
210+
| <nobr>`->getDurationWithOwn()`</nobr> | Returns the duration from "from" to "to" in seconds (including the first second). | `int\|null` |
209211
210212
## Installation
211213
@@ -231,32 +233,32 @@ vendor/bin/php-date-parser pdt --timezone-input=America/New_York --timezone-outp
231233
232234
```text
233235
234-
Given date time range: "<2023-07-01" (America/New_York > Europe/Berlin)
236+
Given date time range: "2023-07-01" (America/New_York > Europe/Berlin)
235237
236238
+----------------------------------------------------------+------------------+
237239
| Value | Given |
238240
+----------------------------------------------------------+------------------+
239-
| Given date time range (America/New_York > Europe/Berlin) | <2023-07-01 |
241+
| Given date time range (America/New_York > Europe/Berlin) | 2023-07-01 |
240242
| Timezone (input) | America/New_York |
241243
| Timezone (output) | Europe/Berlin |
242244
+----------------------------------------------------------+------------------+
243245
244-
Parsed from given string (input):
246+
Parsed from given input string (duration: 86399 seconds):
245247
246248
+------+-------------+---------------------+---------------------+
247249
| Type | Format | UTC | America/New York |
248250
+------+-------------+---------------------+---------------------+
249-
| From | Y-m-d H:i:s | n/a | n/a |
250-
| To | Y-m-d H:i:s | 2023-07-01 03:59:59 | 2023-06-30 23:59:59 |
251+
| From | Y-m-d H:i:s | 2023-07-01 04:00:00 | 2023-07-01 00:00:00 |
252+
| To | Y-m-d H:i:s | 2023-07-02 03:59:59 | 2023-07-01 23:59:59 |
251253
+------+-------------+---------------------+---------------------+
252254
253255
Parsed output:
254256
255257
+------+-------------+---------------------+---------------------+
256258
| Type | Format | UTC | Europe/Berlin |
257259
+------+-------------+---------------------+---------------------+
258-
| From | Y-m-d H:i:s | n/a | n/a |
259-
| To | Y-m-d H:i:s | 2023-07-01 03:59:59 | 2023-07-01 05:59:59 |
260+
| From | Y-m-d H:i:s | 2023-07-01 04:00:00 | 2023-07-01 06:00:00 |
261+
| To | Y-m-d H:i:s | 2023-07-02 03:59:59 | 2023-07-02 05:59:59 |
260262
+------+-------------+---------------------+---------------------+
261263
262264
```

src/Command/ParserCommand.php

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,20 @@ public function execute(string $timezoneInput, string $timezoneOutput): int
227227

228228
$dateParser = (new DateParser($dateTimeRange, $timezoneInput));
229229

230+
$duration = $dateParser->getDurationWithOwn();
231+
232+
$messageInput = match (true) {
233+
is_null($duration) => 'Parsed from given input string (duration: infinite)',
234+
default => sprintf('Parsed from given input string (duration: %d seconds)', $duration),
235+
};
236+
$messageOutput = match (true) {
237+
is_null($duration) => 'Parsed output (duration: infinite)',
238+
default => sprintf('Parsed output (duration: %d seconds)', $duration),
239+
};
240+
230241
$this->printGivenDateTimeRange($dateTimeRange, $timezoneInput, $timezoneOutput);
231-
$this->printData($dateParser, $timezoneInput, 'Parsed from given string (input)');
232-
$this->printData($dateParser, $timezoneOutput, 'Parsed output');
242+
$this->printData($dateParser, $timezoneInput, $messageInput);
243+
$this->printData($dateParser, $timezoneOutput, $messageOutput);
233244
$this->writer->write(PHP_EOL);
234245

235246
return self::SUCCESS;

src/DateParser.php

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use DateTime;
1717
use DateTimeImmutable;
1818
use DateTimeZone;
19+
use Exception;
1920
use Ixnode\PhpDateParser\Base\BaseDateParser;
2021
use Ixnode\PhpDateParser\Constants\Timezones;
2122
use Ixnode\PhpDateParser\Tests\Unit\DateParserTest;
@@ -36,6 +37,7 @@ class DateParser extends BaseDateParser
3637
*
3738
* @param DateTimeZone|string|null $dateTimeZone
3839
* @return DateRange
40+
* @throws Exception
3941
*/
4042
public function getDateRange(DateTimeZone|string $dateTimeZone = null): DateRange
4143
{
@@ -50,11 +52,11 @@ public function getDateRange(DateTimeZone|string $dateTimeZone = null): DateRang
5052
* Returns the "from" date as string.
5153
*
5254
* @param string $format
53-
* @param DateTimeZone|null $dateTimeZone
55+
* @param DateTimeZone|string|null $dateTimeZone
5456
* @return string|null
5557
* @throws CaseUnsupportedException
5658
*/
57-
public function formatFrom(string $format, DateTimeZone $dateTimeZone = null): string|null
59+
public function formatFrom(string $format, DateTimeZone|string $dateTimeZone = null): string|null
5860
{
5961
return $this->dateRange->getFrom($dateTimeZone)?->format($format);
6062
}
@@ -63,60 +65,82 @@ public function formatFrom(string $format, DateTimeZone $dateTimeZone = null): s
6365
* Returns the "to" date as string.
6466
*
6567
* @param string $format
66-
* @param DateTimeZone $dateTimeZone
68+
* @param DateTimeZone|string|null $dateTimeZone
6769
* @return string|null
6870
* @throws CaseUnsupportedException
6971
*/
70-
public function formatTo(string $format, DateTimeZone $dateTimeZone = new DateTimeZone(Timezones::UTC)): string|null
72+
public function formatTo(string $format, DateTimeZone|string $dateTimeZone = null): string|null
7173
{
7274
return $this->dateRange->getTo($dateTimeZone)?->format($format);
7375
}
7476

7577
/**
7678
* Returns the "from" date as DateTime object.
7779
*
78-
* @param DateTimeZone $dateTimeZone
80+
* @param DateTimeZone|string|null $dateTimeZone
7981
* @return DateTime|null
8082
* @throws CaseUnsupportedException
8183
*/
82-
public function getFrom(DateTimeZone $dateTimeZone = new DateTimeZone(Timezones::UTC)): DateTime|null
84+
public function getFrom(DateTimeZone|string $dateTimeZone = null): DateTime|null
8385
{
8486
return $this->dateRange->getFrom($dateTimeZone);
8587
}
8688

8789
/**
8890
* Returns the "to" date as DateTime object.
8991
*
90-
* @param DateTimeZone $dateTimeZone
92+
* @param DateTimeZone|string|null $dateTimeZone
9193
* @return DateTime|null
9294
* @throws CaseUnsupportedException
9395
*/
94-
public function getTo(DateTimeZone $dateTimeZone = new DateTimeZone(Timezones::UTC)): DateTime|null
96+
public function getTo(DateTimeZone|string $dateTimeZone = null): DateTime|null
9597
{
9698
return $this->dateRange->getTo($dateTimeZone);
9799
}
98100

99101
/**
100102
* Returns the "from" date as DateTimeImmutable object.
101103
*
102-
* @param DateTimeZone $dateTimeZone
104+
* @param DateTimeZone|string|null $dateTimeZone
103105
* @return DateTimeImmutable|null
104106
* @throws CaseUnsupportedException
105107
*/
106-
public function getFromImmutable(DateTimeZone $dateTimeZone = new DateTimeZone(Timezones::UTC)): DateTimeImmutable|null
108+
public function getFromImmutable(DateTimeZone|string $dateTimeZone = null): DateTimeImmutable|null
107109
{
108110
return $this->dateRange->getFromImmutable($dateTimeZone);
109111
}
110112

111113
/**
112114
* Returns the "to" date as DateTimeImmutable object.
113115
*
114-
* @param DateTimeZone $dateTimeZone
116+
* @param DateTimeZone|string|null $dateTimeZone
115117
* @return DateTimeImmutable|null
116118
* @throws CaseUnsupportedException
117119
*/
118-
public function getToImmutable(DateTimeZone $dateTimeZone = new DateTimeZone(Timezones::UTC)): DateTimeImmutable|null
120+
public function getToImmutable(DateTimeZone|string $dateTimeZone = null): DateTimeImmutable|null
119121
{
120122
return $this->dateRange->getToImmutable($dateTimeZone);
121123
}
124+
125+
/**
126+
* Returns the duration from "from" to "to" in seconds.
127+
*
128+
* @return int|null
129+
* @throws CaseUnsupportedException
130+
*/
131+
public function getDuration(): int|null
132+
{
133+
return $this->dateRange->getDuration();
134+
}
135+
136+
/**
137+
* Returns the duration from "from" to "to" in seconds (with own second).
138+
*
139+
* @return int|null
140+
* @throws CaseUnsupportedException
141+
*/
142+
public function getDurationWithOwn(): int|null
143+
{
144+
return $this->dateRange->getDurationWithOwn();
145+
}
122146
}

src/DateRange.php

Lines changed: 72 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,17 @@ public function __construct(
6161
};
6262

6363
$this->defaultDateTimeZone = new DateTimeZone(Timezones::UTC);
64+
65+
$duration = $this->getDuration();
66+
67+
if (!is_null($duration) && $duration < 0) {
68+
throw new CaseUnsupportedException(sprintf(
69+
'The duration of the date range cannot be negative: %s. The "to" date (%s) must be later or equal to the "from" date (%s).',
70+
$duration,
71+
$this->to?->format('Y-m-d H:i:s (e)') ?: 'NULL',
72+
$this->from?->format('Y-m-d H:i:s (e)') ?: 'NULL'
73+
));
74+
}
6475
}
6576

6677
/**
@@ -94,11 +105,12 @@ public function setDefaultDateTimeZone(DateTimeZone|string $defaultDateTimeZone)
94105
/**
95106
* Returns the mutable representation from "from" value.
96107
*
97-
* @param DateTimeZone|null $dateTimeZone
108+
* @param DateTimeZone|string|null $dateTimeZone
98109
* @return DateTime|null
99110
* @throws CaseUnsupportedException
111+
* @throws Exception
100112
*/
101-
public function getFrom(DateTimeZone $dateTimeZone = null): ?DateTime
113+
public function getFrom(DateTimeZone|string $dateTimeZone = null): ?DateTime
102114
{
103115
if (null === $this->from) {
104116
return null;
@@ -108,6 +120,10 @@ public function getFrom(DateTimeZone $dateTimeZone = null): ?DateTime
108120
$dateTimeZone = $this->defaultDateTimeZone;
109121
}
110122

123+
if (is_string($dateTimeZone)) {
124+
$dateTimeZone = new DateTimeZone($dateTimeZone);
125+
}
126+
111127
$from = clone $this->from;
112128

113129
return $this->convertTimezone($from, new DateTimeZone(Timezones::UTC), $dateTimeZone);
@@ -116,11 +132,12 @@ public function getFrom(DateTimeZone $dateTimeZone = null): ?DateTime
116132
/**
117133
* Returns the mutable representation from "to" value.
118134
*
119-
* @param DateTimeZone|null $dateTimeZone
135+
* @param DateTimeZone|string|null $dateTimeZone
120136
* @return DateTime|null
121137
* @throws CaseUnsupportedException
138+
* @throws Exception
122139
*/
123-
public function getTo(DateTimeZone $dateTimeZone = null): ?DateTime
140+
public function getTo(DateTimeZone|string $dateTimeZone = null): ?DateTime
124141
{
125142
if (null === $this->to) {
126143
return null;
@@ -130,6 +147,10 @@ public function getTo(DateTimeZone $dateTimeZone = null): ?DateTime
130147
$dateTimeZone = $this->defaultDateTimeZone;
131148
}
132149

150+
if (is_string($dateTimeZone)) {
151+
$dateTimeZone = new DateTimeZone($dateTimeZone);
152+
}
153+
133154
$to = clone $this->to;
134155

135156
return $this->convertTimezone($to, new DateTimeZone(Timezones::UTC), $dateTimeZone);
@@ -138,12 +159,12 @@ public function getTo(DateTimeZone $dateTimeZone = null): ?DateTime
138159
/**
139160
* Returns the immutable representation from "from" value.
140161
*
141-
* @param DateTimeZone|null $dateTimeZone
162+
* @param DateTimeZone|string|null $dateTimeZone
142163
* @return DateTimeImmutable|null
143164
* @throws CaseUnsupportedException
144165
* @SuppressWarnings(PHPMD.StaticAccess)
145166
*/
146-
public function getFromImmutable(DateTimeZone $dateTimeZone = null): ?DateTimeImmutable
167+
public function getFromImmutable(DateTimeZone|string $dateTimeZone = null): ?DateTimeImmutable
147168
{
148169
$from = $this->getFrom($dateTimeZone);
149170

@@ -157,12 +178,12 @@ public function getFromImmutable(DateTimeZone $dateTimeZone = null): ?DateTimeIm
157178
/**
158179
* Returns the immutable representation from "to" value.
159180
*
160-
* @param DateTimeZone|null $dateTimeZone
181+
* @param DateTimeZone|string|null $dateTimeZone
161182
* @return DateTimeImmutable|null
162183
* @throws CaseUnsupportedException
163184
* @SuppressWarnings(PHPMD.StaticAccess)
164185
*/
165-
public function getToImmutable(DateTimeZone $dateTimeZone = null): ?DateTimeImmutable
186+
public function getToImmutable(DateTimeZone|string $dateTimeZone = null): ?DateTimeImmutable
166187
{
167188
$to = $this->getTo($dateTimeZone);
168189

@@ -173,6 +194,49 @@ public function getToImmutable(DateTimeZone $dateTimeZone = null): ?DateTimeImmu
173194
return DateTimeImmutable::createFromMutable($to);
174195
}
175196

197+
/**
198+
* Returns the duration between "from" and "to" in seconds.
199+
*
200+
* @return int|null
201+
* @throws CaseUnsupportedException
202+
*/
203+
public function getDuration(): int|null
204+
{
205+
$toDateTime = $this->getTo();
206+
$fromDateTime = $this->getFrom();
207+
208+
if (is_null($fromDateTime) || is_null($toDateTime)) {
209+
return null;
210+
}
211+
212+
if ($fromDateTime->getTimezone()->getName() !== $toDateTime->getTimezone()->getName()) {
213+
throw new CaseUnsupportedException(sprintf(
214+
'Unable to determine duration between different timezones: "%s" and "%s".',
215+
$fromDateTime->getTimezone()->getName(),
216+
$toDateTime->getTimezone()->getName()
217+
));
218+
}
219+
220+
return $toDateTime->getTimestamp() - $fromDateTime->getTimestamp();
221+
}
222+
223+
/**
224+
* Returns the duration between "from" and "to" in seconds.
225+
*
226+
* @return int|null
227+
* @throws CaseUnsupportedException
228+
*/
229+
public function getDurationWithOwn(): int|null
230+
{
231+
$duration = $this->getDuration();
232+
233+
if (is_null($duration)) {
234+
return null;
235+
}
236+
237+
return $duration + 1;
238+
}
239+
176240
/**
177241
* Returns a DateTime instance with timezone UTC.
178242
*

0 commit comments

Comments
 (0)