static function smartReCalculate($user_id, $user_date_ids, $enable_exception = TRUE, $enable_premature_exceptions = FALSE, $enable_future_exceptions = TRUE)
 {
     if ($user_id == '') {
         return FALSE;
     }
     //Debug::Arr($user_date_ids, 'aUser Date IDs: ', __FILE__, __LINE__, __METHOD__, 10);
     if (!is_array($user_date_ids) and is_numeric($user_date_ids) and $user_date_ids > 0) {
         $user_date_ids = array($user_date_ids);
     }
     if (!is_array($user_date_ids)) {
         Debug::Text('Returning FALSE... User Date IDs not an array...', __FILE__, __LINE__, __METHOD__, 10);
         return FALSE;
     }
     $user_date_ids = array_unique($user_date_ids);
     //Debug::Arr($user_date_ids, 'bUser Date IDs: ', __FILE__, __LINE__, __METHOD__, 10);
     $start_week_day_id = 0;
     $ppslf = TTnew('PayPeriodScheduleListFactory');
     $ppslf->getByUserId($user_id);
     if ($ppslf->getRecordCount() == 1) {
         $pps_obj = $ppslf->getCurrent();
         $start_week_day_id = $pps_obj->getStartWeekDay();
     }
     Debug::text('Start Week Day ID: ' . $start_week_day_id, __FILE__, __LINE__, __METHOD__, 10);
     //Get date stamps for all user_date_ids.
     $udlf = TTnew('UserDateListFactory');
     $udlf->getByIds($user_date_ids, NULL, array('date_stamp' => 'asc'));
     //Order by date asc
     if ($udlf->getRecordCount() > 0) {
         //Order them, and get the one or more sets of date ranges that need to be recalculated.
         //Need to consider re-calculating multiple weeks at once.
         $i = 0;
         foreach ($udlf as $ud_obj) {
             $start_week_epoch = TTDate::getBeginWeekEpoch($ud_obj->getDateStamp(), $start_week_day_id);
             $end_week_epoch = TTDate::getEndWeekEpoch($ud_obj->getDateStamp(), $start_week_day_id);
             Debug::text('Current Date: ' . TTDate::getDate('DATE', $ud_obj->getDateStamp()) . ' Start Week: ' . TTDate::getDate('DATE', $start_week_epoch) . ' End Week: ' . TTDate::getDate('DATE', $end_week_epoch), __FILE__, __LINE__, __METHOD__, 10);
             if ($i == 0) {
                 $range_arr[$start_week_epoch] = array('start_date' => $ud_obj->getDateStamp(), 'end_date' => $end_week_epoch);
             } else {
                 //Loop through each range extending it if needed.
                 foreach ($range_arr as $tmp_start_week_epoch => $tmp_range) {
                     if ($ud_obj->getDateStamp() >= $tmp_range['start_date'] and $ud_obj->getDateStamp() <= $tmp_range['end_date']) {
                         //Date falls within already existing range
                         continue;
                     } elseif ($ud_obj->getDateStamp() < $tmp_range['start_date'] and $ud_obj->getDateStamp() >= $tmp_start_week_epoch) {
                         //Date falls within the same week, but before the current start date.
                         $range_arr[$tmp_start_week_epoch]['start_date'] = $ud_obj->getDateStamp();
                         Debug::text('Pushing Start Date back...', __FILE__, __LINE__, __METHOD__, 10);
                     } else {
                         //Outside current range. Check to make sure it isn't within another range.
                         if (isset($range_arr[$start_week_epoch])) {
                             //Within another existing week, check to see if we need to extend it.
                             if ($ud_obj->getDateStamp() < $range_arr[$start_week_epoch]['start_date']) {
                                 Debug::text('bPushing Start Date back...', __FILE__, __LINE__, __METHOD__, 10);
                                 $range_arr[$start_week_epoch]['start_date'] = $ud_obj->getDateStamp();
                             }
                         } else {
                             //Not within another existing week
                             Debug::text('Adding new range...', __FILE__, __LINE__, __METHOD__, 10);
                             $range_arr[$start_week_epoch] = array('start_date' => $ud_obj->getDateStamp(), 'end_date' => $end_week_epoch);
                         }
                     }
                 }
                 unset($tmp_range, $tmp_start_week_epoch);
             }
             $i++;
         }
         unset($start_week_epoch, $end_week_epoch, $udlf, $ud_obj);
         if (is_array($range_arr)) {
             ksort($range_arr);
             //Sort range by start week, so recalculating goes in date order.
             //Debug::Arr($range_arr, 'Range Array: ', __FILE__, __LINE__, __METHOD__, 10);
             foreach ($range_arr as $week_range) {
                 $udlf = TTnew('UserDateListFactory');
                 $udlf->getByUserIdAndStartDateAndEndDate($user_id, $week_range['start_date'], $week_range['end_date']);
                 if ($udlf->getRecordCount() > 0) {
                     Debug::text('Found days to re-calculate: ' . $udlf->getRecordCount(), __FILE__, __LINE__, __METHOD__, 10);
                     $udlf->StartTransaction();
                     $z = 1;
                     $z_max = $udlf->getRecordCount();
                     foreach ($udlf as $ud_obj) {
                         //We only need to re-calculate exceptions on the exact days specified by user_date_ids.
                         //This was the case before we Over Weekly Time/Over Scheduled Weekly Time exceptions,
                         //Now we have to enable calculating exceptions for the entire week.
                         Debug::text('Re-calculating day with exceptions: ' . $ud_obj->getId(), __FILE__, __LINE__, __METHOD__, 10);
                         if ($z == $z_max) {
                             //Enable recalculating holidays at the end of each week.
                             UserDateTotalFactory::reCalculateDay($ud_obj->getId(), $enable_exception, $enable_premature_exceptions, $enable_future_exceptions, TRUE);
                         } else {
                             UserDateTotalFactory::reCalculateDay($ud_obj->getId(), $enable_exception, $enable_premature_exceptions, $enable_future_exceptions);
                         }
                         $z++;
                     }
                     $udlf->CommitTransaction();
                 }
             }
             //Use the last date to base the future week calculation on. Make sure we don't unset $week_range['end_date']
             //When BiWeekly overtime policies are calculated, it sets getEnableCalcFutureWeek() to TRUE.
             if (isset($week_range['end_date']) and UserDateTotalFactory::getEnableCalcFutureWeek() == TRUE) {
                 $future_week_date = $week_range['end_date'] + 86400 * 7;
                 Debug::text('Found Biweekly overtime policy, calculate one week into the future: ' . TTDate::getDate('DATE', $future_week_date), __FILE__, __LINE__, __METHOD__, 10);
                 UserDateTotalFactory::reCalculateRange($user_id, TTDate::getBeginWeekEpoch($future_week_date, $start_week_day_id), TTDate::getEndWeekEpoch($future_week_date, $start_week_day_id));
                 UserDateTotalFactory::setEnableCalcFutureWeek(FALSE);
                 //Return to FALSE so future weeks aren't calculate for other users.
                 unset($future_week_date);
             }
             return TRUE;
         }
     }
     Debug::text('Returning FALSE!', __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
 function calcWeeklySystemTotalTime()
 {
     if ($this->getEnableCalcWeeklySystemTotalTime() == TRUE) {
         global $profiler;
         $profiler->startTimer("UserDateTotal::postSave() - reCalculateRange 1");
         //Get Pay Period Schedule info
         if (is_object($this->getUserDateObject()->getPayPeriodObject()) and is_object($this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject())) {
             $start_week_day_id = $this->getUserDateObject()->getPayPeriodObject()->getPayPeriodScheduleObject()->getStartWeekDay();
         } else {
             $start_week_day_id = 0;
         }
         Debug::text('Start Week Day ID: ' . $start_week_day_id . ' Date Stamp: ' . TTDate::getDate('DATE+TIME', $this->getUserDateObject()->getDateStamp()), __FILE__, __LINE__, __METHOD__, 10);
         UserDateTotalFactory::reCalculateRange($this->getUserDateObject()->getUser(), $this->getUserDateObject()->getDateStamp() + 86400, TTDate::getEndWeekEpoch($this->getUserDateObject()->getDateStamp(), $start_week_day_id));
         unset($start_week_day_id);
         $profiler->stopTimer("UserDateTotal::postSave() - reCalculateRange 1");
         return TRUE;
     }
     return FALSE;
 }