src/php/Arbit/Periodic/CronjobIterator.php
protected function generateTimetable( $yearOffset = 0 )
    {
        // Reset the current data arrays
        $this->monthAndDays = array();
        $this->hours        = array();
        $this->minutes      = array();

        $this->yearOffset = $yearOffset;
        $year = $this->year + $this->yearOffset;

        // If we are processing the year we are currently in we will need some
        // extra information ready for filtering events from the past
        if ( $this->yearOffset === 0 )
        {
            $currentMonth = (int)date( 'm', $this->getCurrentTime() );
            $currentDay   = (int)date( 'd', $this->getCurrentTime() );
        }

        // Read the columns and generate lists of possible dates
        $months  = $this->applyStepping(
            $this->extractRange( $this->attributes['month'], 1, 12 ),
            $this->extractStep( $this->attributes['month'] )
        );
        $days  = $this->applyStepping(
            $this->extractRange( $this->attributes['dayOfMonth'], 1, 31 ),
            $this->extractStep( $this->attributes['dayOfMonth'] )
        );
        $this->hours  = $this->applyStepping(
            $this->extractRange( $this->attributes['hour'], 0, 23 ),
            $this->extractStep( $this->attributes['hour'] )
        );
        $this->minutes  = $this->applyStepping(
            $this->extractRange( $this->attributes['minute'], 0, 59 ),
            $this->extractStep( $this->attributes['minute'] )
        );

        // If the current year is processed every month that lies before the
        // current one can be removed because it is definetly an event in the past
        if ( $this->yearOffset === 0 )
        {
            foreach ( $months as $nr => $month )
            {
                if ( $month < $currentMonth )
                {
                    unset( $months[$nr] );
                }
            }
        }

        // Combine the months and days into a single array to be able to handle
        // the dayOfWeek entries appropriately

        // There is one special case. If the dayOfWeek is specified, but the
        // dayOfMonth is not restricted (*), only the matching weekdays will
        // the used. Therefore the following processing can be skipped.
        if ( $this->attributes['dayOfMonth'] !== '*' || $this->attributes['dayOfWeek'] === '*' )
        {
            foreach( $months as $month )
            {
                foreach( $days as $day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }

                    if ( $this->isValidDate( $year, $month, $day ) === true )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Retrieve every day that matches the given dayOfWeek definition if it
         * is restricted in any way
         */
        if ( $this->attributes['dayOfWeek'] !== '*' )
        {
            $weekdays = $this->applyStepping(
                $this->extractRange( $this->attributes['dayOfWeek'], 0, 7 ),
                $this->extractStep( $this->attributes['dayOfWeek'] )
            );

            // Sanitize the weekday array for later processing by ISO-8601
            // weekday specification
            $weekdays = array_flip( $weekdays );
            if( array_key_exists( 0, $weekdays ) )
            {
                unset( $weekdays[0] );
                $weekdays[7] = true;
            }

            /*
             * To get a list of all dates which lie on the given weekdays we
             * loop through every possible date of the year and check for the
             * weekday. We need to take into account the month restriction
             * though.
             */
            foreach( $months as $month )
            {
                for( $day = 1; $day <= 31; ++$day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }


                    if ( $this->isValidDate( $year, $month, $day ) !== true )
                    {
                        break;
                    }

                    $isoWeekday = (int)date(
                        'N',
                        strtotime(
                            sprintf(
                                '%d-%02d-%02d',
                                $year,
                                $month,
                                $day
                            )
                        )
                    );
                    if ( array_key_exists( $isoWeekday, $weekdays ) )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Flip keys and values on the monthAndDays array and sort it to be easily
         * processable by foreach in the correct order
         */
        $this->monthAndDays = array_keys( $this->monthAndDays );
        sort( $this->monthAndDays );
    }
protected function generateTimetable( $yearOffset = 0 )
    {
        // Reset the current data arrays
        $this->monthAndDays = array();
        $this->hours        = array();
        $this->minutes      = array();

        $this->yearOffset = $yearOffset;
        $year = $this->year + $this->yearOffset;

        // If we are processing the year we are currently in we will need some
        // extra information ready for filtering events from the past
        if ( $this->yearOffset === 0 )
        {
            $currentMonth = (int)date( 'm', $this->getCurrentTime() );
            $currentDay   = (int)date( 'd', $this->getCurrentTime() );
        }

        // Read the columns and generate lists of possible dates
        $months  = $this->applyStepping(
            $this->extractRange( $this->attributes['month'], 1, 12 ),
            $this->extractStep( $this->attributes['month'] )
        );
        $days  = $this->applyStepping(
            $this->extractRange( $this->attributes['dayOfMonth'], 1, 31 ),
            $this->extractStep( $this->attributes['dayOfMonth'] )
        );
        $this->hours  = $this->applyStepping(
            $this->extractRange( $this->attributes['hour'], 0, 23 ),
            $this->extractStep( $this->attributes['hour'] )
        );
        $this->minutes  = $this->applyStepping(
            $this->extractRange( $this->attributes['minute'], 0, 59 ),
            $this->extractStep( $this->attributes['minute'] )
        );

        // If the current year is processed every month that lies before the
        // current one can be removed because it is definetly an event in the past
        if ( $this->yearOffset === 0 )
        {
            foreach ( $months as $nr => $month )
            {
                if ( $month < $currentMonth )
                {
                    unset( $months[$nr] );
                }
            }
        }

        // Combine the months and days into a single array to be able to handle
        // the dayOfWeek entries appropriately

        // There is one special case. If the dayOfWeek is specified, but the
        // dayOfMonth is not restricted (*), only the matching weekdays will
        // the used. Therefore the following processing can be skipped.
        if ( $this->attributes['dayOfMonth'] !== '*' || $this->attributes['dayOfWeek'] === '*' )
        {
            foreach( $months as $month )
            {
                foreach( $days as $day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }

                    if ( $this->isValidDate( $year, $month, $day ) === true )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Retrieve every day that matches the given dayOfWeek definition if it
         * is restricted in any way
         */
        if ( $this->attributes['dayOfWeek'] !== '*' )
        {
            $weekdays = $this->applyStepping(
                $this->extractRange( $this->attributes['dayOfWeek'], 0, 7 ),
                $this->extractStep( $this->attributes['dayOfWeek'] )
            );

            // Sanitize the weekday array for later processing by ISO-8601
            // weekday specification
            $weekdays = array_flip( $weekdays );
            if( array_key_exists( 0, $weekdays ) )
            {
                unset( $weekdays[0] );
                $weekdays[7] = true;
            }

            /*
             * To get a list of all dates which lie on the given weekdays we
             * loop through every possible date of the year and check for the
             * weekday. We need to take into account the month restriction
             * though.
             */
            foreach( $months as $month )
            {
                for( $day = 1; $day <= 31; ++$day )
                {
                    // Check if we are in the past
                    if ( $this->yearOffset === 0 )
                    {
                        // It is only useful to check this in the first year ;)
                        if ( $month === $currentMonth ) // Use currentMonth which was stored before
                        {
                            if ( $day < $currentDay )
                            {
                                continue;
                            }

                        }
                    }


                    if ( $this->isValidDate( $year, $month, $day ) !== true )
                    {
                        break;
                    }

                    $isoWeekday = (int)date(
                        'N',
                        strtotime(
                            sprintf(
                                '%d-%02d-%02d',
                                $year,
                                $month,
                                $day
                            )
                        )
                    );
                    if ( array_key_exists( $isoWeekday, $weekdays ) )
                    {
                        $this->monthAndDays[sprintf(
                            '%02d-%02d',
                            $month,
                            $day
                        )] = true;
                    }
                }
            }
        }

        /*
         * Flip keys and values on the monthAndDays array and sort it to be easily
         * processable by foreach in the correct order
         */
        $this->monthAndDays = array_keys( $this->monthAndDays );
        sort( $this->monthAndDays );
    }
Generate a timetable array containing the timestamps of this cronjob for
the currently processed year

@param int Offset in correlation to the current year to select the year
to process

@return void