Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Date
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
6 / 6
12
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createIsoDate
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
2
 createIsoDateFromUnixTimestamp
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 getTrackingFileDateStart
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
 getTrackingFileDateEnd
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
2
 format
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * phpMyFAQ Date class.
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public License,
7 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
8 * obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * @package   phpMyFAQ
11 * @author    Thorsten Rinne <thorsten@phpmyfaq.de>
12 * @author    Matteo Scaramuccia <matteo@phpmyfaq.de>
13 * @copyright 2009-2026 phpMyFAQ Team
14 * @license   https://www.mozilla.org/MPL/2.0/ Mozilla Public License Version 2.0
15 * @link      https://www.phpmyfaq.de
16 * @since     2009-09-24
17 */
18
19declare(strict_types=1);
20
21namespace phpMyFAQ;
22
23use DateTime;
24use Exception;
25
26/**
27 * Class Date
28 *
29 * @package phpMyFAQ
30 */
31readonly class Date
32{
33    /**
34     * Constructor.
35     */
36    public function __construct(
37        private Configuration $configuration,
38    ) {
39    }
40
41    /**
42     * Converts a phpMyFAQ date format (YmdHi[...]) to a format similar to ISO 8601 standard.
43     *
44     * Example: "202501311530" -> "2025-01-31 15:30" (default format)
45     */
46    public static function createIsoDate(string $date, string $format = 'Y-m-d H:i', mixed $pmfFormat = null): string
47    {
48        // Back-compat: if the third param is explicitly false, interpret $date as Unix timestamp / strtotime string
49        if ($pmfFormat === false) {
50            return self::createIsoDateFromUnixTimestamp($date, $format);
51        }
52
53        $timestamp = strtotime(
54            substr($date, offset: 0, length: 4)
55                . '-'
56                . substr($date, offset: 4, length: 2)
57                . '-'
58                . substr($date, offset: 6, length: 2)
59                . ' '
60                . substr($date, offset: 8, length: 2)
61                . ':'
62                . substr($date, offset: 10, length: 2),
63        );
64
65        return date($format, (int) $timestamp);
66    }
67
68    /**
69     * Formats a Unix timestamp according to the given format (default similar to ISO 8601).
70     */
71    public static function createIsoDateFromUnixTimestamp(int|string $timestamp, string $format = 'Y-m-d H:i'): string
72    {
73        if (is_string($timestamp) && !ctype_digit($timestamp)) {
74            $parsed = strtotime($timestamp);
75            return date($format, (int) $parsed);
76        }
77
78        return date($format, (int) $timestamp);
79    }
80
81    /**
82     * Returns the start-of-day timestamp of a tracking filename (trackingDDMMYYYY).
83     */
84    public function getTrackingFileDateStart(string $file): int
85    {
86        if (Strings::strlen($file) >= 16) {
87            $day = Strings::substr($file, start: 8, length: 2);
88            $month = Strings::substr($file, start: 10, length: 2);
89            $year = Strings::substr($file, start: 12, length: 4);
90
91            return (int) gmmktime(
92                hour: 0,
93                minute: 0,
94                second: 0,
95                month: (int) $month,
96                day: (int) $day,
97                year: (int) $year,
98            );
99        }
100
101        return -1;
102    }
103
104    /**
105     * Returns the end-of-day timestamp of a tracking filename (trackingDDMMYYYY).
106     */
107    public function getTrackingFileDateEnd(string $file): int
108    {
109        if (Strings::strlen($file) >= 16) {
110            $day = Strings::substr($file, start: 8, length: 2);
111            $month = Strings::substr($file, start: 10, length: 2);
112            $year = Strings::substr($file, start: 12, length: 4);
113
114            return (int) gmmktime(
115                hour: 23,
116                minute: 59,
117                second: 59,
118                month: (int) $month,
119                day: (int) $day,
120                year: (int) $year,
121            );
122        }
123
124        return -1;
125    }
126
127    /**
128     * Returns date formatted according to user-defined format.
129     */
130    public function format(string $unformattedDate): string
131    {
132        try {
133            $dateTime = new DateTime($unformattedDate);
134            return $dateTime->format((string) $this->configuration->get(item: 'main.dateFormat'));
135        } catch (Exception $exception) {
136            $this->configuration->getLogger()->error($exception->getMessage());
137            return '';
138        }
139    }
140}