Completed
Push — master ( 20d39e...498091 )
by Tim
17s queued 12s
created

DateTimeUtility::setSecondsOfDateTime()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 8
rs 10
c 0
b 0
f 0
ccs 1
cts 1
cp 1
cc 1
nc 1
nop 2
crap 1
1
<?php
2
3
/**
4
 * DateTime Utility.
5
 */
6
declare(strict_types=1);
7
8
namespace HDNET\Calendarize\Utility;
9
10
use TYPO3\CMS\Core\Utility\MathUtility;
11
12
/**
13
 * DateTime Utility.
14
 */
15
class DateTimeUtility
16
{
17
    /**
18
     * One second.
19
     */
20
    const SECONDS_SECOND = 1;
21
22
    /**
23
     * One minute in seconds.
24
     */
25
    const SECONDS_MINUTE = 60;
26
27
    /**
28
     * One hour in seconds.
29
     */
30
    const SECONDS_HOUR = 3600;
31
32
    /**
33
     * One day in seconds.
34
     */
35
    const SECONDS_DAY = 86400;
36
37
    /**
38
     * One week in seconds.
39
     */
40
    const SECONDS_WEEK = 604800;
41
42
    /**
43
     * One quartar in seconds (90 days).
44
     */
45
    const SECONDS_QUARTER = 7776000;
46
47
    /**
48
     * One year in seconds (365 days).
49
     */
50
    const SECONDS_YEAR = 31536000;
51
52
    /**
53
     * One decade in seconds (base on a 365 days year).
54
     */
55
    const SECONDS_DECADE = 315360000;
56
57
    /**
58
     * Format date (Backend).
59
     */
60
    const FORMAT_DATE_BACKEND = '%a %d.%m.%Y';
61
62
    /**
63
     * Convert a Week/Year combination to a DateTime of the first day of week.
64
     *
65
     * @param int $week
66
     * @param int $year
67
     * @param int $startDay
68
     *
69
     * @return \DateTime
70
     */
71
    public static function convertWeekYear2DayMonthYear($week, $year, $startDay = 1): \DateTime
72
    {
73
        $date = self::getNow();
74 2
        $date->setTime(0, 0, 0);
75
        $date->setISODate($year, $week, $startDay);
76 2
77
        return $date;
78
    }
79
80
    /**
81
     * Time zone is set by the TYPO3 core.
82
     *
83
     * @return \DateTimeZone
84
     *
85
     * @see \TYPO3\CMS\Core\Core\Bootstrap->setDefaultTimezone()
86
     */
87
    public static function getTimeZone()
88
    {
89
        return new \DateTimeZone(date_default_timezone_get());
90
    }
91
92
    /**
93
     * Time zone that is always UTC.
94
     *
95
     * @return \DateTimeZone
96
     */
97
    public static function getUtcTimeZone()
98
    {
99
        return new \DateTimeZone('UTC');
100
    }
101
102
    /**
103
     * Get the time seconds of the given date (TYPO3 Backend style).
104
     *
105
     * @param \DateTimeInterface $dateTime
106
     *
107
     * @return int
108
     */
109
    public static function getDaySecondsOfDateTime(\DateTimeInterface $dateTime): int
110
    {
111
        $hours = (int)$dateTime->format('G');
112
        $minutes = $hours * self::SECONDS_MINUTE + (int)$dateTime->format('i');
113
114
        return $minutes * self::SECONDS_MINUTE + (int)$dateTime->format('s');
115
    }
116
117
    /**
118
     * Get the time seconds of the given date (TYPO3 Backend style) in the server timezone.
119
     *
120
     * @param \DateTimeInterface $dateTime
121
     *
122
     * @return int
123
     */
124
    public static function getNormalizedDaySecondsOfDateTime(\DateTimeInterface $dateTime): int
125
    {
126
        $date = self::normalizeDateTimeSingle($dateTime);
127
128
        return self::getDaySecondsOfDateTime($date);
129
    }
130
131
    /**
132
     * Sets the time seconds on the given date.
133
     *
134
     * @param \DateTime $date
135
     * @param int       $seconds
136
     *
137
     * @return \DateTime
138
     */
139
    public static function setSecondsOfDateTime(\DateTime $date, int $seconds): \DateTime
140
    {
141
        $date = clone $date;
142
        $date->setTime(0, 0, 0);
143
        $date->modify("+$seconds seconds");
144
145 2
        return $date;
146
    }
147 2
148 2
    /**
149 2
     * Get a normalize date time object.
150
     *
151 2
     * @param int|null $day
152
     * @param int|null $month
153
     * @param int|null $year
154 2
     *
155
     * @return \DateTime
156
     */
157
    public static function normalizeDateTime($day = null, $month = null, $year = null): \DateTime
158
    {
159
        $date = self::getNow();
160
        // Check if this date should handle always in UTC
161
        // $date->setTimezone(self::getUtcTimeZone());
162
        if (!MathUtility::canBeInterpretedAsInteger($year)) {
163
            $year = $date->format('Y');
164
        }
165
        if (!MathUtility::canBeInterpretedAsInteger($month)) {
166
            $month = $date->format('m');
167
        }
168
        if (!MathUtility::canBeInterpretedAsInteger($day)) {
169
            $day = $date->format('d');
170
        }
171
        $date->setDate((int)$year, (int)$month, (int)$day);
172
        $date->setTime(0, 0, 0);
173
        if ($date->format('m') > $month) {
174
            $date->modify('last day of last month');
175
        } elseif ($date->format('m') < $month) {
176
            $date->modify('first day of next month');
177
        }
178
179
        return $date;
180
    }
181
182
    /**
183
     * Normalize quartar.
184
     *
185
     * @param int|null $quarter
186
     *
187
     * @return int
188
     */
189
    public static function normalizeQuarter(int $quarter = null): int
190
    {
191
        if (null === $quarter) {
192
            $quarter = self::getQuartar(self::getNow());
193
        }
194
195
        return MathUtility::forceIntegerInRange((int)$quarter, 1, 4);
196
    }
197
198
    /**
199
     * Normalize quartar.
200
     *
201
     * @param \DateTimeInterface $date
202
     *
203
     * @return int
204
     */
205
    public static function getQuartar(\DateTimeInterface $date): int
206
    {
207
        $month = (int)$date->format('n');
208
209
        return (int)ceil($month / 3);
210
    }
211
212
    /**
213
     * Reset the DateTime.
214
     *
215
     * @param int|string|\DateTimeInterface|null $dateTime
216
     *
217
     * @return \DateTime
218
     */
219
    public static function resetTime($dateTime = null): \DateTime
220
    {
221
        $dateTime = self::normalizeDateTimeSingle($dateTime);
222
        $dateTime->setTime(0, 0, 0);
223
224
        return $dateTime;
225
    }
226
227
    /**
228
     * Get a normalized date time object in a specific timezone.
229
     *
230
     * @param int|string|\DateTimeInterface|null $dateInformation
231
     * @param \DateTimeZone|null                 $timezone        Timezone to normalize to. Defaults to the self::getTimeZone().
232
     *
233
     * @return \DateTime
234
     *
235
     * @throws \Exception
236
     */
237
    public static function normalizeDateTimeSingle($dateInformation = null, \DateTimeZone $timezone = null): \DateTime
238
    {
239
        $timezone = $timezone ?? self::getTimeZone();
240
        $date = self::getNow();
241
242
        if ($dateInformation instanceof \DateTimeInterface) {
243
            // Convert DateTimeInterface to a DateTime object
244
            $date = \DateTime::createFromFormat(
245
                \DateTimeInterface::ATOM,
246
                $dateInformation->format(\DateTimeInterface::ATOM),
247
                $timezone
248
            );
249
        } elseif (MathUtility::canBeInterpretedAsInteger($dateInformation)) {
250
            // http://php.net/manual/en/datetime.construct#refsect1-datetime.construct-parameters :
251
            // The $timezone parameter and the current timezone are ignored [ie. set to UTC] when the $time parameter [...] is a UNIX timestamp (e.g. @946684800) [...]
252
            $date = new \DateTime("@$dateInformation");
253
        } elseif (\is_string($dateInformation)) {
254
            // Add timezone explicitly here, so that it does not depend on the "current timezone".
255
            $date = new \DateTime($dateInformation, $timezone);
256
        }
257
258
        // Change timezone
259
        $date->setTimezone($timezone);
260
261
        return $date;
262
    }
263
264
    /**
265
     * Get the current date (normalized optimized for queries, because SIM_ACCESS_TIME is rounded to minutes)
266
     * in the current timezone.
267
     *
268
     * @return \DateTime
269
     */
270
    public static function getNow(): \DateTime
271
    {
272
        // NOTE that new \DateTime('@timestamp') does NOT work - @see comment in normalizeDateTimeSingle()
273
        // So we create a date string with timezone information first, and a \DateTime in the current server timezone then.
274
        return new \DateTime(date(\DateTime::ATOM, (int)$GLOBALS['SIM_ACCESS_TIME']), self::getTimeZone());
275
    }
276
277
    /**
278
     * Alias for resetTime.
279
     *
280
     * @see resetTime()
281
     *
282
     * @param int|string|\DateTimeInterface|null $dateInformation
283
     *
284
     * @return \DateTime
285
     */
286
    public static function getDayStart($dateInformation): \DateTime
287
    {
288
        return self::resetTime($dateInformation);
289
    }
290
291
    /**
292
     * Get the End of the given day.
293
     *
294
     * @param int|string|\DateTimeInterface|null $dateInformation
295
     *
296
     * @return \DateTime
297
     */
298
    public static function getDayEnd($dateInformation): \DateTime
299
    {
300
        $dateTime = self::getDayStart($dateInformation);
301
        $dateTime->setTime(23, 59, 59);
302
303
        return $dateTime;
304
    }
305
306
    /**
307
     * Converts DateTime objects for native dates, so that they are stored "as is".
308
     * This is required for Typo3 versions before 11, since they are formatted in UTC, but shouldn't.
309
     *
310
     * @param \DateTime|null $date
311
     *
312
     * @return \DateTime|null
313
     */
314
    public static function fixDateTimeForDb(?\DateTime $date): ?\DateTime
315
    {
316
        if ($date instanceof \DateTimeInterface) {
317
            $typo3Version = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Information\Typo3Version::class);
318
            if ($typo3Version->getMajorVersion() < 11) {
319
                $date = new \DateTime($date->format('Y-m-d\TH:i:s'), self::getUtcTimeZone());
320
            }
321
        }
322
323
        return $date;
324
    }
325
326
    /**
327
     * Converts the native date object from UTC to the local timezone.
328
     * This is required for Typo3 versions before 11, since the dates in the db are assumed as UTC, but aren't.
329
     *
330
     * @param \DateTime|null $date
331
     *
332
     * @return \DateTime|null
333
     */
334
    public static function fixDateTimeForExtbase(?\DateTime $date): ?\DateTime
335
    {
336
        if ($date instanceof \DateTimeInterface) {
337
            $typo3Version = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Information\Typo3Version::class);
338
            if ($typo3Version->getMajorVersion() < 11) {
339
                $date = (clone $date)->setTimezone(self::getUtcTimeZone());
340
                $date = new \DateTime($date->format('Y-m-d\TH:i:s'), self::getTimeZone());
341
            }
342
        }
343
344
        return $date;
345
    }
346
}
347