public function oldestDateAdded($duration, string $timezone = null, \DateTime $dateSend = null)
    {
        if (!$timezone) {
            $timezone = date_default_timezone_get();
        }
        if (is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        }
        if ($dateSend) {
            $oldest = clone $dateSend;
            $oldest->setTimezone($timezone);
        } else {
            $oldest = new \DateTime('now', $timezone);
        }
        if (0 !== strpos($duration, 'P')) {
            // Non-rolling interval, go to previous interval segment.
            // Will only work for simple (singular) intervals.
            switch (strtoupper(substr($duration, -1))) {
                case 'Y':
                    $oldest->modify('next year jan 1 midnight');
                    break;
                case 'M':
                    $oldest->modify('first day of next month midnight');
                    break;
                case 'W':
                    $oldest->modify('sunday next week midnight');
                    break;
                case 'D':
                    $oldest->modify('tomorrow midnight');
                    break;
            }
            // Add P so that we can now use standard interval
            $duration = 'P'.$duration;
        }
        try {
            $interval = new \DateInterval($duration);
        } catch (\Exception $e) {
            // Default to monthly if the interval is faulty.
            $interval = new \DateInterval('P1M');
        }
        $oldest->sub($interval);

        return $oldest;
    }
public function oldestDateAdded($duration, string $timezone = null, \DateTime $dateSend = null)
    {
        if (!$timezone) {
            $timezone = date_default_timezone_get();
        }
        if (is_string($timezone)) {
            $timezone = new \DateTimeZone($timezone);
        }
        if ($dateSend) {
            $oldest = clone $dateSend;
            $oldest->setTimezone($timezone);
        } else {
            $oldest = new \DateTime('now', $timezone);
        }
        if (0 !== strpos($duration, 'P')) {
            // Non-rolling interval, go to previous interval segment.
            // Will only work for simple (singular) intervals.
            switch (strtoupper(substr($duration, -1))) {
                case 'Y':
                    $oldest->modify('next year jan 1 midnight');
                    break;
                case 'M':
                    $oldest->modify('first day of next month midnight');
                    break;
                case 'W':
                    $oldest->modify('sunday next week midnight');
                    break;
                case 'D':
                    $oldest->modify('tomorrow midnight');
                    break;
            }
            // Add P so that we can now use standard interval
            $duration = 'P'.$duration;
        }
        try {
            $interval = new \DateInterval($duration);
        } catch (\Exception $e) {
            // Default to monthly if the interval is faulty.
            $interval = new \DateInterval('P1M');
        }
        $oldest->sub($interval);

        return $oldest;
    }
public function oldestDateAdded ( $ duration , string $ timezone = null , \ DateTime $ dateSend = null ) { if ( ! $ timezone ) { $ timezone = date_default_timezone_get ( ) ; } if ( is_string ( $ timezone ) ) { $ timezone = new \ DateTimeZone ( $ timezone ) ; } if ( $ dateSend ) { $ oldest = clone $ dateSend ; $ oldest -> setTimezone ( $ timezone ) ; } else { $ oldest = new \ DateTime ( 'now' , $ timezone ) ; } if ( 0 !== strpos ( $ duration , 'P' ) ) { // Non-rolling interval, go to previous interval segment. // Will only work for simple (singular) intervals. switch ( strtoupper ( substr ( $ duration , - 1 ) ) ) { case 'Y' : $ oldest -> modify ( 'next year jan 1 midnight' ) ; break ; case 'M' : $ oldest -> modify ( 'first day of next month midnight' ) ; break ; case 'W' : $ oldest -> modify ( 'sunday next week midnight' ) ; break ; case 'D' : $ oldest -> modify ( 'tomorrow midnight' ) ; break ; } // Add P so that we can now use standard interval $ duration = 'P' . $ duration ; } try { $ interval = new \ DateInterval ( $ duration ) ; } catch ( \ Exception $ e ) { // Default to monthly if the interval is faulty. $ interval = new \ DateInterval ( 'P1M' ) ; } $ oldest -> sub ( $ interval ) ; return $ oldest ; }
Support non-rolling durations when P is not prefixing.

@param                $duration
@param string|null    $timezone
@param \DateTime|null $dateSend

@return \DateTime

@throws \Exception
Support non - rolling durations when P is not prefixing .