Skip to content

Commit de29aae

Browse files
committed
Review date and time interfaces and classes
- Review `DateFormatter` - Review `IDateFormatter` and rename to `DateFormatterInterface` - Review `IDateParser` and rename to `DateParserInterface` - Review `CreateFromFormatDateParser` and rename to `DateFormatParser` - Review `TextualDateParser` and rename to `DateParser` - Move `RegexDateParser::dotNet()` to `DotNetDateParser` - Remove unused `RegexDateParser` - Move aforementioned to `Lkrms\Support\Date`
1 parent f5bcc40 commit de29aae

22 files changed

+190
-161
lines changed

src/Concept/Provider.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
namespace Lkrms\Concept;
44

55
use Lkrms\Contract\IContainer;
6-
use Lkrms\Contract\IDateFormatter;
76
use Lkrms\Contract\IProvider;
87
use Lkrms\Exception\MethodNotImplementedException;
8+
use Lkrms\Support\Date\DateFormatterInterface;
99
use Lkrms\Support\ProviderContext;
1010

1111
/**
@@ -17,7 +17,7 @@ abstract class Provider implements IProvider
1717
{
1818
protected IContainer $App;
1919

20-
private IDateFormatter $DateFormatter;
20+
private DateFormatterInterface $DateFormatter;
2121

2222
/**
2323
* Creates a new provider object
@@ -31,10 +31,10 @@ public function __construct(IContainer $app)
3131
* Get a date formatter to work with the backend's date and time format
3232
* and/or timezone
3333
*
34-
* The {@see IDateFormatter} returned will be cached for the lifetime of the
35-
* {@see Provider} instance.
34+
* The {@see DateFormatterInterface} returned will be cached for the
35+
* lifetime of the {@see Provider} instance.
3636
*/
37-
abstract protected function getDateFormatter(): IDateFormatter;
37+
abstract protected function getDateFormatter(): DateFormatterInterface;
3838

