DateTimeHelper::compare()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
3
/*
4
 * This file is part of the core-library package.
5
 *
6
 * (c) 2018 WEBEWEB
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace WBW\Library\Core\Argument\Helper;
13
14
use DateTime;
15
use InvalidArgumentException;
16
use Symfony\Component\Yaml\Yaml;
17
use WBW\Library\Core\Argument\Exception\DateArgumentException;
18
19
/**
20
 * Date/time helper.
21
 *
22
 * @author webeweb <https://github.com/webeweb/>
23
 * @package WBW\Library\Core\Argument\Helper
24
 */
25
class DateTimeHelper {
26
27
    /**
28
     * Compare two date/time.
29
     *
30
     * @param DateTime $a The date/time A.
31
     * @param DateTime $b The date/time B.
32
     * @return int Returns
33
     *  -1: if the date/time A is lesser than date/time B
34
     *   0: if the date/time are equals.
35
     *   1: if the date/time A is greater than date/time B
36
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
37
     */
38
    public static function compare(DateTime $a, DateTime $b): int {
39
        if (true === static::isLessThan($a, $b)) {
40
            return -1;
41
        }
42
        if (true === static::isGreaterThan($a, $b)) {
43
            return 1;
44
        }
45
        return 0;
46
    }
47
48
    /**
49
     * Compare tow date/time zones.
50
     *
51
     * @param DateTime $a The date/time A.
52
     * @param DateTime $b The date/time B.
53
     * @return void
54
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
55
     */
56
    protected static function compareZone(DateTime $a, DateTime $b): void {
57
        if (false === DateTimeZoneHelper::equals($a->getTimezone(), $b->getTimezone())) {
58
            throw new InvalidArgumentException("The two date/times does not have the same time zone");
59
        }
60
    }
61
62
    /**
63
     * Determines if two date/time are equals.
64
     *
65
     * @param DateTime $a The date/time A.
66
     * @param DateTime $b The date/time B.
67
     * @return bool Returns true in case o success, false otherwise.
68
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
69
     */
70
    public static function equals(DateTime $a, DateTime $b): bool {
71
        return 0 === static::compare($a, $b);
72
    }
73
74
    /**
75
     * Get a day number.
76
     *
77
     * @param DateTime $dateTime The date/time.
78
     * @return int Returns the day number between 1 and 7 with monday equals to 1.
79
     */
80
    public static function getDayNumber(DateTime $dateTime): int {
81
        return intval($dateTime->format("N"));
82
    }
83
84
    /**
85
     * Get the duration.
86
     *
87
     * @param DateTime $a The date/time A.
88
     * @param DateTime $b The date/time B.
89
     * @return int Returns the duration.
90
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
91
     */
92
    public static function getDuration(DateTime $a, DateTime $b): int {
93
        static::compareZone($a, $b);
94
        return $b->getTimestamp() - $a->getTimestamp();
95
    }
96
97
    /**
98
     * Get the greater date/time.
99
     *
100
     * @param DateTime $a The date/time A.
101
     * @param DateTime $b The date/time B.
102
     * @return DateTime Returns the greater date/time.
103
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
104
     */
105
    public static function getGreater(DateTime $a, DateTime $b): DateTime {
106
        return 0 <= static::compare($a, $b) ? $a : $b;
107
    }
108
109
    /**
110
     * Get a month number.
111
     *
112
     * @param DateTime $dateTime The date/time.
113
     * @return int Returns the month number.
114
     */
115
    public static function getMonthNumber(DateTime $dateTime): int {
116
        return intval($dateTime->format("m"));
117
    }
118
119
    /**
120
     * Get the smaller date/time.
121
     *
122
     * @param DateTime $a The date/time A.
123
     * @param DateTime $b The date/time B.
124
     * @return DateTime Returns the smaller date/time.
125
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
126
     */
127
    public static function getSmaller(DateTime $a, DateTime $b): DateTime {
128
        return 0 <= static::compare($a, $b) ? $b : $a;
129
    }
130
131
    /**
132
     * Get a week number.
133
     *
134
     * @param DateTime $dateTime The date/time.
135
     * @return int Returns the week number.
136
     */
137
    public static function getWeekNumber(DateTime $dateTime): int {
138
        return intval($dateTime->format("W"));
139
    }
140
141
    /**
142
     * Get a week number to apply with a schedule.
143
     * <p>
144
     * For example:
145
     * We have a schedule etablished over 5 weeks.
146
     * We start the schedule with the week number 1.
147
     * If the current date is 2018-01-01 and the start date is 2018-01-01, the week number is 1
148
     * If the current date is 2018-01-08 and the start date is 2018-01-01, the week number is 2
149
     * etc.
150
     * We start the schedule with the week number 3.
151
     * If the current date is 2018-01-01 and the start date is 2018-01-01, the week number is 3
152
     * If the current date is 2018-01-08 and the start date is 2018-01-01, the week number is 4
153
     * etc.
154
     * </p>
155
     *
156
     * @param DateTime $date The date.
157
     * @param DateTime $startDate The start date.
158
     * @param int $weekCount The week count.
159
     * @param int $weekOffset The week offset.
160
     * @return int Returns the week number to apply between 1 and $weekCount.
161
     */
162
    public static function getWeekNumberToApply(DateTime $date, DateTime $startDate, int $weekCount, int $weekOffset = 1): int {
163
164
        if ($weekCount <= 0 || $weekOffset <= 0 || $weekCount < $weekOffset) {
165
            return -1;
166
        }
167
168
        $result = intval($date->diff($startDate)->d / 7);
169
        $result %= $weekCount;
170
        $result += $weekOffset;
171
        if ($weekCount < $result) {
172
            $result -= $weekCount;
173
        }
174
175
        return $result;
176
    }
177
178
    /**
179
     * Get a year number.
180
     *
181
     * @param DateTime $dateTime The date/time.
182
     * @return int Returns the year number.
183
     */
184
    public static function getYearNumber(DateTime $dateTime): int {
185
        return intval($dateTime->format("Y"));
186
    }
187
188
    /**
189
     * Determines if a date/time is between date/time A and date/time B.
190
     *
191
     * @param DateTime $dateTime The date/time.
192
     * @param DateTime $a The date/time A.
193
     * @param DateTime $b The date/time B.
194
     * @return bool Returns true in case of success, false otherwise.
195
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
196
     */
197
    public static function isBetween(DateTime $dateTime, DateTime $a, DateTime $b): bool {
198
        static::compareZone($a, $b);
199
        $c1 = $a->getTimestamp() <= $dateTime->getTimestamp();
200
        $c2 = $dateTime->getTimestamp() <= $b->getTimestamp();
201
        return $c1 && $c2;
202
    }
203
204
    /**
205
     * Determines if a value is a date.
206
     *
207
     * @param mixed $value The value.
208
     * @return void
209
     * @throws DateArgumentException Throws a Date argument exception if the value is not of expected type.
210
     */
211
    public static function isDate($value): void {
212
        if (false === strtotime($value)) {
213
            throw new DateArgumentException($value);
214
        }
215
    }
216
217
    /**
218
     * Determines if date/time A is greater than date/time B.
219
     *
220
     * @param DateTime $a The date/time A.
221
     * @param DateTime $b The date/time B.
222
     * @return bool Returns true in case of success, false otherwise.
223
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
224
     */
225
    public static function isGreaterThan(DateTime $a, DateTime $b): bool {
226
        static::compareZone($a, $b);
227
        return $a->getTimestamp() > $b->getTimestamp();
228
    }
229
230
    /**
231
     * Detremines if date/time A is less than date/time B.
232
     *
233
     * @param DateTime $a The date/time A.
234
     * @param DateTime $b The date/time B.
235
     * @return bool Returns true in case of success, false otherwise.
236
     * @throws InvalidArgumentException Throws an illegal argument exception if the two date/time does not have the same time zone.
237
     */
238
    public static function isLessThan(DateTime $a, DateTime $b): bool {
239
        static::compareZone($a, $b);
240
        return $a->getTimestamp() < $b->getTimestamp();
241
    }
242
243
    /**
244
     * Translate the weekday part.
245
     *
246
     * @param string $date The date.
247
     * @param string $locale The locale.
248
     * @return string Returns the weekday part translated.
249
     */
250
    public static function translateWeekday(string $date, $locale = "en"): string {
251
252
        $messages = __DIR__ . "/../../Resources/translations/messages.%locale%.yml";
253
        $filename = str_replace("%locale%", $locale, $messages);
254
255
        if (false === file_exists($filename)) {
256
            $filename = str_replace("%locale%", "en", $messages);
257
        }
258
259
        $translations = Yaml::parse(file_get_contents(realpath($filename)));
260
261
        return str_ireplace(array_keys($translations["weekdays"]), array_values($translations["weekdays"]), $date);
262
    }
263
}
264