[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/vendor/dragonmantank/cron-expression/src/Cron/ -> HoursField.php (source)

   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  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer