DateTime::date()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace DummyGenerator\Core;
6
7
use DateInterval;
8
use DateTimeInterface;
9
use DummyGenerator\Definitions\Extension\Awareness\RandomizerAwareExtensionInterface;
10
use DummyGenerator\Definitions\Extension\Awareness\RandomizerAwareExtensionTrait;
11
use DummyGenerator\Definitions\Extension\DateTimeExtensionInterface;
12
use DummyGenerator\Definitions\Extension\Exception\ExtensionArgumentException;
13
14
class DateTime implements DateTimeExtensionInterface, RandomizerAwareExtensionInterface
15
{
16
    use RandomizerAwareExtensionTrait;
17
18
    /**
19
     * @var string[]
20
     * TODO move to interface const
21
     */
22
    protected array $centuries = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X', 'XI', 'XII', 'XIII', 'XIV', 'XV', 'XVI', 'XVII', 'XVIII', 'XIX', 'XX', 'XXI'];
23
24
    protected ?string $defaultTimezone = null;
25
26 10
    public function dateTime(DateTimeInterface|string $until = 'now', ?string $timezone = null): \DateTimeInterface
27
    {
28 10
        return $this->setTimezone(
29 10
            $this->getTimestampDateTime($this->unixTime($until)),
30 10
            $timezone,
31 10
        );
32
    }
33
34 1
    public function dateTimeAD(DateTimeInterface|string $until = 'now', ?string $timezone = null): \DateTimeInterface
35
    {
36 1
        $min = (PHP_INT_SIZE > 4) ? -62135597361 : -PHP_INT_MAX;
37
38 1
        return $this->setTimezone(
39 1
            $this->getTimestampDateTime($this->randomizer->getInt($min, $this->getTimestamp($until))),
40 1
            $timezone,
41 1
        );
42
    }
43
44 9
    public function dateTimeBetween(DateTimeInterface|string $from = '-30 years', DateTimeInterface|string $until = 'now', ?string $timezone = null): \DateTimeInterface
45
    {
46 9
        $start = $this->getTimestamp($from);
47 9
        $end = $this->getTimestamp($until);
48
49 9
        if ($start > $end) {
50
            throw new ExtensionArgumentException('"$from" must be anterior to "$until".');
51
        }
52
53 9
        $timestamp = $this->randomizer->getInt($start, $end);
54
55 9
        return $this->setTimezone(
56 9
            $this->getTimestampDateTime($timestamp),
57 9
            $timezone,
58 9
        );
59
    }
60
61 1
    public function dateTimeInInterval(
62
        DateTimeInterface|string $from = '-30 years',
63
        DateInterval|string $interval = '+5 days',
64
        ?string $timezone = null
65
    ): \DateTimeInterface {
66 1
        $intervalObject = $interval instanceof DateInterval ? $interval : DateInterval::createFromDateString($interval);
67 1
        $datetime = $from instanceof \DateTimeInterface ? $from : new \DateTimeImmutable((string) $from);
68
69
        // @phpstan-ignore-next-line
70 1
        $other = $datetime->add($intervalObject);
71
72 1
        $begin = min($datetime, $other);
73 1
        $end = $datetime === $begin ? $other : $datetime;
74
75 1
        return $this->dateTimeBetween($begin, $end, $timezone);
76
    }
77
78 1
    public function dateTimeThisWeek(DateTimeInterface|string $until = 'sunday this week', ?string $timezone = null): \DateTimeInterface
79
    {
80 1
        return $this->dateTimeBetween('monday this week', $until, $timezone);
81
    }
82
83 1
    public function dateTimeThisMonth(DateTimeInterface|string $until = 'last day of this month', ?string $timezone = null): \DateTimeInterface
84
    {
85 1
        return $this->dateTimeBetween('first day of this month', $until, $timezone);
86
    }
87
88 1
    public function dateTimeThisYear(DateTimeInterface|string $until = 'last day of december', ?string $timezone = null): \DateTimeInterface
89
    {
90 1
        return $this->dateTimeBetween('first day of january', $until, $timezone);
91
    }
92
93 1
    public function dateTimeThisDecade(DateTimeInterface|string $until = 'now', ?string $timezone = null): \DateTimeInterface
94
    {
95 1
        $year = floor(date('Y') / 10) * 10;
96
97 1
        return $this->dateTimeBetween("first day of january $year", $until, $timezone);
98
    }
99
100 1
    public function dateTimeThisCentury(DateTimeInterface|string $until = 'now', ?string $timezone = null): \DateTimeInterface
101
    {
102 1
        $year = floor(date('Y') / 100) * 100;
103
104 1
        return $this->dateTimeBetween("first day of january $year", $until, $timezone);
105
    }
106
107 9
    public function date(string $format = 'Y-m-d', DateTimeInterface|string $until = 'now'): string
108
    {
109 9
        return $this->dateTime($until)->format($format);
110
    }
111
112 1
    public function time(string $format = 'H:i:s', DateTimeInterface|string $until = 'now'): string
113
    {
114 1
        return $this->date($format, $until);
115
    }
116
117 11
    public function unixTime(DateTimeInterface|string $until = 'now'): int
118
    {
119 11
        return $this->randomizer->getInt(0, $this->getTimestamp($until));
120
    }
121
122 1
    public function iso8601(DateTimeInterface|string $until = 'now'): string
123
    {
124 1
        return $this->date(DateTimeInterface::ATOM, $until);
125
    }
126
127 1
    public function amPm(DateTimeInterface|string $until = 'now'): string
128
    {
129 1
        return $this->date('a', $until);
130
    }
131
132 1
    public function dayOfMonth(DateTimeInterface|string $until = 'now'): string
133
    {
134 1
        return $this->date('d', $until);
135
    }
136
137 1
    public function dayOfWeek(DateTimeInterface|string $until = 'now'): string
138
    {
139 1
        return $this->date('l', $until);
140
    }
141
142 1
    public function month(DateTimeInterface|string $until = 'now'): string
143
    {
144 1
        return $this->date('m', $until);
145
    }
146
147 1
    public function monthName(DateTimeInterface|string $until = 'now'): string
148
    {
149 1
        return $this->date('F', $until);
150
    }
151
152 1
    public function year(DateTimeInterface|string $until = 'now'): string
153
    {
154 1
        return $this->date('Y', $until);
155
    }
156
157 1
    public function century(): string
158
    {
159 1
        return $this->randomizer->randomElement($this->centuries);
160
    }
161
162 1
    public function timezone(): string
163
    {
164 1
        return $this->randomizer->randomElement(\DateTimeZone::listIdentifiers());
165
    }
166
167
    /**
168
     * Get the POSIX-timestamp of a DateTime or string (can be epoch as "1733785884").
169
     */
170 21
    protected function getTimestamp(\DateTimeInterface|string $until = 'now'): int
171
    {
172 21
        if (is_numeric($until)) {
173
            return (int) $until;
174
        }
175
176 21
        if ($until instanceof \DateTimeInterface) {
177 17
            return $until->getTimestamp();
178
        }
179
180 9
        return (int) strtotime(empty($until) ? 'now' : $until);
181
    }
182
183
    /**
184
     * Get a DateTimeImmutable created based on a POSIX-timestamp.
185
     *
186
     * @param int $timestamp the UNIX / POSIX-compatible timestamp
187
     * @throws \DateMalformedStringException
188
     */
189 20
    protected function getTimestampDateTime(int $timestamp): \DateTimeInterface
190
    {
191 20
        return new \DateTimeImmutable('@' . $timestamp);
192
    }
193
194
    protected function setDefaultTimezone(?string $timezone = null): void
195
    {
196
        $this->defaultTimezone = $timezone;
197
    }
198
199
    protected function getDefaultTimezone(): ?string
200
    {
201
        return $this->defaultTimezone;
202
    }
203
204 20
    protected function resolveTimezone(?string $timezone): string
205
    {
206 20
        return $timezone ?? $this->defaultTimezone ?? date_default_timezone_get();
207
    }
208
209
    /**
210
     * Internal method to set the timezone on a DateTime object.
211
     */
212 20
    protected function setTimezone(\DateTimeInterface $dateTime, ?string $timezone): \DateTimeInterface
213
    {
214 20
        $timezone = $this->resolveTimezone($timezone);
215
216
        // @phpstan-ignore-next-line
217 20
        return $dateTime->setTimezone(new \DateTimeZone($timezone));
218
    }
219
}
220