Вход Регистрация
Файл: vendor/dragonmantank/cron-expression/src/Cron/HoursField.php
Строк: 252
<?php

declare(strict_types=1);

namespace 
Cron;

use 
DateTimeInterface;
use 
DateTimeZone;

/**
 * Hours field.  Allows: * , / -.
 */
class HoursField extends AbstractField
{
    
/**
     * {@inheritdoc}
     */
    
protected $rangeStart 0;

    
/**
     * {@inheritdoc}
     */
    
protected $rangeEnd 23;

    
/**
     * @var array|null Transitions returned by DateTimeZone::getTransitions()
     */
    
protected $transitions = [];

    
/**
     * @var int|null Timestamp of the start of the transitions range
     */
    
protected $transitionsStart null;

    
/**
     * @var int|null Timestamp of the end of the transitions range
     */
    
protected $transitionsEnd null;

    
/**
     * {@inheritdoc}
     */
    
public function isSatisfiedBy(DateTimeInterface $date$valuebool $invert): bool
    
{
        
$checkValue = (int) $date->format('H');
        
$retval $this->isSatisfied($checkValue$value);
        if (
$retval) {
            return 
$retval;
        }

        
// Are we on the edge of a transition
        
$lastTransition $this->getPastTransition($date);
        if ((
$lastTransition !== null) && ($lastTransition["ts"] > ((int) $date->format('U') - 3600))) {
            
$dtLastOffset = clone $date;
            
$this->timezoneSafeModify($dtLastOffset"-1 hour");
            
$lastOffset $dtLastOffset->getOffset();

            
$dtNextOffset = clone $date;
            
$this->timezoneSafeModify($dtNextOffset"+1 hour");
            
$nextOffset $dtNextOffset->getOffset();

            
$offsetChange $nextOffset $lastOffset;
            if (
$offsetChange >= 3600) {
                
$checkValue -= 1;
                return 
$this->isSatisfied($checkValue$value);
            }
            if ((! 
$invert) && ($offsetChange <= -3600)) {
                
$checkValue += 1;
                return 
$this->isSatisfied($checkValue$value);
            }
        }

        return 
$retval;
    }

    public function 
getPastTransition(DateTimeInterface $date): ?array
    {
        
$currentTimestamp = (int) $date->format('U');
        if (
            (
$this->transitions === null)
            || (
$this->transitionsStart < ($currentTimestamp 86400))
            || (
$this->transitionsEnd > ($currentTimestamp 86400))
        ) {
            
// We start a day before current time so we can differentiate between the first transition entry
            // and a change that happens now
            
$dtLimitStart = clone $date;
            
$dtLimitStart $dtLimitStart->modify("-12 months");
            
$dtLimitEnd = clone $date;
            
$dtLimitEnd $dtLimitEnd->modify('+12 months');

            
$this->transitions $date->getTimezone()->getTransitions(
                
$dtLimitStart->getTimestamp(),
                
$dtLimitEnd->getTimestamp()
            );
            if (empty(
$this->transitions)) {
                return 
null;
            }
            
$this->transitionsStart $dtLimitStart->getTimestamp();
            
$this->transitionsEnd $dtLimitEnd->getTimestamp();
        }

        
$nextTransition null;
        foreach (
$this->transitions as $transition) {
            if (
$transition["ts"] > $currentTimestamp) {
                continue;
            }

            if ((
$nextTransition !== null) && ($transition["ts"] < $nextTransition["ts"])) {
                continue;
            }

            
$nextTransition $transition;
        }

        return (
$nextTransition ?? null);
    }

    
/**
     * {@inheritdoc}
     *
     * @param string|null                  $parts
     */
    
public function increment(DateTimeInterface &$date$invert false$parts null): FieldInterface
    
{
        
$originalTimestamp = (int) $date->format('U');

        
// Change timezone to UTC temporarily. This will
        // allow us to go back or forwards and hour even
        // if DST will be changed between the hours.
        
if (null === $parts || '*' === $parts) {
            if (
$invert) {
                
$date $date->sub(new DateInterval('PT1H'));
            } else {
                
$date $date->add(new DateInterval('PT1H'));
            }

            
$date $this->setTimeHour($date$invert$originalTimestamp);
            return 
$this;
        }

        
$parts false !== strpos($parts',') ? explode(','$parts) : [$parts];
        
$hours = [];
        foreach (
$parts as $part) {
            
$hours array_merge($hours$this->getRangeForExpression($part23));
        }

        
$current_hour = (int) $date->format('H');
        
$position $invert count($hours) - 0;
        
$countHours count($hours);
        if (
$countHours 1) {
            for (
$i 0$i $countHours 1; ++$i) {
                if ((!
$invert && $current_hour >= $hours[$i] && $current_hour $hours[$i 1]) ||
                    (
$invert && $current_hour $hours[$i] && $current_hour <= $hours[$i 1])) {
                    
$position $invert $i $i 1;

                    break;
                }
            }
        }

        
$target = (int) $hours[$position];
        
$originalHour = (int)$date->format('H');

        
$originalDay = (int)$date->format('d');
        
$previousOffset $date->getOffset();

        if (! 
$invert) {
            if (
$originalHour >= $target) {
                
$distance 24 $originalHour;
                
$date $this->timezoneSafeModify($date"+{$distance} hours");

                
$actualDay = (int)$date->format('d');
                
$actualHour = (int)$date->format('H');
                if ((
$actualDay !== ($originalDay 1)) && ($actualHour !== 0)) {
                    
$offsetChange = ($previousOffset $date->getOffset());
                    
$date $this->timezoneSafeModify($date"+{$offsetChange} seconds");
                }

                
$originalHour = (int)$date->format('H');
            }

            
$distance $target $originalHour;
            
$date $this->timezoneSafeModify($date"+{$distance} hours");
        } else {
            if (
$originalHour <= $target) {
                
$distance = ($originalHour 1);
                
$date $this->timezoneSafeModify($date"-" $distance " hours");

                
$actualDay = (int)$date->format('d');
                
$actualHour = (int)$date->format('H');
                if ((
$actualDay !== ($originalDay 1)) && ($actualHour !== 23)) {
                    
$offsetChange = ($previousOffset $date->getOffset());
                    
$date $this->timezoneSafeModify($date"+{$offsetChange} seconds");
                }

                
$originalHour = (int)$date->format('H');
            }

            
$distance $originalHour $target;
            
$date $this->timezoneSafeModify($date"-{$distance} hours");
        }

        
$date $this->setTimeHour($date$invert$originalTimestamp);

        
$actualHour = (int)$date->format('H');
        if (
$invert && ($actualHour === ($target 1) || (($actualHour === 23) && ($target === 0)))) {
            
$date $this->timezoneSafeModify($date"+1 hour");
        }

        return 
$this;
    }
}
Онлайн: 0
Реклама