1 | <?php |
||
2 | |||
3 | namespace Dates\Manejos; |
||
4 | |||
5 | use DateTime; |
||
6 | use InvalidArgumentException; |
||
7 | |||
8 | /** |
||
9 | * Es una clase que maneja fechas de forma facil |
||
10 | * |
||
11 | * Para usuarla hay dos parametros opcionales |
||
12 | * datetime que si no ingresa una fecha en formato string |
||
13 | * y no ingresa nada regresa la fecha actual |
||
14 | * el segundo parametro es la zono horaria si no ingresa una |
||
15 | * zona horaria que soporte PHP se ejecutara con la zona horaria |
||
16 | * por defecto del servidor zonas horarias soportadas por PHP @link<https://www.php.net/manual/es/timezones.php> |
||
17 | * revise su continente y luego escoga su continente y luego su cuidad y agreguelo como segundo argumento |
||
18 | * o a partir de PHP 8 puede agregar ese unico argumento como zoneHoraria:"America/Guayaquil" |
||
19 | * |
||
20 | * |
||
21 | * PHP version ^8.1 |
||
22 | * |
||
23 | * @author Dorian Armijos |
||
24 | * @link <> |
||
25 | * @category Dates |
||
26 | * @return DateTime |
||
27 | */ |
||
28 | |||
29 | class ArithmeticDates extends \DateTime |
||
30 | { |
||
31 | /** |
||
32 | * @var datetime |
||
33 | */ |
||
34 | private $datetime; |
||
35 | private $day; |
||
36 | private $hours; |
||
37 | private $minute; |
||
38 | private $seconds; |
||
39 | private $microseconds; |
||
40 | private $year; |
||
41 | private $mounth; |
||
42 | private $message; |
||
43 | private const REG_E = "/^([0-9]{4}\b)-([0][1-9]{1}\b|[1][0-2]{1}\b)-([0][1-9]{1}\b|[1-2][0-9]{1}\b|[3][0-1]{1}\b)/"; |
||
44 | /** |
||
45 | * |
||
46 | */ |
||
47 | 3 | public function __construct(string $datetime = 'now', string $zoneHoraria = null) |
|
48 | { |
||
49 | /** |
||
50 | * Los siguientes if realizar la tarea de identificar que sea una fecha valida |
||
51 | */ |
||
52 | |||
53 | 3 | if (strtolower($datetime) != 'now' && !preg_match(self::REG_E, $datetime)) { |
|
54 | throw new InvalidArgumentException('Error no ingreso una fecha correcta'); |
||
55 | } |
||
56 | /** |
||
57 | * Verifica que tenga agregada una zona horaria |
||
58 | */ |
||
59 | 3 | if ($zoneHoraria) { |
|
60 | 3 | date_default_timezone_set($zoneHoraria); |
|
61 | } |
||
62 | |||
63 | 3 | $this->datetime = new \DateTime($datetime); |
|
64 | 3 | parent::__construct($this->datetime->format('Y-m-d H:i:s')); |
|
65 | 3 | $this->day = $this->datetime->format('d'); |
|
66 | 3 | $this->hours = $this->datetime->format('H'); |
|
67 | 3 | $this->minute = $this->datetime->format('i'); |
|
68 | 3 | $this->seconds = $this->datetime->format('s'); |
|
69 | 3 | $this->microseconds = $this->datetime->format('u'); |
|
70 | 3 | $this->year = $this->datetime->format('Y'); |
|
71 | 3 | $this->mounth = $this->datetime->format('m'); |
|
72 | } |
||
73 | /** |
||
74 | * Este metodo permite aumentar los meses de la fecha actual |
||
75 | * |
||
76 | * @param int $numberMoth Es un entero que aumenta a la fecha el numero de meses este valor no puede ser > 12 o < 0 |
||
77 | */ |
||
78 | public function setMoth(int $numberMoth): void |
||
79 | { |
||
80 | if ($numberMoth > 12) { |
||
81 | $this->message = 'Desborda el numero de meses permitidos'; |
||
82 | throw new InvalidArgumentException($this->message); |
||
83 | } |
||
84 | if ($numberMoth < 0) { |
||
85 | $this->message = 'Error no se puede aumentar meses negativos' ; |
||
86 | throw new InvalidArgumentException($this->message); |
||
87 | } |
||
88 | |||
89 | $mounthChange = intval($this->mounth, 10); |
||
90 | $calculo = $mounthChange + $numberMoth; |
||
91 | $moreYear = $this->year; |
||
92 | $moreMounth = $calculo; |
||
93 | if ($calculo > 12) { |
||
94 | $this->setYear(1); |
||
95 | $moreYear = $this->year; |
||
96 | $moreMounth = $calculo - 12; |
||
97 | } |
||
98 | if ($moreMounth < 10) { |
||
99 | $moreMounth = '0' . $moreMounth; |
||
100 | } |
||
101 | $dateFormat = $moreYear . '-' . $moreMounth . '-' . $this->day . ' '; |
||
102 | $timeFormat = $this->hours . ':' . $this->minute . ':' . $this->seconds . '.' . $this->microseconds; |
||
103 | $formatDate = $dateFormat . $timeFormat; |
||
104 | $this->year = $moreYear; |
||
105 | $this->mounth = $moreMounth; |
||
106 | $this->datetime = new \DateTime($formatDate); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * Este metodo permite aumentar los años a la fecha actual |
||
111 | * |
||
112 | * @param int $year aumenta en años la fecha actual |
||
113 | * @return void |
||
114 | */ |
||
115 | |||
116 | public function setYear(int $year) |
||
117 | { |
||
118 | if ($year < 0) { |
||
119 | $this->message = 'Error no se puede aumentar años negativos'; |
||
120 | throw new InvalidArgumentException($this->message); |
||
121 | } |
||
122 | $this->year = intval($this->year, 10) + $year; |
||
123 | $dateFormat = $this->year . '-' . $this->mounth . '-' . $this->day . ' '; |
||
124 | $timeFormat = $this->hours . ':' . $this->minute . ':' . $this->seconds . '.' . $this->microseconds; |
||
125 | $formatDate = $dateFormat . $timeFormat; |
||
126 | $this->datetime = new \DateTime($formatDate); |
||
127 | } |
||
128 | |||
129 | /** |
||
130 | * Este metodo sirve para aumentar los dias de la fecha |
||
131 | * |
||
132 | * @param int $day Son los dias que puede aumentar a la fecha este valor no puede ser > 31 o < 0 |
||
133 | * @return void |
||
134 | */ |
||
135 | |||
136 | public function setDay(int $day): void |
||
137 | { |
||
138 | if ($day > 31 || $day < 0) { |
||
139 | $this->message = 'Error el valor no puede ser mayor a 31 o menor a 0'; |
||
140 | throw new InvalidArgumentException($this->message); |
||
141 | } |
||
142 | $numberDays = $this->getMothDay($this->mounth); |
||
143 | $daysCalculo = intval($this->day) + $day; |
||
144 | $moreDays = $daysCalculo; |
||
145 | $moreMounth = $this->mounth; |
||
146 | if ($daysCalculo > $numberDays) { |
||
147 | $this->setMoth(1); |
||
148 | $moreMounth = $this->mounth; |
||
149 | $daysmorMount = $this->getMothDay($moreMounth); |
||
150 | if ($daysCalculo > $daysmorMount) { |
||
151 | $this->setMoth(1); |
||
152 | $moreMounth = $this->mounth; |
||
153 | $moreDays = $daysCalculo - $daysmorMount; |
||
154 | } else { |
||
155 | $moreDays = $daysmorMount - $daysCalculo; |
||
156 | } |
||
157 | } |
||
158 | |||
159 | if ($moreDays < 10) { |
||
160 | $moreDays = '0' . $moreDays; |
||
161 | } |
||
162 | $dateFormat = $this->year . '-' . $moreMounth . '-' . $moreDays . ' '; |
||
163 | $timeFormat = $this->hours . ':' . $this->minute . ':' . $this->seconds . '.' . $this->microseconds; |
||
164 | $formatDate = $dateFormat . $timeFormat; |
||
165 | $this->datetime = new \DateTime($formatDate); |
||
166 | $this->mounth = $moreMounth; |
||
167 | $this->day = $moreDays; |
||
168 | } |
||
169 | |||
170 | |||
171 | /** |
||
172 | * Este metodo permite aumenta a la fecha las horas los minutos y los segundos |
||
173 | * |
||
174 | * @param int $hours Son las horas que se aumneta a la fecha el valor no puede ser > 24 y < 0 |
||
175 | * @param int $minutes Son los minutos que se aumenta a la fecha el valor no puede ser > 60 y < 0 |
||
176 | * @param int $seconds Son los segundos que se aumenta a la fecha el valor no puede ser > 60 y < 0 |
||
177 | * @return void |
||
178 | */ |
||
179 | 1 | public function setHourMinutesSeconds(int $hours, int $minutes, int $seconds = 00): void |
|
180 | { |
||
181 | 1 | if ($hours > 24 || $hours < 0) { |
|
182 | $this->message = 'Error las horas no deben sobrepasar el valor de 24 o menor a 0'; |
||
183 | throw new InvalidArgumentException($this->message); |
||
184 | } |
||
185 | 1 | if ($minutes > 60 || $minutes < 0) { |
|
186 | $this->message = 'Error los minitos no deben sobrepasar los 60 o ser menores a 0'; |
||
187 | throw new InvalidArgumentException($this->message); |
||
188 | } |
||
189 | 1 | if ($seconds > 60 || $seconds < 0) { |
|
190 | $this->message = 'Error los segundos no deben sobrepasar los 60 o ser menores a 0'; |
||
191 | throw new InvalidArgumentException(); |
||
192 | } |
||
193 | |||
194 | 1 | $hoursCalculo = intval($this->hours) + $hours; |
|
195 | 1 | $minutesCalculo = intval($this->minute) + $minutes; |
|
196 | 1 | $secondsCalculo = $seconds; |
|
197 | 1 | if ($seconds > 0) { |
|
198 | $secondsCalculo = intval($this->seconds) + $seconds; |
||
199 | } |
||
200 | /** |
||
201 | * Calculamos las horas |
||
202 | * Calculamos los minitos |
||
203 | * Calculamos los segundos |
||
204 | */ |
||
205 | 1 | $moreHours = $hoursCalculo; |
|
0 ignored issues
–
show
Unused Code
introduced
by
![]() |
|||
206 | 1 | $moreMinites = $minutesCalculo; |
|
207 | 1 | $moreSeconds = $secondsCalculo; |
|
208 | |||
209 | 1 | if ($secondsCalculo > 60) { |
|
210 | $minutesCalculo += 1; |
||
211 | $moreSeconds = $secondsCalculo - 60; |
||
212 | } |
||
213 | 1 | if ($moreSeconds < 9) { |
|
214 | 1 | $moreSeconds = '0' . $moreSeconds; |
|
215 | } |
||
216 | |||
217 | 1 | if ($minutesCalculo > 60) { |
|
218 | $hoursCalculo += 1; |
||
219 | $moreMinites = $minutesCalculo - 60; |
||
220 | } |
||
221 | 1 | if ($moreMinites < 9) { |
|
222 | 1 | $moreMinites = '0' . $moreMinites; |
|
223 | } |
||
224 | |||
225 | 1 | $moreDays = $this->day; |
|
226 | 1 | if ($hoursCalculo > 24) { |
|
227 | $this->setDay(1); |
||
228 | $moreDays = $this->day; |
||
229 | $moreHours = $hoursCalculo - 24; |
||
230 | } |
||
231 | 1 | $moreHours = $hoursCalculo; |
|
232 | 1 | if ($moreHours < 9) { |
|
233 | $moreHours = '0' . $moreHours; |
||
234 | } |
||
235 | 1 | if (intval($moreMinites) == 60 && intval($moreSeconds) == 00) { |
|
236 | $moreMinites = '59'; |
||
237 | $moreSeconds = '60'; |
||
238 | } |
||
239 | 1 | $dateFormat = $this->year . '-' . $this->mounth . '-' . $moreDays . ' '; |
|
240 | 1 | $timeFormat = $moreHours . ':' . $moreMinites . ':' . $moreSeconds; |
|
241 | 1 | $formatDate = $dateFormat . $timeFormat; |
|
242 | 1 | $this->datetime = new \DateTime($formatDate); |
|
243 | 1 | $this->day = $moreDays; |
|
244 | 1 | $this->hours = $moreHours; |
|
245 | 1 | $this->minute = $moreMinites; |
|
246 | 1 | $this->seconds = $moreSeconds; |
|
247 | } |
||
248 | |||
249 | /** |
||
250 | * Permite encontrar cuantos dias tiene el mes a umentar |
||
251 | * |
||
252 | * @param string $indexMounth Es el indece del mes que regresa el numero de dias que tiene |
||
253 | * @return int |
||
254 | */ |
||
255 | private function getMothDay(string $indexMounth): int |
||
256 | { |
||
257 | $mounthDays = [31,28,31,30,31,30,31,31,30,31,30,31]; |
||
258 | if ($this->leapYear()) { |
||
259 | $mounthDays = [31,29,31,30,31,30,31,31,30,31,30,31]; |
||
260 | } |
||
261 | |||
262 | return $mounthDays[intval($indexMounth) - 1]; |
||
263 | } |
||
264 | /** |
||
265 | * Metodo para saber si una año es bisiesto y es febrero |
||
266 | * |
||
267 | * @return bool |
||
268 | */ |
||
269 | |||
270 | private function leapYear(): bool |
||
271 | { |
||
272 | return date('L', strtotime($this->datetime->format('Y-m-d'))) && intval($this->mounth) == 2 ; |
||
273 | } |
||
274 | /** |
||
275 | * Esta funcion regresa el resultado final de haber aplicado los metodos |
||
276 | * |
||
277 | * @return DateTime|ArithmeticDates |
||
278 | */ |
||
279 | 1 | public function getResult(): DateTime|ArithmeticDates |
|
280 | { |
||
281 | 1 | return $this->datetime; |
|
282 | } |
||
283 | |||
284 | /** |
||
285 | * Este metodo estatico permite verificar si una fecha en especifo se encentra dentro de un rango de fechas |
||
286 | * |
||
287 | * @param DateTime|ArithmeticDates $start Es el intervalo inicial |
||
288 | * @param DateTime|ArithmeticDates $end Es el intervalo final |
||
289 | * @param DateTime|ArithmeticDates $date Es la fecha a comprobar si se encuentra en ese intervalo de $start a $end |
||
290 | * @return bool |
||
291 | */ |
||
292 | |||
293 | 1 | public static function hasInterval( |
|
294 | DateTime|ArithmeticDates $start, |
||
295 | DateTime|ArithmeticDates $end, |
||
296 | DateTime|ArithmeticDates $date |
||
297 | ): bool |
||
298 | { |
||
299 | 1 | $startInterval = $start->getTimestamp(); |
|
300 | 1 | $endInterval = $end->getTimestamp(); |
|
301 | |||
302 | 1 | return $date->getTimestamp() >= $startInterval && $date->getTimestamp() <= $endInterval; |
|
303 | } |
||
304 | } |
||
305 |