diff --git a/workflow/engine/classes/class.dates.php b/workflow/engine/classes/class.dates.php
index d1ff56fd1..5d9dea6da 100755
--- a/workflow/engine/classes/class.dates.php
+++ b/workflow/engine/classes/class.dates.php
@@ -1,7 +1,8 @@
.
+ * along with this program. If not, see .
*
* For more information, contact Colosa Inc, 2566 Le Jeune Rd.,
* Coral Gables, FL, 33134, USA, or email info@colosa.com.
* /
-
-/*
+ *
+ * /*
* Created on 21/01/2008
* This class is used for handling dates
*
* @author David Callizaya
*/
-
- require_once ( "classes/model/TaskPeer.php" );
- require_once ( "classes/model/HolidayPeer.php" );
-
- /**
- * @package workflow.engine.classes
- */
-class dates {
- private $holidays = array();
- private $weekends = array();
- private $range = array();
- private $skipEveryYear = true;
- private $calendarDays = false; //by default we are using working days
- private $hoursPerDay = 8; //you should change this
-
-
- /**
- * Function that calculate a final date based on $sInitDate and $iDuration
- * This function also uses a Calendar component (class.calendar.php) where all the definition of
- * a User, task, Process or default calendar is defined. base on that information is possible to setup different calendars
- * and apply them to a task, process or user. Each calendar have Working Days, Business Hours and Holidays
- *
- * @name calculateDate
- * @access public
- * @author Hugo Loza
- * @param date $sInitDate
- * @param double $iDuration
- * @param string $sTimeUnit
- * @param string $iTypeDay
- * @param string $UsrUid
- * @param string $ProUid
- * @param string $TasUid
- * @return array('DUE_DATE'=>'Final calculated date formatted as Y-m-d H:i:s','DUE_DATE_SECONDS'=>'Final calculated date in seconds','OLD_DUE_DATE'=>'Using deprecate4d function','OLD_DUE_DATE_SECONDS'=>'Using deprecated function','DUE_DATE_LOG'=>'Log of all the calculations made')
- * @todo test this function with negative durations (for events)
- *
- *
- */
- function calculateDate( $sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid = NULL, $ProUid = NULL, $TasUid =NULL )
- {
- //$oldDate=$this->calculateDate_noCalendar( $sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid, $ProUid, $TasUid);
- //Set Calendar when the object is instanced in this order/priority (Task, User, Process, Default)
- G::LoadClass('calendar');
- $calendarObj=new calendar($UsrUid,$ProUid,$TasUid);
- //Get next Business Hours/Range based on :
- switch(strtoupper($sTimeUnit)){
- case 'DAYS': $hoursToProcess=$iDuration*8; break;//In Hours
- default: $hoursToProcess=$iDuration; break;//In Hours
- }
- $dateArray = explode(" ",$sInitDate);
- $currentDate = $dateArray[0];
- $currentTime = isset($dateArray[1])? $dateArray[1]: "00:00:00";
-
- $startTime=(float) array_sum(explode(' ',microtime()));
-
- $calendarObj->addCalendarLog("* Starting at: $startTime");
- $calendarObj->addCalendarLog(">>>>> Hours to Process: $hoursToProcess");
- $calendarObj->addCalendarLog(">>>>> Current Date: $currentDate");
- $calendarObj->addCalendarLog(">>>>> Current Time: $currentTime");
- $array_hours = explode(":",$currentTime);
- $seconds2 = $array_hours[2];
- $minutes2 = 0;
- while($hoursToProcess>0){
- $validBusinessHour=$calendarObj->getNextValidBusinessHoursRange($currentDate,$currentTime);
- //For Date/Time operations
- $currentDateA = explode("-",$validBusinessHour['DATE']);
- $currentTimeA = explode(":",$validBusinessHour['TIME']);
- $hour = $currentTimeA[0];
- $minute = $currentTimeA[1];
- $second = isset($currentTimeA[2])?$currentTimeA[2]:0;
- $month = $currentDateA[1];
- $day = $currentDateA[2];
- $year = $currentDateA[0];
- $normalizedDate = date("Y-m-d H:i:s",mktime($hour,$minute,$second,$month,$day,$year));
- $normalizedDateInt = mktime($hour,$minute,$second,$month,$day,$year);
- $normalizedDateSeconds = ($hour*60*60)+($minute*60);
- $arrayHour = explode(".",$hoursToProcess);
- if(isset($arrayHour[1])){
- $minutes1 = $arrayHour[1];
- $cadm = strlen($minutes1);
- $minutes2 = (($minutes1/pow(10,$cadm))*60);
- }
- $possibleTime=date("Y-m-d H:i:s",mktime($hour+$hoursToProcess,$minute+$minutes2,$second+$seconds2,$month,$day,$year));
- $possibleTimeInt=mktime($hour+$hoursToProcess,$minute+$minutes2,$second+$seconds2,$month,$day,$year);
- $offsetPermitedMinutes="0";
- $calendarBusinessEndA=explode(":",$validBusinessHour['BUSINESS_HOURS']['CALENDAR_BUSINESS_END']);
- $calendarBusinessEndNormalized=date("Y-m-d H:i:s",mktime($calendarBusinessEndA[0],$calendarBusinessEndA[1]+$offsetPermitedMinutes,0,$month,$day,$year));
- $calendarBusinessEndInt=mktime($calendarBusinessEndA[0],$calendarBusinessEndA[1]+$offsetPermitedMinutes,0,$month,$day,$year);
- $calendarBusinessEndSeconds=($calendarBusinessEndA[0]*60*60)+($calendarBusinessEndA[1]*60);
- $calendarObj->addCalendarLog("Possible time: $possibleTime");
- $calendarObj->addCalendarLog("Current Start Date/Time: $normalizedDate");
- $calendarObj->addCalendarLog("Calendar Business End: $calendarBusinessEndNormalized");
- if($possibleTimeInt>$calendarBusinessEndInt){
- $currentDateTimeB = explode(" ",$calendarBusinessEndNormalized);
- $currentDate = $currentDateTimeB[0];
- $currentTime = $currentDateTimeB[1];
- $diff = abs($normalizedDateSeconds-$calendarBusinessEndSeconds);
- $diffHours = $diff/3600;
- $hoursToProcess = $hoursToProcess-$diffHours;
- }
- else{
- $currentDateTimeA = explode(" ",$possibleTime);
- $currentDate = $currentDateTimeA[0];
- $currentTime = $currentDateTimeA[1];
- $hoursToProcess = 0;
- }
- $calendarObj->addCalendarLog("** Hours to Process: $hoursToProcess");
- }
- $calendarObj->addCalendarLog("+++++++++++ Calculated Due Date $currentDate $currentTime");
- $result['DUE_DATE'] = $currentDate." ".$currentTime;
- $result['DUE_DATE_SECONDS'] = strtotime($currentDate." ".$currentTime);
- //$result['OLD_DUE_DATE'] = date("Y-m-d H:i:s",$oldDate);
- //$result['OLD_DUE_DATE_SECONDS']= $oldDate;
-
- $endTime=(float) array_sum(explode(' ',microtime()));
- $calendarObj->addCalendarLog("* Ending at: $endTime");
- $calcTime=round($endTime-$startTime,3);
- $calendarObj->addCalendarLog("** Processing time: ". sprintf("%.4f", ($endTime-$startTime))." seconds");
- $result['DUE_DATE_LOG'] = $calendarObj->calendarLog;
- return $result;
- }
-
- /**
- * Calculate $sInitDate + $iDaysCount, skipping non laborable days.
- * Input: Any valid strtotime function type input.
- * Returns: Integer timestamp of the result.
- * Warning: It will hangs if there is no possible days to count as
- * "laborable".
- * @param date $sInitDate
- * @param double $iDuration
- * @param string $sTimeUnit
- * @param string $iTypeDay
- * @param string $UsrUid
- * @param string $ProUid
- * @param string $TasUid
- * @return integer timestamp of the result
- * @deprecated renamed by Hugo Loza (see calculateDate new function)
- */
-
- function calculateDate_noCalendar( $sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid = NULL, $ProUid = NULL, $TasUid =NULL ) {
- //load in class variables the config of working days, holidays etc..
- $this->prepareInformation( $UsrUid , $ProUid , $TasUid );
- $iHours = 0; $iDays = 0;
- //convert the $iDuration and $sTimeUnit in hours and days, take in mind 8 hours = 1 day. and then we will have similar for 5 days = 1 weekends
- if ( strtolower ( $sTimeUnit ) == 'hours' ) {
- $iAux = intval(abs($iDuration));
- $iHours = $iAux % $this->hoursPerDay;
- $iDays = intval( $iAux / $this->hoursPerDay );
- }
- if ( strtolower ( $sTimeUnit ) == 'days' ) {
- $iAux = intval(abs($iDuration * $this->hoursPerDay));
- $iHours = $iAux % 8;
- $iDays = intval( $iAux / 8 );
- }
- $addSign = ( $iDuration >= 0 ) ? '+' : '-';
- $iInitDate = strtotime( $sInitDate );
- if ( $iTypeDay == 1 ) { // working days
- // if there are days calculate the days,
- $iEndDate = $this->addDays( $iInitDate , $iDays, $addSign );
- // if there are hours calculate the hours, and probably add a day if the quantity of hours for last day > 8 hours
- $iEndDate = $this->addHours( $iEndDate , $iHours, $addSign );
- }
- else { // $task->getTasTypeDay() == 2 // calendar days
- $iEndDate = strtotime( $addSign . $iDays . ' days ' , $iInitDate );
- $iEndDate = strtotime( $addSign . $iHours . ' hours ' , $iEndDate );
- }
- return $iEndDate;
- }
+require_once ("classes/model/TaskPeer.php");
+require_once ("classes/model/HolidayPeer.php");
/**
- * Calculate duration of the $sInitDate - $sEndDate.
- * @param date $sInitDate
- * @param date $sEndDate
- * @param string $UsrUid
- * @param string $ProUid
- * @param string $TasUid
- * @return int
- *
+ *
+ * @package workflow.engine.classes
*/
- function calculateDuration( $sInitDate, $sEndDate = '', $UsrUid = NULL, $ProUid = NULL, $TasUid = NULL) {
- $this->prepareInformation($UsrUid, $ProUid, $TasUid);
- if ((string)$sEndDate == '') {
- $sEndDate = date('Y-m-d H:i:s');
- }
- if (strtotime($sInitDate) > strtotime($sEndDate)) {
- $sAux = $sInitDate;
- $sInitDate = $sEndDate;
- $sEndDate = $sAux;
- }
- $aAux1 = explode(' ', $sInitDate);
- $aAux2 = explode(' ', $sEndDate);
- $aInitDate = explode('-', $aAux1[0]);
- $aEndDate = explode('-', $aAux2[0]);
- $i = 1;
- $iWorkedDays = 0;
- $bFinished = false;
- $fHours1 = 0.0;
- $fHours2 = 0.0;
- if (count($aInitDate) != 3) {
- $aInitDate = array(0, 0, 0);
- }
- if (count($aEndDate) != 3) {
- $aEndDate = array(0, 0, 0);
- }
- if ($aInitDate !== $aEndDate) {
- while (!$bFinished && ($i < 10000)) {
- $sAux = date('Y-m-d', mktime(0, 0, 0, $aInitDate[1], $aInitDate[2] + $i, $aInitDate[0]));
- if ($sAux != implode('-', $aEndDate)) {
- if (!in_array($sAux, $this->holidays)) {
- if (!in_array(date('w', mktime(0, 0, 0, $aInitDate[1], $aInitDate[2] + $i, $aInitDate[0])), $this->weekends)) {
- $iWorkedDays++;
+class dates
+{
+ private $holidays = array ();
+ private $weekends = array ();
+ private $range = array ();
+ private $skipEveryYear = true;
+ private $calendarDays = false; //by default we are using working days
+ private $hoursPerDay = 8; //you should change this
+
+
+ /**
+ * Function that calculate a final date based on $sInitDate and $iDuration
+ * This function also uses a Calendar component (class.calendar.php) where all the definition of
+ * a User, task, Process or default calendar is defined.
+ * base on that information is possible to setup different calendars
+ * and apply them to a task, process or user. Each calendar have Working Days, Business Hours and Holidays
+ *
+ * @name calculateDate
+ * @access public
+ * @author Hugo Loza
+ * @param date $sInitDate
+ * @param double $iDuration
+ * @param string $sTimeUnit
+ * @param string $iTypeDay
+ * @param string $UsrUid
+ * @param string $ProUid
+ * @param string $TasUid
+ * @return array('DUE_DATE'=>'Final calculated date formatted as Y-m-d H:i:s','DUE_DATE_SECONDS'=>'Final calculated date in seconds','OLD_DUE_DATE'=>'Using deprecate4d function','OLD_DUE_DATE_SECONDS'=>'Using deprecated function','DUE_DATE_LOG'=>'Log of all the calculations made')
+ * @todo test this function with negative durations (for events)
+ *
+ *
+ */
+ function calculateDate ($sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid = NULL, $ProUid = NULL, $TasUid = NULL)
+ {
+ //$oldDate=$this->calculateDate_noCalendar( $sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid, $ProUid, $TasUid);
+ //Set Calendar when the object is instanced in this order/priority (Task, User, Process, Default)
+ G::LoadClass( 'calendar' );
+ $calendarObj = new calendar( $UsrUid, $ProUid, $TasUid );
+ //Get next Business Hours/Range based on :
+ switch (strtoupper( $sTimeUnit )) {
+ case 'DAYS':
+ $hoursToProcess = $iDuration * 8;
+ break; //In Hours
+ default:
+ $hoursToProcess = $iDuration;
+ break; //In Hours
+ }
+ $dateArray = explode( " ", $sInitDate );
+ $currentDate = $dateArray[0];
+ $currentTime = isset( $dateArray[1] ) ? $dateArray[1] : "00:00:00";
+
+ $startTime = (float) array_sum( explode( ' ', microtime() ) );
+
+ $calendarObj->addCalendarLog( "* Starting at: $startTime" );
+ $calendarObj->addCalendarLog( ">>>>> Hours to Process: $hoursToProcess" );
+ $calendarObj->addCalendarLog( ">>>>> Current Date: $currentDate" );
+ $calendarObj->addCalendarLog( ">>>>> Current Time: $currentTime" );
+ $array_hours = explode( ":", $currentTime );
+ $seconds2 = $array_hours[2];
+ $minutes2 = 0;
+ while ($hoursToProcess > 0) {
+ $validBusinessHour = $calendarObj->getNextValidBusinessHoursRange( $currentDate, $currentTime );
+ //For Date/Time operations
+ $currentDateA = explode( "-", $validBusinessHour['DATE'] );
+ $currentTimeA = explode( ":", $validBusinessHour['TIME'] );
+ $hour = $currentTimeA[0];
+ $minute = $currentTimeA[1];
+ $second = isset( $currentTimeA[2] ) ? $currentTimeA[2] : 0;
+ $month = $currentDateA[1];
+ $day = $currentDateA[2];
+ $year = $currentDateA[0];
+ $normalizedDate = date( "Y-m-d H:i:s", mktime( $hour, $minute, $second, $month, $day, $year ) );
+ $normalizedDateInt = mktime( $hour, $minute, $second, $month, $day, $year );
+ $normalizedDateSeconds = ($hour * 60 * 60) + ($minute * 60);
+ $arrayHour = explode( ".", $hoursToProcess );
+ if (isset( $arrayHour[1] )) {
+ $minutes1 = $arrayHour[1];
+ $cadm = strlen( $minutes1 );
+ $minutes2 = (($minutes1 / pow( 10, $cadm )) * 60);
}
- }
- $i++;
+ $possibleTime = date( "Y-m-d H:i:s", mktime( $hour + $hoursToProcess, $minute + $minutes2, $second + $seconds2, $month, $day, $year ) );
+ $possibleTimeInt = mktime( $hour + $hoursToProcess, $minute + $minutes2, $second + $seconds2, $month, $day, $year );
+ $offsetPermitedMinutes = "0";
+ $calendarBusinessEndA = explode( ":", $validBusinessHour['BUSINESS_HOURS']['CALENDAR_BUSINESS_END'] );
+ $calendarBusinessEndNormalized = date( "Y-m-d H:i:s", mktime( $calendarBusinessEndA[0], $calendarBusinessEndA[1] + $offsetPermitedMinutes, 0, $month, $day, $year ) );
+ $calendarBusinessEndInt = mktime( $calendarBusinessEndA[0], $calendarBusinessEndA[1] + $offsetPermitedMinutes, 0, $month, $day, $year );
+ $calendarBusinessEndSeconds = ($calendarBusinessEndA[0] * 60 * 60) + ($calendarBusinessEndA[1] * 60);
+ $calendarObj->addCalendarLog( "Possible time: $possibleTime" );
+ $calendarObj->addCalendarLog( "Current Start Date/Time: $normalizedDate" );
+ $calendarObj->addCalendarLog( "Calendar Business End: $calendarBusinessEndNormalized" );
+ if ($possibleTimeInt > $calendarBusinessEndInt) {
+ $currentDateTimeB = explode( " ", $calendarBusinessEndNormalized );
+ $currentDate = $currentDateTimeB[0];
+ $currentTime = $currentDateTimeB[1];
+ $diff = abs( $normalizedDateSeconds - $calendarBusinessEndSeconds );
+ $diffHours = $diff / 3600;
+ $hoursToProcess = $hoursToProcess - $diffHours;
+ } else {
+ $currentDateTimeA = explode( " ", $possibleTime );
+ $currentDate = $currentDateTimeA[0];
+ $currentTime = $currentDateTimeA[1];
+ $hoursToProcess = 0;
+ }
+ $calendarObj->addCalendarLog( "** Hours to Process: $hoursToProcess" );
}
- else {
- $bFinished = true;
- }
- }
- if (isset($aAux1[1])) {
- $aAux1[1] = explode(':', $aAux1[1]);
- $fHours1 = 24 - ($aAux1[1][0] + ($aAux1[1][1] / 60) + ($aAux1[1][2] / 3600));
- }
- if (isset($aAux2[1])) {
- $aAux2[1] = explode(':', $aAux2[1]);
- $fHours2 = $aAux2[1][0] + ($aAux2[1][1] / 60) + ($aAux2[1][2] / 3600);
- }
- $fDuration = ($iWorkedDays * 24) + $fHours1 + $fHours2;
- }
- else {
- $fDuration = (strtotime($sEndDate) - strtotime($sInitDate)) / 3600;
- }
- return $fDuration;
- }
-
- /**
- * Configuration functions
- * @param string $UsrUid
- * @param string $ProUid
- * @param string $TasUid
- * @return void
- */
- function prepareInformation( $UsrUid = NULL , $ProUid = NULL , $TasUid =NULL )
- {
- // setup calendarDays according the task
- if (isset($TasUid))
- {
- $task = TaskPeer::retrieveByPK( $TasUid );
- if (!is_null($task)) {
- $this->calendarDays = ($task->getTasTypeDay()==2);
- }
+ $calendarObj->addCalendarLog( "+++++++++++ Calculated Due Date $currentDate $currentTime" );
+ $result['DUE_DATE'] = $currentDate . " " . $currentTime;
+ $result['DUE_DATE_SECONDS'] = strtotime( $currentDate . " " . $currentTime );
+ //$result['OLD_DUE_DATE'] = date("Y-m-d H:i:s",$oldDate);
+ //$result['OLD_DUE_DATE_SECONDS']= $oldDate;
+
+
+ $endTime = (float) array_sum( explode( ' ', microtime() ) );
+ $calendarObj->addCalendarLog( "* Ending at: $endTime" );
+ $calcTime = round( $endTime - $startTime, 3 );
+ $calendarObj->addCalendarLog( "** Processing time: " . sprintf( "%.4f", ($endTime - $startTime) ) . " seconds" );
+ $result['DUE_DATE_LOG'] = $calendarObj->calendarLog;
+ return $result;
}
- //get an array with all holidays.
- $aoHolidays=HolidayPeer::doSelect(new Criteria());
- $holidays=array();
- foreach($aoHolidays as $holiday)
- $holidays[] = strtotime($holiday->getHldDate());
-
- // by default the weekdays are from monday to friday
- $this->weekends = array(0,6);
- $this->holidays = $holidays;
- return ;
- }
-
- /**
- * Set to repeat for every year all dates defined in $this->holiday
- * @param $bSkipEveryYear
- * @return void
- */
- function setSkipEveryYear( $bSkipEveryYear )
- {
- $this->skipEveryYear = $bSkipEveryYear===true;
- }
-
- /**
- * Add a single date to holidays
- * @param data $sDate
- * @return void
- */
- function addHoliday( $sDate )
- {
- if ($date=strtotime( $sDate )) $this->holidays[]=self::truncateTime($date);
- else throw new Exception("Invalid date: $sDate.");
- }
-
- /**
- * Set all the holidays
- * @param date/array $aDate must be an array of (strtotime type) dates
- * @return void
- */
- function setHolidays( $aDates )
- {
- foreach($aDates as $sDate) $this->holidays = $aDates;
- }
-
- /**
- * Set all the weekends
- * @param array/integers $aWeekends must be an array of integers [1,7]
- * 1=Sunday
- * 7=Saturday
- * @return void
- */
- function setWeekends( $aWeekends )
- {
- $this->weekends = $aWeekends;
- }
-
- /**
- * Add one day of week to the weekends list
- * @param $iDayNumber must be an array of integers [1,7]
- * 1=Sunday
- * 7=Saturday
- * @return void
- */
- function skipDayOfWeek( $iDayNumber )
- {
- if ($iDayNumber<1 || $iDayNumber>7) throw new Exception("The day of week must be a number from 1 to 7.");
- $this->weekends[]=$iDayNumber;
- }
-
- /**
- * Add a range of non working dates
- * @param date $sDateA must be a (strtotime type) dates
- * @param date $sDateB must be a (strtotime type) dates
- * @return void
- */
- function addNonWorkingRange( $sDateA , $sDateB )
- {
- if ($date=strtotime( $sDateA )) $iDateA=self::truncateTime($date);
- else throw new Exception("Invalid date: $sDateA.");
- if ($date=strtotime( $sDateB )) $iDateB=self::truncateTime($date);
- else throw new Exception("Invalid date: $sDateB.");
- if ($iDateA>$iDateB) { $s=$iDateA;$iDateA=$iDateB;$iDateB=$s; };
- $this->range[]=array( $iDateA , $iDateB );
- }
-
- /**
- * PRIVATE UTILITARY FUNCTIONS
- * Add days to the date
- * @param date $iInitDate
- * @param int $iDaysCount
- * @param string $addSign
- * @return date $iEndDate
- */
- private function addDays( $iInitDate , $iDaysCount, $addSign = '+' )
- {
- $iEndDate = $iInitDate;
- $aList = $this->holidays;
- for( $r=1; $r <= $iDaysCount ; $r++) {
- $iEndDate = strtotime( $addSign . "1 day", $iEndDate );
- $dayOfWeek = idate('w',$iEndDate); //now sunday=0
- if ( array_search( $dayOfWeek, $this->weekends )!== false ) $r--; //continue loop, but we are adding one more day.
- }
- return $iEndDate;
- }
-
- /**
- * Add hours to the date
- * @param date $iInitDate
- * @param int $iHoursCount
- * @param string $addSign
- * @return $iEndDate
- */
-
- private function addHours( $sInitDate , $iHoursCount, $addSign = '+' )
- {
- $iEndDate = strtotime( $addSign . $iHoursCount ." hours", $sInitDate );
- return $iEndDate;
- }
-
- /**
- * Compare if the date is in range
- * @param $iDate = valid timestamp
- * @return true if it is within any of the ranges defined.
- */
- private function inRange( $iDate )
- {
- $aRange = $this->range;
- $iYear = idate( 'Y', $iDate );
- foreach($aRange as $key => $rang)
- {
- if ($this->skipEveryYear)
- {
- $deltaYears = idate( 'Y', $rang[1] ) - idate( 'Y', $rang[0] );
- $rang[0]=self::changeYear( $rang[0] , $iYear );
- $rang[1]=self::changeYear( $rang[1] , $iYear + $deltaYears );
- }
- if (($iDate>=$rang[0]) && ($iDate<=$rang[1])) return true;
- }
- return false;
- }
-
- /**
- * Truncate a date
- * @param $iDate = valid timestamp
- * @return date
- */
- private function truncateTime( $iDate )
- {
- return mktime(0,0,0,idate('m',$iDate),idate('d',$iDate),idate('Y',$iDate));
- }
-
- /**
- * Get time
- * @param timestamp $iDate
- * @return date
- */
- private function getTime( $iDate )
- {
- return array(idate('H',$iDate),idate('m',$iDate),idate('s',$iDate));
- }
-
- /**
- * Set time
- * @param timestamp $iDate
- * @param timestamp $aTime
- * @return date
- */
- private function setTime( $iDate , $aTime )
- {
- return mktime($aTime[0],$aTime[1],$aTime[2],idate('m',$iDate),idate('d',$iDate),idate('Y',$iDate));
- }
-
-/**
- * Returns an array with all the dates of $this->skip['List'] with its
- * year changed to $iYear.
- * Warning: Don't know what to do if change a 29-02-2004 to 29-02-2005
- * the last one doesn't exist.
- * @param List $iYear
- * @return array
- */
- private function listForYear( $iYear )
- {
- $aList = $this->holidays;
- foreach($aList as $k => $v)
- {
- $aList[$k] = self::changeYear( $v , $iYear );
- }
- return $aList;
- }
+ /**
+ * Calculate $sInitDate + $iDaysCount, skipping non laborable days.
+ * Input: Any valid strtotime function type input.
+ * Returns: Integer timestamp of the result.
+ * Warning: It will hangs if there is no possible days to count as
+ * "laborable".
+ *
+ * @param date $sInitDate
+ * @param double $iDuration
+ * @param string $sTimeUnit
+ * @param string $iTypeDay
+ * @param string $UsrUid
+ * @param string $ProUid
+ * @param string $TasUid
+ * @return integer timestamp of the result
+ * @deprecated renamed by Hugo Loza (see calculateDate new function)
+ */
-/**
- * Returns an array with all the dates of $this->skip['List'] with its
- * year changed to $iYear.
- * Warning: Don't know what to do if change a 29-02-2004 to 29-02-2005
- * the last one doesn't exist.
- * @param array $iYear
- * @param date $iDate
- * @return array
- */
- private function changeYear( $iDate , $iYear )
- {
- if ($delta = ( $iYear - idate('Y',$iDate) ) )
+ function calculateDate_noCalendar ($sInitDate, $iDuration, $sTimeUnit, $iTypeDay, $UsrUid = NULL, $ProUid = NULL, $TasUid = NULL)
{
- $iDate = strtotime( "$delta year" , $iDate );
+ //load in class variables the config of working days, holidays etc..
+ $this->prepareInformation( $UsrUid, $ProUid, $TasUid );
+ $iHours = 0;
+ $iDays = 0;
+ //convert the $iDuration and $sTimeUnit in hours and days, take in mind 8 hours = 1 day. and then we will have similar for 5 days = 1 weekends
+ if (strtolower( $sTimeUnit ) == 'hours') {
+ $iAux = intval( abs( $iDuration ) );
+ $iHours = $iAux % $this->hoursPerDay;
+ $iDays = intval( $iAux / $this->hoursPerDay );
+ }
+ if (strtolower( $sTimeUnit ) == 'days') {
+ $iAux = intval( abs( $iDuration * $this->hoursPerDay ) );
+ $iHours = $iAux % 8;
+ $iDays = intval( $iAux / 8 );
+ }
+ $addSign = ($iDuration >= 0) ? '+' : '-';
+ $iInitDate = strtotime( $sInitDate );
+ if ($iTypeDay == 1) { // working days
+ // if there are days calculate the days,
+ $iEndDate = $this->addDays( $iInitDate, $iDays, $addSign );
+ // if there are hours calculate the hours, and probably add a day if the quantity of hours for last day > 8 hours
+ $iEndDate = $this->addHours( $iEndDate, $iHours, $addSign );
+ } else { // $task->getTasTypeDay() == 2 // calendar days
+ $iEndDate = strtotime( $addSign . $iDays . ' days ', $iInitDate );
+ $iEndDate = strtotime( $addSign . $iHours . ' hours ', $iEndDate );
+ }
+ return $iEndDate;
+ }
+
+ /**
+ * Calculate duration of the $sInitDate - $sEndDate.
+ *
+ * @param date $sInitDate
+ * @param date $sEndDate
+ * @param string $UsrUid
+ * @param string $ProUid
+ * @param string $TasUid
+ * @return int
+ *
+ */
+ function calculateDuration ($sInitDate, $sEndDate = '', $UsrUid = NULL, $ProUid = NULL, $TasUid = NULL)
+ {
+ $this->prepareInformation( $UsrUid, $ProUid, $TasUid );
+ if ((string) $sEndDate == '') {
+ $sEndDate = date( 'Y-m-d H:i:s' );
+ }
+ if (strtotime( $sInitDate ) > strtotime( $sEndDate )) {
+ $sAux = $sInitDate;
+ $sInitDate = $sEndDate;
+ $sEndDate = $sAux;
+ }
+ $aAux1 = explode( ' ', $sInitDate );
+ $aAux2 = explode( ' ', $sEndDate );
+ $aInitDate = explode( '-', $aAux1[0] );
+ $aEndDate = explode( '-', $aAux2[0] );
+ $i = 1;
+ $iWorkedDays = 0;
+ $bFinished = false;
+ $fHours1 = 0.0;
+ $fHours2 = 0.0;
+ if (count( $aInitDate ) != 3) {
+ $aInitDate = array (0,0,0
+ );
+ }
+ if (count( $aEndDate ) != 3) {
+ $aEndDate = array (0,0,0
+ );
+ }
+ if ($aInitDate !== $aEndDate) {
+ while (! $bFinished && ($i < 10000)) {
+ $sAux = date( 'Y-m-d', mktime( 0, 0, 0, $aInitDate[1], $aInitDate[2] + $i, $aInitDate[0] ) );
+ if ($sAux != implode( '-', $aEndDate )) {
+ if (! in_array( $sAux, $this->holidays )) {
+ if (! in_array( date( 'w', mktime( 0, 0, 0, $aInitDate[1], $aInitDate[2] + $i, $aInitDate[0] ) ), $this->weekends )) {
+ $iWorkedDays ++;
+ }
+ }
+ $i ++;
+ } else {
+ $bFinished = true;
+ }
+ }
+ if (isset( $aAux1[1] )) {
+ $aAux1[1] = explode( ':', $aAux1[1] );
+ $fHours1 = 24 - ($aAux1[1][0] + ($aAux1[1][1] / 60) + ($aAux1[1][2] / 3600));
+ }
+ if (isset( $aAux2[1] )) {
+ $aAux2[1] = explode( ':', $aAux2[1] );
+ $fHours2 = $aAux2[1][0] + ($aAux2[1][1] / 60) + ($aAux2[1][2] / 3600);
+ }
+ $fDuration = ($iWorkedDays * 24) + $fHours1 + $fHours2;
+ } else {
+ $fDuration = (strtotime( $sEndDate ) - strtotime( $sInitDate )) / 3600;
+ }
+ return $fDuration;
+ }
+
+ /**
+ * Configuration functions
+ *
+ * @param string $UsrUid
+ * @param string $ProUid
+ * @param string $TasUid
+ * @return void
+ */
+ function prepareInformation ($UsrUid = NULL, $ProUid = NULL, $TasUid = NULL)
+ {
+ // setup calendarDays according the task
+ if (isset( $TasUid )) {
+ $task = TaskPeer::retrieveByPK( $TasUid );
+ if (! is_null( $task )) {
+ $this->calendarDays = ($task->getTasTypeDay() == 2);
+ }
+ }
+
+ //get an array with all holidays.
+ $aoHolidays = HolidayPeer::doSelect( new Criteria() );
+ $holidays = array ();
+ foreach ($aoHolidays as $holiday)
+ $holidays[] = strtotime( $holiday->getHldDate() );
+
+ // by default the weekdays are from monday to friday
+ $this->weekends = array (0,6
+ );
+ $this->holidays = $holidays;
+ return;
+ }
+
+ /**
+ * Set to repeat for every year all dates defined in $this->holiday
+ *
+ * @param $bSkipEveryYear
+ * @return void
+ */
+ function setSkipEveryYear ($bSkipEveryYear)
+ {
+ $this->skipEveryYear = $bSkipEveryYear === true;
+ }
+
+ /**
+ * Add a single date to holidays
+ *
+ * @param data $sDate
+ * @return void
+ */
+ function addHoliday ($sDate)
+ {
+ if ($date = strtotime( $sDate ))
+ $this->holidays[] = self::truncateTime( $date );
+ else
+ throw new Exception( "Invalid date: $sDate." );
+ }
+
+ /**
+ * Set all the holidays
+ *
+ * @param date/array $aDate must be an array of (strtotime type) dates
+ * @return void
+ */
+ function setHolidays ($aDates)
+ {
+ foreach ($aDates as $sDate)
+ $this->holidays = $aDates;
+ }
+
+ /**
+ * Set all the weekends
+ *
+ * @param array/integers $aWeekends must be an array of integers [1,7]
+ * 1=Sunday
+ * 7=Saturday
+ * @return void
+ */
+ function setWeekends ($aWeekends)
+ {
+ $this->weekends = $aWeekends;
+ }
+
+ /**
+ * Add one day of week to the weekends list
+ *
+ * @param $iDayNumber must be an array of integers [1,7]
+ * 1=Sunday
+ * 7=Saturday
+ * @return void
+ */
+ function skipDayOfWeek ($iDayNumber)
+ {
+ if ($iDayNumber < 1 || $iDayNumber > 7)
+ throw new Exception( "The day of week must be a number from 1 to 7." );
+ $this->weekends[] = $iDayNumber;
+ }
+
+ /**
+ * Add a range of non working dates
+ *
+ * @param date $sDateA must be a (strtotime type) dates
+ * @param date $sDateB must be a (strtotime type) dates
+ * @return void
+ */
+ function addNonWorkingRange ($sDateA, $sDateB)
+ {
+ if ($date = strtotime( $sDateA ))
+ $iDateA = self::truncateTime( $date );
+ else
+ throw new Exception( "Invalid date: $sDateA." );
+ if ($date = strtotime( $sDateB ))
+ $iDateB = self::truncateTime( $date );
+ else
+ throw new Exception( "Invalid date: $sDateB." );
+ if ($iDateA > $iDateB) {
+ $s = $iDateA;
+ $iDateA = $iDateB;
+ $iDateB = $s;
+ }
+ ;
+ $this->range[] = array ($iDateA,$iDateB
+ );
+ }
+
+ /**
+ * PRIVATE UTILITARY FUNCTIONS
+ * Add days to the date
+ *
+ * @param date $iInitDate
+ * @param int $iDaysCount
+ * @param string $addSign
+ * @return date $iEndDate
+ */
+ private function addDays ($iInitDate, $iDaysCount, $addSign = '+')
+ {
+ $iEndDate = $iInitDate;
+ $aList = $this->holidays;
+ for ($r = 1; $r <= $iDaysCount; $r ++) {
+ $iEndDate = strtotime( $addSign . "1 day", $iEndDate );
+ $dayOfWeek = idate( 'w', $iEndDate ); //now sunday=0
+ if (array_search( $dayOfWeek, $this->weekends ) !== false)
+ $r --; //continue loop, but we are adding one more day.
+ }
+ return $iEndDate;
+ }
+
+ /**
+ * Add hours to the date
+ *
+ * @param date $iInitDate
+ * @param int $iHoursCount
+ * @param string $addSign
+ * @return $iEndDate
+ */
+
+ private function addHours ($sInitDate, $iHoursCount, $addSign = '+')
+ {
+ $iEndDate = strtotime( $addSign . $iHoursCount . " hours", $sInitDate );
+ return $iEndDate;
+ }
+
+ /**
+ * Compare if the date is in range
+ *
+ * @param $iDate = valid timestamp
+ * @return true if it is within any of the ranges defined.
+ */
+ private function inRange ($iDate)
+ {
+ $aRange = $this->range;
+ $iYear = idate( 'Y', $iDate );
+ foreach ($aRange as $key => $rang) {
+ if ($this->skipEveryYear) {
+ $deltaYears = idate( 'Y', $rang[1] ) - idate( 'Y', $rang[0] );
+ $rang[0] = self::changeYear( $rang[0], $iYear );
+ $rang[1] = self::changeYear( $rang[1], $iYear + $deltaYears );
+ }
+ if (($iDate >= $rang[0]) && ($iDate <= $rang[1]))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Truncate a date
+ *
+ * @param $iDate = valid timestamp
+ * @return date
+ */
+ private function truncateTime ($iDate)
+ {
+ return mktime( 0, 0, 0, idate( 'm', $iDate ), idate( 'd', $iDate ), idate( 'Y', $iDate ) );
+ }
+
+ /**
+ * Get time
+ *
+ * @param timestamp $iDate
+ * @return date
+ */
+ private function getTime ($iDate)
+ {
+ return array (idate( 'H', $iDate ),idate( 'm', $iDate ),idate( 's', $iDate )
+ );
+ }
+
+ /**
+ * Set time
+ *
+ * @param timestamp $iDate
+ * @param timestamp $aTime
+ * @return date
+ */
+ private function setTime ($iDate, $aTime)
+ {
+ return mktime( $aTime[0], $aTime[1], $aTime[2], idate( 'm', $iDate ), idate( 'd', $iDate ), idate( 'Y', $iDate ) );
+ }
+
+ /**
+ * Returns an array with all the dates of $this->skip['List'] with its
+ * year changed to $iYear.
+ * Warning: Don't know what to do if change a 29-02-2004 to 29-02-2005
+ * the last one doesn't exist.
+ *
+ * @param List $iYear
+ * @return array
+ */
+ private function listForYear ($iYear)
+ {
+ $aList = $this->holidays;
+ foreach ($aList as $k => $v) {
+ $aList[$k] = self::changeYear( $v, $iYear );
+ }
+ return $aList;
+ }
+
+ /**
+ * Returns an array with all the dates of $this->skip['List'] with its
+ * year changed to $iYear.
+ * Warning: Don't know what to do if change a 29-02-2004 to 29-02-2005
+ * the last one doesn't exist.
+ *
+ * @param array $iYear
+ * @param date $iDate
+ * @return array
+ */
+ private function changeYear ($iDate, $iYear)
+ {
+ if ($delta = ($iYear - idate( 'Y', $iDate ))) {
+ $iDate = strtotime( "$delta year", $iDate );
+ }
+ return $iDate;
}
- return $iDate;
- }
}
?>
\ No newline at end of file