[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
1 <?php 2 3 declare(strict_types=1); 4 5 namespace Cron; 6 7 use DateTimeInterface; 8 use DateTimeZone; 9 10 /** 11 * Hours field. Allows: * , / -. 12 */ 13 class HoursField extends AbstractField 14 { 15 /** 16 * {@inheritdoc} 17 */ 18 protected $rangeStart = 0; 19 20 /** 21 * {@inheritdoc} 22 */ 23 protected $rangeEnd = 23; 24 25 /** 26 * @var array|null Transitions returned by DateTimeZone::getTransitions() 27 */ 28 protected $transitions = null; 29 30 /** 31 * @var int|null Timestamp of the start of the transitions range 32 */ 33 protected $transitionsStart = null; 34 35 /** 36 * @var int|null Timestamp of the end of the transitions range 37 */ 38 protected $transitionsEnd = null; 39 40 /** 41 * {@inheritdoc} 42 */ 43 public function isSatisfiedBy(DateTimeInterface $date, $value, bool $invert): bool 44 { 45 $checkValue = (int) $date->format('H'); 46 $retval = $this->isSatisfied($checkValue, $value); 47 if ($retval) { 48 return $retval; 49 } 50 51 // Are we on the edge of a transition 52 $lastTransition = $this->getPastTransition($date); 53 if (($lastTransition !== null) && ($lastTransition["ts"] > ((int) $date->format('U') - 3600))) { 54 $dtLastOffset = clone $date; 55 $this->timezoneSafeModify($dtLastOffset, "-1 hour"); 56 $lastOffset = $dtLastOffset->getOffset(); 57 58 $dtNextOffset = clone $date; 59 $this->timezoneSafeModify($dtNextOffset, "+1 hour"); 60 $nextOffset = $dtNextOffset->getOffset(); 61 62 $offsetChange = $nextOffset - $lastOffset; 63 if ($offsetChange >= 3600) { 64 $checkValue -= 1; 65 return $this->isSatisfied($checkValue, $value); 66 } 67 if ((! $invert) && ($offsetChange <= -3600)) { 68 $checkValue += 1; 69 return $this->isSatisfied($checkValue, $value); 70 } 71 } 72 73 return $retval; 74 } 75 76 public function getPastTransition(DateTimeInterface $date): ?array 77 { 78 $currentTimestamp = (int) $date->format('U'); 79 if ( 80 ($this->transitions === null) 81 || ($this->transitionsStart < ($currentTimestamp + 86400)) 82 || ($this->transitionsEnd > ($currentTimestamp - 86400)) 83 ) { 84 // We start a day before current time so we can differentiate between the first transition entry 85 // and a change that happens now 86 $dtLimitStart = clone $date; 87 $dtLimitStart = $dtLimitStart->modify("-12 months"); 88 $dtLimitEnd = clone $date; 89 $dtLimitEnd = $dtLimitEnd->modify('+12 months'); 90 91 $this->transitions = $date->getTimezone()->getTransitions( 92 $dtLimitStart->getTimestamp(), 93 $dtLimitEnd->getTimestamp() 94 ); 95 if ($this->transitions === false) { 96 return null; 97 } 98 $this->transitionsStart = $dtLimitStart->getTimestamp(); 99 $this->transitionsEnd = $dtLimitEnd->getTimestamp(); 100 } 101 102 $nextTransition = null; 103 foreach ($this->transitions as $transition) { 104 if ($transition["ts"] > $currentTimestamp) { 105 continue; 106 } 107 108 if (($nextTransition !== null) && ($transition["ts"] < $nextTransition["ts"])) { 109 continue; 110 } 111 112 $nextTransition = $transition; 113 } 114 115 return ($nextTransition ?? null); 116 } 117 118 /** 119 * {@inheritdoc} 120 * 121 * @param string|null $parts 122 */ 123 public function increment(DateTimeInterface &$date, $invert = false, $parts = null): FieldInterface 124 { 125 $originalTimestamp = (int) $date->format('U'); 126 127 // Change timezone to UTC temporarily. This will 128 // allow us to go back or forwards and hour even 129 // if DST will be changed between the hours. 130 if (null === $parts || '*' === $parts) { 131 if ($invert) { 132 $date = $date->sub(new \DateInterval('PT1H')); 133 } else { 134 $date = $date->add(new \DateInterval('PT1H')); 135 } 136 137 $date = $this->setTimeHour($date, $invert, $originalTimestamp); 138 return $this; 139 } 140 141 $parts = false !== strpos($parts, ',') ? explode(',', $parts) : [$parts]; 142 $hours = []; 143 foreach ($parts as $part) { 144 $hours = array_merge($hours, $this->getRangeForExpression($part, 23)); 145 } 146 147 $current_hour = (int) $date->format('H'); 148 $position = $invert ? \count($hours) - 1 : 0; 149 $countHours = \count($hours); 150 if ($countHours > 1) { 151 for ($i = 0; $i < $countHours - 1; ++$i) { 152 if ((!$invert && $current_hour >= $hours[$i] && $current_hour < $hours[$i + 1]) || 153 ($invert && $current_hour > $hours[$i] && $current_hour <= $hours[$i + 1])) { 154 $position = $invert ? $i : $i + 1; 155 156 break; 157 } 158 } 159 } 160 161 $target = (int) $hours[$position]; 162 $originalHour = (int)$date->format('H'); 163 164 $originalDay = (int)$date->format('d'); 165 $previousOffset = $date->getOffset(); 166 167 if (! $invert) { 168 if ($originalHour >= $target) { 169 $distance = 24 - $originalHour; 170 $date = $this->timezoneSafeModify($date, "+{$distance} hours"); 171 172 $actualDay = (int)$date->format('d'); 173 $actualHour = (int)$date->format('H'); 174 if (($actualDay !== ($originalDay + 1)) && ($actualHour !== 0)) { 175 $offsetChange = ($previousOffset - $date->getOffset()); 176 $date = $this->timezoneSafeModify($date, "+{$offsetChange} seconds"); 177 } 178 179 $originalHour = (int)$date->format('H'); 180 } 181 182 $distance = $target - $originalHour; 183 $date = $this->timezoneSafeModify($date, "+{$distance} hours"); 184 } else { 185 if ($originalHour <= $target) { 186 $distance = ($originalHour + 1); 187 $date = $this->timezoneSafeModify($date, "-" . $distance . " hours"); 188 189 $actualDay = (int)$date->format('d'); 190 $actualHour = (int)$date->format('H'); 191 if (($actualDay !== ($originalDay - 1)) && ($actualHour !== 23)) { 192 $offsetChange = ($previousOffset - $date->getOffset()); 193 $date = $this->timezoneSafeModify($date, "+{$offsetChange} seconds"); 194 } 195 196 $originalHour = (int)$date->format('H'); 197 } 198 199 $distance = $originalHour - $target; 200 $date = $this->timezoneSafeModify($date, "-{$distance} hours"); 201 } 202 203 $date = $this->setTimeHour($date, $invert, $originalTimestamp); 204 205 $actualHour = (int)$date->format('H'); 206 if ($invert && ($actualHour === ($target - 1) || (($actualHour === 23) && ($target === 0)))) { 207 $date = $this->timezoneSafeModify($date, "+1 hour"); 208 } 209 210 return $this; 211 } 212 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |