Doriandj9 /
dorian-dates-aritmetic
| 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
Loading history...
|
|||
| 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 |