1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace Arp\DateTime; |
||||
6 | |||||
7 | use Arp\DateTime\Exception\DateTimeFactoryException; |
||||
8 | use Arp\DateTime\Exception\DateTimeZoneFactoryException; |
||||
9 | |||||
10 | final class DateTimeFactory implements DateTimeFactoryInterface |
||||
11 | { |
||||
12 | /** |
||||
13 | * @var class-string<\DateTimeInterface> |
||||
0 ignored issues
–
show
Documentation
Bug
introduced
by
![]() |
|||||
14 | */ |
||||
15 | private string $dateTimeClassName; |
||||
16 | |||||
17 | /** |
||||
18 | * @param class-string<\DateTimeInterface>|null $dateTimeClassName |
||||
0 ignored issues
–
show
|
|||||
19 | * |
||||
20 | * @throws DateTimeFactoryException |
||||
21 | */ |
||||
22 | public function __construct( |
||||
23 | private ?DateTimeZoneFactoryInterface $dateTimeZoneFactory = null, |
||||
24 | ?string $dateTimeClassName = null |
||||
25 | ) { |
||||
26 | $this->dateTimeZoneFactory = $dateTimeZoneFactory ?? new DateTimeZoneFactory(); |
||||
27 | |||||
28 | $dateTimeClassName ??= \DateTime::class; |
||||
29 | if (!is_a($dateTimeClassName, \DateTimeInterface::class, true)) { |
||||
30 | throw new DateTimeFactoryException( |
||||
31 | sprintf( |
||||
32 | 'The \'dateTimeClassName\' parameter must be a class that implements \'%s\'', |
||||
33 | \DateTimeInterface::class |
||||
34 | ) |
||||
35 | ); |
||||
36 | } |
||||
37 | |||||
38 | $this->dateTimeClassName = $dateTimeClassName; |
||||
39 | } |
||||
40 | |||||
41 | /** |
||||
42 | * @throws DateTimeFactoryException |
||||
43 | */ |
||||
44 | public function createDateTime(?string $spec = null, string|\DateTimeZone|null $timeZone = null): \DateTimeInterface |
||||
45 | { |
||||
46 | $dateTimeZone = $this->resolveDateTimeZone($timeZone); |
||||
47 | |||||
48 | try { |
||||
49 | /** @throws \Exception */ |
||||
50 | return new $this->dateTimeClassName($spec ?? 'now', $dateTimeZone); |
||||
51 | } catch (\Exception $e) { |
||||
52 | throw new DateTimeFactoryException( |
||||
53 | sprintf('Failed to create a valid \DateTime instance using \'%s\'', $spec), |
||||
54 | $e->getCode(), |
||||
55 | $e |
||||
56 | ); |
||||
57 | } |
||||
58 | } |
||||
59 | |||||
60 | /** |
||||
61 | * @throws DateTimeFactoryException |
||||
62 | */ |
||||
63 | public function createFromFormat( |
||||
64 | string $format, |
||||
65 | string $spec, |
||||
66 | string|\DateTimeZone|null $timeZone = null |
||||
67 | ): \DateTimeInterface { |
||||
68 | /** @var callable $factory */ |
||||
69 | $factory = [$this->dateTimeClassName, 'createFromFormat']; |
||||
70 | |||||
71 | $dateTime = $factory($format, $spec, $this->resolveDateTimeZone($timeZone)); |
||||
72 | |||||
73 | if (!$dateTime instanceof \DateTimeInterface) { |
||||
74 | throw new DateTimeFactoryException( |
||||
75 | sprintf( |
||||
76 | 'Failed to create a valid \DateTime instance using \'%s\' and format \'%s\'', |
||||
77 | $spec, |
||||
78 | $format |
||||
79 | ) |
||||
80 | ); |
||||
81 | } |
||||
82 | |||||
83 | return $dateTime; |
||||
84 | } |
||||
85 | |||||
86 | /** |
||||
87 | * @throws DateTimeFactoryException |
||||
88 | */ |
||||
89 | private function resolveDateTimeZone(string|\DateTimeZone|null $timeZone): ?\DateTimeZone |
||||
90 | { |
||||
91 | try { |
||||
92 | return is_string($timeZone) |
||||
93 | ? $this->dateTimeZoneFactory->createDateTimeZone($timeZone) |
||||
0 ignored issues
–
show
The method
createDateTimeZone() does not exist on null .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces. This is most likely a typographical error or the method has been renamed. ![]() |
|||||
94 | : $timeZone; |
||||
95 | } catch (DateTimeZoneFactoryException $e) { |
||||
96 | throw new DateTimeFactoryException('Failed to create date time zone', $e->getCode(), $e); |
||||
97 | } |
||||
98 | } |
||||
99 | } |
||||
100 |