/** * This is the heart of the class * @param time $tLast last time at which the command was completed * @param time $tNow the reference time, usually the current time stamp * @param string $sSpec the specifier in the usual crontab format * @return boolean * TRUE if a timestamp exists between $tLast and $tNow fulfilling the $sSpec criteria. * returns FALSE otherwise */ function due($tLast, $tNow, $sSpec) { // this array describes the classic crontab format // for internal use the elements are listed in reverse order $arSeg = array("wday", "mon", "mday", "hours", "minutes"); // alternate crontab format includes year // this format is internally not (yet) supported!!! /* $arSeg = array("year", "wday", "mon", "mday", "hours", "minutes"); */ // this array contains the offset in case for the carry over status // see below for the determination of the carry over status $arPeriod = array("wday" => 7, "mon" => 12, "mday" => array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31), "hours" => 24, "minutes" => 60); $arTime = array("wday" => 604800, // 7 * 24 * 60 * 60 "mon" => 31536000, // 365 * 24 * 60 * 60 "mday" => array(31 * 86400, // 31 * 24 * 60 * 60 28 * 86400, 31 * 86400, 30 * 86400, 31 * 86400, 30 * 86400, 31 * 86400, 31 * 86400, 30 * 86400, 31 * 86400, 30 * 86400, 31 * 86400), "hours" => 86400, // 24 * 60 * 60 "minutes" => 3600); // 60 * 60 $iSeg = 0; // segment index $iCmpVal = 0; // compare value // these lines added in 0.2.5 $bStatus = FALSE; // procedure status $iPFaktor = 0; // period factor $iTFaktor = 0; // time factor if ($tNow == NULL) $tNow = time(); // this line added in version 0.2.2 if ($tLast == NULL) return FALSE; // convert strings to time if (is_string($tLast)) $tLast = strtotime($tLast); if (is_string($tNow)) $tNow = strtotime($tNow); if ($tNow < $tLast) return FALSE; // convert time variables to arrays $arLast = getdate($tLast); $arNow = getdate($tNow); $arSpec = array_reverse(explode(" ", $sSpec)); // walk through segments of crontab specifier for ($iSeg = 0; $iSeg < count($arSeg); $iSeg ++) { // obtain segment key $sSeg = $arSeg[$iSeg]; // does specifier segment contain '*'? if (strstr($arSpec[$iSeg], "*") != FALSE) { // week days need special treatment if ($sSeg == "wday") $iCmpVal = $arLast[$sSeg]; // use same segment of time reference else $iCmpVal = $arNow[$sSeg]; // specifier segment contains specific criteria } else { // get reference value $iCmpVal = cron::_nextLowerVal($arSpec[$iSeg], $arNow[$sSeg]); } /* endif */ // this section completely changed in 0.2.5 // obtain period factor $iPFactor = $arPeriod[$sSeg]; // numbers of days per month are always different ... if ($sSeg == "mday") $iPFactor = $iPFactor[$arLast["mon"]]; // obtain period time factor $iTFactor = $arTime[$sSeg]; // numbers of days per month are always different ... if ($sSeg == "mday") $iTFactor = $iTFactor[$arLast["mon"]]; // this is the decisive part of the function: if ($arLast[$sSeg] < $iCmpVal && $iCmpVal <= $arNow[$sSeg]) { $bStatus = TRUE; } if (strstr($arSpec[$iSeg], "*") == FALSE) { // next two lines changed in 0.2.7 if ((($bStatus == TRUE && $arNow[$sSeg] == $arLast[$sSeg]) || $arNow[$sSeg] < $arLast[$sSeg]) && $arLast[$sSeg] < $iCmpVal + $iPFactor && $iCmpVal + $iPFactor <= $arNow[$sSeg] + $iPFactor && $iCmpVal >= 0) { $bStatus = TRUE; } else if ($tNow > $tLast + $iTFactor) { $bStatus = TRUE; } // note that this condition causes a premature return: else if ($arLast[$sSeg] > $iCmpVal) { return FALSE; } else if ($iCmpVal < $arNow[$sSeg] && $iCmpVal == $arLast[$sSeg] ) { return FALSE; } } /* endif */ // end of section } /* endfor */ return $bStatus; }