DateTimeFactory   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 87
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
wmc 9
eloc 33
c 3
b 1
f 0
dl 0
loc 87
rs 10

4 Methods

Rating   Name   Duplication   Size   Complexity  
A createFromFormat() 0 21 2
A __construct() 0 17 2
A createDateTime() 0 12 2
A resolveDateTimeZone() 0 8 3
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
The doc comment class-string<\DateTimeInterface> at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\DateTimeInterface>.
Loading history...
14
     */
15
    private string $dateTimeClassName;
16
17
    /**
18
     * @param class-string<\DateTimeInterface>|null $dateTimeClassName
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string<\DateTimeInterface>|null at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string<\DateTimeInterface>|null.
Loading history...
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
Bug introduced by
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 ignore-call  annotation

93
                ? $this->dateTimeZoneFactory->/** @scrutinizer ignore-call */ createDateTimeZone($timeZone)

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.

Loading history...
94
                : $timeZone;
95
        } catch (DateTimeZoneFactoryException $e) {
96
            throw new DateTimeFactoryException('Failed to create date time zone', $e->getCode(), $e);
97
        }
98
    }
99
}
100