3939
/**
4040
* @inheritDoc
@@ -79,7 +79,7 @@ final public function container(): IContainer
7979
/**
8080
* @inheritDoc
8181
*/
82-
final public function dateFormatter(): IDateFormatter
82+
final public function dateFormatter(): DateFormatterInterface
8383
{
8484
return $this->DateFormatter
8585
?? ($this->DateFormatter = $this->getDateFormatter());
@@ -89,7 +89,7 @@ final public function dateFormatter(): IDateFormatter
8989
* Get the date formatter cached by dateFormatter(), or null if it hasn't
9090
* been cached
9191
*/
92-
final protected function getCachedDateFormatter(): ?IDateFormatter
92+
final protected function getCachedDateFormatter(): ?DateFormatterInterface
9393
{
9494
return $this->DateFormatter ?? null;
9595
}
@@ -99,7 +99,7 @@ final protected function getCachedDateFormatter(): ?IDateFormatter
9999
*
100100
* @return $this
101101
*/
102-
final protected function setDateFormatter(?IDateFormatter $formatter)
102+
final protected function setDateFormatter(?DateFormatterInterface $formatter)
103103
{
104104
if ($formatter === null) {
105105
unset($this->DateFormatter);

src/Contract/IProvider.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Lkrms\Contract;
44

55
use Lkrms\Exception\MethodNotImplementedException;
6+
use Lkrms\Support\Date\DateFormatterInterface;
67
use Stringable;
78

89
/**
@@ -64,7 +65,7 @@ public function getBackendIdentifier(): array;
6465
* Get a date formatter to work with the backend's date and time format
6566
* and/or timezone
6667
*/
67-
public function dateFormatter(): IDateFormatter;
68+
public function dateFormatter(): DateFormatterInterface;
6869

6970
/**
7071
* Throw an exception if the backend isn't reachable

src/Contract/ISerializeRules.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
namespace Lkrms\Contract;
44

5-
use Lkrms\Support\DateFormatter;
5+
use Lkrms\Support\Date\DateFormatter;
66

77
/**
88
* Instructions for serializing nested entities

src/Curler/Curler.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
use Lkrms\Concern\TWritable;
99
use Lkrms\Contract\Buildable;
1010
use Lkrms\Contract\ICollection;
11-
use Lkrms\Contract\IDateFormatter;
1211
use Lkrms\Contract\IReadable;
1312
use Lkrms\Contract\IWritable;
1413
use Lkrms\Curler\Catalog\CurlerProperty;
@@ -28,7 +27,8 @@
2827
use Lkrms\Iterator\RecursiveMutableGraphIterator;
2928
use Lkrms\Store\CacheStore;
3029
use Lkrms\Support\Catalog\MimeType;
31-
use Lkrms\Support\DateFormatter;
30+
use Lkrms\Support\Date\DateFormatter;
31+
use Lkrms\Support\Date\DateFormatterInterface;
3232
use Lkrms\Utility\Arr;
3333
use Lkrms\Utility\Compute;
3434
use Lkrms\Utility\Convert;
@@ -78,7 +78,7 @@
7878
* @property bool $ExpectJson Request JSON from upstream?
7979
* @property bool $PostJson Use JSON to serialize POST/PUT/PATCH/DELETE data?
8080
* @property bool $PreserveKeys Suppress removal of numeric indices from serialized lists?
81-
* @property IDateFormatter|null $DateFormatter Specify the date format and timezone used upstream
81+
* @property DateFormatterInterface|null $DateFormatter Specify the date format and timezone used upstream
8282
* @property string|null $UserAgent Override the default User-Agent header
8383
* @property bool $AlwaysPaginate Pass every response to the pager?
8484
* @property bool $ObjectAsArray Return deserialized objects as associative arrays?
@@ -359,7 +359,7 @@ final class Curler implements IReadable, IWritable, Buildable
359359
/**
360360
* Specify the date format and timezone used upstream
361361
*
362-
* @var IDateFormatter|null
362+
* @var DateFormatterInterface|null
363363
*/
364364
protected $DateFormatter;
365365

@@ -465,7 +465,7 @@ public function __construct(
465465
bool $expectJson = true,
466466
bool $postJson = true,
467467
bool $preserveKeys = false,
468-
?IDateFormatter $dateFormatter = null,
468+
?DateFormatterInterface $dateFormatter = null,
469469
?string $userAgent = null,
470470
bool $alwaysPaginate = false,
471471
bool $objectAsArray = true
@@ -924,7 +924,7 @@ private function getCookieKey(): ?string
924924
: null;
925925
}
926926

927-
private function getDateFormatter(): IDateFormatter
927+
private function getDateFormatter(): DateFormatterInterface
928928
{
929929
return $this->DateFormatter
930930
?: ($this->DateFormatter = new DateFormatter());

src/Curler/CurlerBuilder.php

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,44 @@
11
<?php declare(strict_types=1);
22

3-
namespace Lkrms\Support\DateParser;
3+
namespace Lkrms\Support\Date;
44

5-
use Lkrms\Contract\IDateParser;
65
use DateTimeImmutable;
76
use DateTimeZone;
87

98
/**
10-
* A wrapper around DateTimeImmutable::createFromFormat()
9+
* Parses date and time strings with a given format
10+
*
11+
* @api
1112
*/
12-
final class CreateFromFormatDateParser implements IDateParser
13+
final class DateFormatParser implements DateParserInterface
1314
{
15+
private string $Format;
16+
1417
/**
15-
* @var string
18+
* Creates a new CreateFromFormatDateParser object
19+
*
20+
* @see DateTimeImmutable::createFromFormat()
1621
*/
17-
private $Format;
18-
1922
public function __construct(string $format)
2023
{
21-
// Reset fields that don't appear in the format string to zero,
22-
// otherwise they default to the current time
24+
// Reset fields that don't appear in the format string to zero-like
25+
// values, otherwise they will be set to the current date and time
2326
if (strpos($format, '!') === false && strpos($format, '|') === false) {
2427
$format .= '|';
2528
}
2629

2730
$this->Format = $format;
2831
}
2932

33+
/**
34+
* @inheritDoc
35+
*/
3036
public function parse(string $value, ?DateTimeZone $timezone = null): ?DateTimeImmutable
3137
{
32-
return DateTimeImmutable::createFromFormat($this->Format, $value, $timezone) ?: null;
38+
$date = DateTimeImmutable::createFromFormat($this->Format, $value, $timezone);
39+
if ($date === false) {
40+
return null;
41+
}
42+
return $date;
3343
}
3444
}

src/Support/Date/DateFormatter.php

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,62 @@
11
<?php declare(strict_types=1);
22

3-
namespace Lkrms\Support;
3+
namespace Lkrms\Support\Date;
44

5-
use Lkrms\Concern\TFullyReadable;
6-
use Lkrms\Contract\IDateFormatter;
7-
use Lkrms\Contract\IDateParser;
8-
use Lkrms\Contract\IImmutable;
9-
use Lkrms\Contract\IReadable;
10-
use Lkrms\Support\DateParser\CreateFromFormatDateParser;
115
use Lkrms\Utility\Date;
126
use DateTimeImmutable;
137
use DateTimeInterface;
148
use DateTimeZone;
159

1610
/**
17-
* An immutable date formatter and parser that optionally applies a preferred
18-
* timezone to both operations
11+
* Formats and parses dates, optionally applying a preferred timezone to both
12+
* operations
1913
*
20-
* @property-read string $Format
21-
* @property-read DateTimeZone|null $Timezone
22-
* @property-read IDateParser[] $Parsers
14+
* @api
2315
*/
24-
final class DateFormatter implements IDateFormatter, IImmutable, IReadable
16+
final class DateFormatter implements DateFormatterInterface
2517
{
26-
use TFullyReadable;
18+
private string $Format;
2719

28-
/**
29-
* @var string
30-
*/
31-
protected $Format;
32-
33-
/**
34-
* @var DateTimeZone|null
35-
*/
36-
protected $Timezone;
20+
private ?DateTimeZone $Timezone;
3721

3822
/**
39-
* @var IDateParser[]
23+
* @var DateParserInterface[]
4024
*/
41-
protected $Parsers;
25+
private array $Parsers;
4226

4327
/**
4428
* @param DateTimeZone|string|null $timezone
4529
*/
46-
public function __construct(string $format = DateTimeInterface::ATOM, $timezone = null, IDateParser ...$parsers)
30+
public function __construct(string $format = DateTimeInterface::ATOM, $timezone = null, DateParserInterface ...$parsers)
4731
{
4832
$this->Format = $format;
49-
$this->Timezone = $timezone === null ? null : Date::timezone($timezone);
50-
$this->Parsers = $parsers ?: [new CreateFromFormatDateParser($format)];
33+
$this->Timezone = is_string($timezone) ? new DateTimeZone($timezone) : $timezone;
34+
$this->Parsers = $parsers ?: [new DateFormatParser($format)];
5135
}
5236

5337
/**
54-
* Format a date after optionally applying the preferred timezone
55-
*
56-
* If `$date` is a `DateTime` object, {@see DateFormatter::$Timezone} is
57-
* set, and `$date->Timezone` has a different value, `$date` is converted to
58-
* a `DateTimeImmutable` before applying the timezone. The original
59-
* `DateTime` object is not modified.
38+
* @inheritDoc
6039
*/
6140
public function format(DateTimeInterface $date): string
6241
{
63-
if ($this->Timezone &&
64-
$this->Timezone->getName() !== $date->getTimezone()->getName()) {
42+
if (
43+
$this->Timezone &&
44+
$this->Timezone->getName() !== $date->getTimezone()->getName()
45+
) {
6546
$date = Date::immutable($date)->setTimezone($this->Timezone);
6647
}
6748

6849
return $date->format($this->Format);
6950
}
7051

7152
/**
72-
* Convert a string to a date, if possible
73-
*
74-
* @return DateTimeImmutable|null a `DateTimeImmutable` object on success or
75-
* `null` on failure.
53+
* @inheritDoc
7654
*/
7755
public function parse(string $value): ?DateTimeImmutable
7856
{
7957
foreach ($this->Parsers as $parser) {
80-
if ($date = $parser->parse($value, $this->Timezone)) {
58+
$date = $parser->parse($value, $this->Timezone);
59+
if ($date) {
8160
return $date;
8261
}
8362
}
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<?php declare(strict_types=1);
22

3-
namespace Lkrms\Contract;
3+
namespace Lkrms\Support\Date;
44

55
use DateTimeImmutable;
66
use DateTimeInterface;
77

88
/**
9-
* Formats and parses date and time values
9+
* @api
1010
*/
11-
interface IDateFormatter
11+
interface DateFormatterInterface
1212
{
1313
/**
1414
* Format a date and time
@@ -17,6 +17,8 @@ public function format(DateTimeInterface $date): string;
1717

1818
/**
1919
* Convert a string to a date and time, if possible
20+
*
21+
* Returns `null` if `$value` cannot be parsed.
2022
*/
2123
public function parse(string $value): ?DateTimeImmutable;
2224
}

src/Support/Date/DateParser.php

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,26 @@
11
<?php declare(strict_types=1);
22

3-
namespace Lkrms\Support\DateParser;
3+
namespace Lkrms\Support\Date;
44

5-
use Lkrms\Contract\IDateParser;
65
use DateTimeImmutable;
76
use DateTimeZone;
87

98
/**
10-
* A wrapper around date_create_immutable()
9+
* Parses date and time strings understood by strtotime()
10+
*
11+
* @api
1112
*/
12-
final class TextualDateParser implements IDateParser
13+
final class DateParser implements DateParserInterface
1314
{
15+
/**
16+
* @inheritDoc
17+
*/
1418
public function parse(string $value, ?DateTimeZone $timezone = null): ?DateTimeImmutable
1519
{
16-
return date_create_immutable($value, $timezone) ?: null;
20+
$date = date_create_immutable($value, $timezone);
21+
if ($date === false) {
22+
return null;
23+
}
24+
return $date;
1725
}
1826
}

0 commit comments

Comments
 (0)