function getShiftsByStartDateAndEndDate($start_date, $end_date)
 {
     //Make sure timezone isn't in the time format. Because recurring schedules
     //are timezone agnostic. 7:00AM in PST is also 7:00AM in EST.
     //This causes an issue where the previous users timezone carries over to the next
     //users timezone, causing errors.
     //TTDate::setTimeFormat('g:i A');
     if ($start_date == '') {
         return FALSE;
     }
     if ($end_date == '') {
         return FALSE;
     }
     if ($start_date < $this->getStartDate()) {
         $start_date = $this->getStartDate();
     }
     if ($this->getEndDate(TRUE) != NULL and $end_date > $this->getEndDate()) {
         $end_date = $this->getEndDate();
     }
     Debug::text('Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . '(' . $start_date . ') End Date: ' . TTDate::getDate('DATE+TIME', $end_date) . '(' . $end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     //Get week data
     $rstlf = TTnew('RecurringScheduleTemplateListFactory');
     $rstlf->getByRecurringScheduleTemplateControlId($this->getRecurringScheduleTemplateControl())->getCurrent();
     $max_week = 1;
     $weeks = array();
     if ($rstlf->getRecordCount() > 0) {
         foreach ($rstlf as $rst_obj) {
             //Debug::text('Week: '. $rst_obj->getWeek(), __FILE__, __LINE__, __METHOD__, 10);
             $template_week_rows[$rst_obj->getWeek()][] = $rst_obj->getObjectAsArray();
             $weeks[$rst_obj->getWeek()] = $rst_obj->getWeek();
             if ($rst_obj->getWeek() > $max_week) {
                 $max_week = $rst_obj->getWeek();
             }
         }
     }
     $weeks = $this->ReMapWeeks($weeks);
     //Get week of start_date
     $start_date_week = TTDate::getBeginWeekEpoch($this->getStartDate(), 0);
     //Start week on Sunday to match Recurring Schedule.
     //Debug::text('Week of Start Date: '. $start_date_week .' Date: '. TTDate::getDate('DATE+TIME', $this->getStartDate() ) ,__FILE__, __LINE__, __METHOD__, 10);
     //Since we add 43200 to each iteration (even though its removed right after), we need to add 43200 to the end_date as well so we loop the
     //proper amount of times, otherwise schedules may be added too late.
     for ($i = $start_date; $i <= $end_date + 43200; $i += 86400 + 43200) {
         //Handle DST by adding 12hrs to the date to get the mid-day epoch, then forcing it back to the beginning of the day.
         $i = TTDate::getBeginDayEpoch($i);
         //This needs to take into account weeks spanning January 1st of each year. Where the week goes from 53 to 1.
         //Rather then use the week of the year, calculate the weeks between the recurring schedule start date and now.
         $current_week = round((TTDate::getBeginWeekEpoch($i, 0) - $start_date_week) / 604800);
         //Find out which week we are on based on the recurring schedule start date. Use round due to DST the week might be 6.9 or 7.1, so we need to round to the nearest full week.
         //Debug::text('I: '. $i .' User ID: '. $this->getColumn('user_id') .' Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week .' Start Week: '. $start_date_week,__FILE__, __LINE__, __METHOD__, 10);
         $template_week = $current_week % $max_week + 1;
         //Debug::text('Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
         $day_of_week = strtolower(date('D', $i));
         //Debug::text('Day Of Week: '. $day_of_week,__FILE__, __LINE__, __METHOD__, 10);
         if (isset($weeks[$template_week])) {
             $mapped_template_week = $weeks[$template_week];
             //Debug::text('&nbsp;&nbsp;Mapped Template Week: '. $mapped_template_week,__FILE__, __LINE__, __METHOD__, 10);
             if (isset($template_week_rows[$mapped_template_week])) {
                 //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Starting Looping...!',__FILE__, __LINE__, __METHOD__, 10);
                 foreach ($template_week_rows[$mapped_template_week] as $template_week_arr) {
                     if ($template_week_arr['days'][$day_of_week] == TRUE) {
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Found Scheduled Time: Start Time: '. TTDate::getDate('DATE+TIME', TTDate::getTimeLockedDate( $template_week_arr['start_time'], $i ) ),__FILE__, __LINE__, __METHOD__, 10);
                         $start_time = TTDate::getTimeLockedDate($template_week_arr['raw_start_time'], $i);
                         $end_time = TTDate::getTimeLockedDate($template_week_arr['raw_end_time'], $i);
                         if ($end_time < $start_time) {
                             //Spans the day boundary, add 86400 to end_time
                             $end_time = $end_time + 86400;
                             //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Schedule spans day boundary, bumping endtime to next day: ',__FILE__, __LINE__, __METHOD__, 10);
                         }
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start Date: '. TTDate::getDate('DATE+TIME', $start_time) .' End Date: '. TTDate::getDate('DATE+TIME', $end_time),__FILE__, __LINE__, __METHOD__, 10);
                         //$shifts[TTDate::getBeginDayEpoch($i)][] = array(
                         $shifts[TTDate::getISODateStamp($i)][] = array('status_id' => $template_week_arr['status_id'], 'start_time' => $start_time, 'raw_start_time' => TTDate::getDate('DATE+TIME', $start_time), 'end_time' => $end_time, 'raw_end_time' => TTDate::getDate('DATE+TIME', $end_time), 'total_time' => $template_week_arr['total_time'], 'schedule_policy_id' => $template_week_arr['schedule_policy_id'], 'branch_id' => $template_week_arr['branch_id'], 'department_id' => $template_week_arr['department_id'], 'job_id' => $template_week_arr['job_id'], 'job_item_id' => $template_week_arr['job_item_id']);
                         unset($start_time, $end_time);
                     } else {
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aSkipping!',__FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
             } else {
                 //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;bSkipping!',__FILE__, __LINE__, __METHOD__, 10);
             }
         } else {
             //Debug::text('&nbsp;&nbsp;cSkipping!',__FILE__, __LINE__, __METHOD__, 10);
         }
     }
     //var_dump($shifts);
     if (isset($shifts)) {
         return $shifts;
     }
     return FALSE;
 }
 function getNextPayPeriod($end_date = NULL)
 {
     if (!$this->Validator->isValid()) {
         return FALSE;
     }
     //Manual Pay Period Schedule, skip repeating...
     if ($this->getType() == 5) {
         return FALSE;
     }
     $pplf = new PayPeriodListFactory();
     //Debug::text('PP Schedule ID: '. $this->getId(), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('PP Schedule Name: '. $this->getName(), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('PP Schedule Type (' . $this->getType() . '): ' . Option::getByKey($this->getType(), $this->getOptions('type')), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Anchor Date: '. $this->getAnchorDate() ." - ". TTDate::getDate('DATE+TIME', $this->getAnchorDate() ), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Primary Date: '. $this->getPrimaryDate() ." - ". TTDate::getDate('DATE+TIME', $this->getPrimaryDate() ), __FILE__, __LINE__, __METHOD__, 10);
     //Debug::text('Secondary Date: '. $this->getSecondaryDate() ." - ". TTDate::getDate('DATE+TIME', $this->getPrimaryDate() ), __FILE__, __LINE__, __METHOD__, 10);
     $last_pay_period_is_new = FALSE;
     if ($end_date != '' and $end_date != 0) {
         Debug::text('End Date is set: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
         $last_pay_period_end_date = $end_date;
     } else {
         Debug::text('Checking for Previous pay periods...', __FILE__, __LINE__, __METHOD__, 10);
         //Get the last pay period schedule in the database.
         $pplf->getByPayPeriodScheduleId($this->getId(), NULL, NULL, NULL, array('start_date' => 'desc'));
         $last_pay_period = $pplf->getCurrent();
         if ($last_pay_period->isNew()) {
             $last_pay_period_is_new = TRUE;
             Debug::text('No Previous pay periods...', __FILE__, __LINE__, __METHOD__, 10);
             //Do this so a rollover doesn't happen while we're calculating.
             //$last_pay_period_end_date = TTDate::getTime();
             //This causes the pay period schedule to jump ahead one month. So set this to be beginning of the month.
             $last_pay_period_end_date = TTDate::getBeginMonthEpoch();
         } else {
             Debug::text('Previous pay periods found... ID: ' . $last_pay_period->getId(), __FILE__, __LINE__, __METHOD__, 10);
             $last_pay_period_end_date = $last_pay_period->getEndDate();
         }
         unset($last_pay_period, $pplf);
     }
     Debug::text('aLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     //FIXME: This breaks having pay periods with different daily start times.
     //However, without it, I think DST breaks pay periods.
     //$last_pay_period_end_date = TTDate::getEndDayEpoch( $last_pay_period_end_date + 1 ) - 86400;
     $last_pay_period_end_date = TTDate::getEndDayEpoch($last_pay_period_end_date - 86400 / 2);
     Debug::text('bLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     if ($this->getDayStartTime() != 0) {
         Debug::text('Daily Start Time is set, adjusting Last Pay Period End Date by: ' . TTDate::getHours($this->getDayStartTime()), __FILE__, __LINE__, __METHOD__, 10);
         //Next adjust last_pay_period_end_date (which becomes the start date) to DayStartTime because then there could be a gap if they
         //change this mid-schedule. The End Date will take care of it after the first pay period.
         $last_pay_period_end_date = TTDate::getTimeLockedDate(TTDate::getBeginDayEpoch($last_pay_period_end_date) + $this->getDayStartTime(), $last_pay_period_end_date);
         Debug::text('cLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
     }
     $insert_pay_period = 1;
     //deprecate primary pay periods.
     switch ($this->getType()) {
         case 10:
             //Weekly
         //Weekly
         case 20:
             //Bi-Weekly
             $last_pay_period_end_day_of_week = TTDate::getDayOfWeek($last_pay_period_end_date);
             Debug::text('Last Pay Period End Day Of Week: ' . $last_pay_period_end_day_of_week . ' Start Day Of Week: ' . $this->getStartDayOfWeek(), __LINE__, __METHOD__, 10);
             if ($last_pay_period_end_day_of_week != $this->getStartDayOfWeek()) {
                 Debug::text('zTmp Pay Period End Date: ' . 'next ' . TTDate::getDayOfWeekByInt($this->getStartDayOfWeek()), __FILE__, __LINE__, __METHOD__, 10);
                 //$tmp_pay_period_end_date = strtotime('next '. TTDate::getDayOfWeekByInt( $this->getStartDayOfWeek() ), $last_pay_period_end_date )-1;
                 $tmp_pay_period_end_date = strtotime('next ' . TTDate::getDayOfWeekByInt($this->getStartDayOfWeek(), FALSE), $last_pay_period_end_date);
                 //strtotime doesn't keep time when using "next", it resets it to midnight on the day, so we need to adjust for that.
                 $tmp_pay_period_end_date = TTDate::getTimeLockedDate(TTDate::getBeginDayEpoch($tmp_pay_period_end_date) + $this->getDayStartTime(), $tmp_pay_period_end_date) - 1;
             } else {
                 $tmp_pay_period_end_date = $last_pay_period_end_date;
                 //This should fix a bug where if they are creating a new pay period schedule
                 //starting on Monday with the anchor date of 01-Jul-08, it would start on 01-Jul-08 (Tue)
                 //rather moving back to the Monday.
                 if (TTDate::getDayOfMonth($tmp_pay_period_end_date) != TTDate::getDayOfMonth($tmp_pay_period_end_date + 1)) {
                     Debug::text('Right on day boundary, minus an additional second to account for difference...', __FILE__, __LINE__, __METHOD__, 10);
                     $tmp_pay_period_end_date--;
                 }
             }
             Debug::text('aTmp Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $tmp_pay_period_end_date) . ' (' . $tmp_pay_period_end_date . ')', __FILE__, __LINE__, __METHOD__, 10);
             $start_date = $tmp_pay_period_end_date + 1;
             if ($this->getType() == 10) {
                 //Weekly
                 $tmp_pay_period_end_date = TTDate::getMiddleDayEpoch($start_date) + 86400 * 7;
                 //Add one week
             } elseif ($this->getType() == 20) {
                 //Bi-Weekly
                 $tmp_pay_period_end_date = TTDate::getMiddleDayEpoch($start_date) + 86400 * 14;
                 //Add two weeks
             }
             //Use Begin Day Epoch to nullify DST issues.
             $end_date = TTDate::getBeginDayEpoch($tmp_pay_period_end_date) - 1;
             $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getMiddleDayEpoch($end_date) + $this->getTransactionDate() * 86400);
             break;
         case 30:
             //Semi-monthly
             $tmp_last_pay_period_end_day_of_month = TTDate::getDayOfMonth($last_pay_period_end_date + 1);
             Debug::text('bLast Pay Period End Day Of Month: ' . $tmp_last_pay_period_end_day_of_month, __FILE__, __LINE__, __METHOD__, 10);
             if ($tmp_last_pay_period_end_day_of_month == $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth())) {
                 $insert_pay_period = 1;
                 $primary = TRUE;
             } elseif ($tmp_last_pay_period_end_day_of_month == $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth())) {
                 $insert_pay_period = 2;
                 $primary = FALSE;
             } else {
                 Debug::text('Finding if Primary or Secondary is closest...', __FILE__, __LINE__, __METHOD__, 10);
                 $primary_date_offset = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth())) - $last_pay_period_end_date;
                 $secondary_date_offset = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth())) - $last_pay_period_end_date;
                 Debug::text('Primary Date Offset: ' . TTDate::getDays($primary_date_offset) . ' Secondary Date Offset: ' . TTDate::getDays($secondary_date_offset), __FILE__, __LINE__, __METHOD__, 10);
                 if ($primary_date_offset <= $secondary_date_offset) {
                     $insert_pay_period = 1;
                     $primary = TRUE;
                     $last_pay_period_end_date = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()));
                 } else {
                     $insert_pay_period = 2;
                     $primary = FALSE;
                     $last_pay_period_end_date = TTDate::getDateOfNextDayOfMonth($last_pay_period_end_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth()));
                 }
                 $last_pay_period_end_date = TTDate::getBeginDayEpoch($last_pay_period_end_date);
             }
             unset($tmp_last_pay_period_end_day_of_month);
             Debug::text('cLast Pay Period End Date: ' . TTDate::getDate('DATE+TIME', $last_pay_period_end_date) . ' (' . $last_pay_period_end_date . ') Primary: ' . (int) $primary, __FILE__, __LINE__, __METHOD__, 10);
             $start_date = $last_pay_period_end_date + 1;
             if ($primary == TRUE) {
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getDateOfNextDayOfMonth($start_date, NULL, $this->convertLastDayOfMonth($this->getSecondaryDayOfMonth()))) - 1;
                 $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth(TTDate::getMiddleDayEpoch($end_date), NULL, $this->convertLastDayOfMonth($this->getPrimaryTransactionDayOfMonth())));
             } else {
                 $end_date = TTDate::getBeginDayEpoch(TTDate::getDateOfNextDayOfMonth($start_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()))) - 1;
                 $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth(TTDate::getMiddleDayEpoch($end_date), NULL, $this->convertLastDayOfMonth($this->getSecondaryTransactionDayOfMonth())));
             }
             break;
         case 50:
             //Monthly
             $start_date = $last_pay_period_end_date + 1;
             $end_date = TTDate::getDateOfNextDayOfMonth($start_date + 86400, NULL, $this->convertLastDayOfMonth($this->getPrimaryDayOfMonth()));
             //Use Begin Day Epoch to nullify DST issues.
             $end_date = TTDate::getBeginDayEpoch(TTDate::getBeginMinuteEpoch($end_date)) - 1;
             $transaction_date = TTDate::getMiddleDayEpoch(TTDate::getDateOfNextDayOfMonth($end_date, NULL, $this->convertLastDayOfMonth($this->getPrimaryTransactionDayOfMonth())));
             break;
     }
     if ($this->getDayStartTime() != 0) {
         Debug::text('Daily Start Time is set, adjusting End Date by: ' . TTDate::getHours($this->getDayStartTime()) . ' Start Date: ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
         //We already account for DayStartTime in weekly/bi-weekly start_date cases above, so skip applying it again here.
         if ($this->getType() != 10 and $this->getType() != 20) {
             $start_date = $start_date + $this->getDayStartTime();
         }
         $end_date = $end_date + $this->getDayStartTime();
         //Need to do this, otherwise transaction date could be earlier then end date.
         $transaction_date = $transaction_date + $this->getDayStartTime();
     }
     Debug::text('aStart Date(' . $start_date . '): ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('aEnd Date(' . $end_date . '): ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('aPay Date(' . $transaction_date . '): ' . TTDate::getDate('DATE+TIME', $transaction_date), __FILE__, __LINE__, __METHOD__, 10);
     //Handle last day of the month flag for primary and secondary dates here
     if ($this->getType() == 30 and ($insert_pay_period == 1 and ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1) or $insert_pay_period == 2 and ($this->getSecondaryDayOfMonth() == 31 or $this->getSecondaryDayOfMonth() == -1)) or $this->getType() == 50 and ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1)) {
         Debug::text('Last day of the month set for start date: ', __FILE__, __LINE__, __METHOD__, 10);
         if ($this->getDayStartTime() > 0) {
             //Minus one day, THEN add daily start time, otherwise it will go past the month boundary
             $end_date = TTDate::getEndMonthEpoch($end_date) - 86400 + $this->getDayStartTime();
             //End month epoch is 23:59:59, so don't minus one.
         } else {
             $end_date = TTDate::getEndMonthEpoch($end_date) + $this->getDayStartTime();
             //End month epoch is 23:59:59, so don't minus one.
         }
     }
     //Handle "last day of the month" for transaction dates.
     if ($this->getPrimaryDayOfMonth() == 31 or $this->getPrimaryDayOfMonth() == -1) {
         //Debug::text('LDOM set for Primary: ', __FILE__, __LINE__, __METHOD__, 10);
         $transaction_date = TTDate::getEndMonthEpoch($transaction_date);
     }
     //Handle "always business day" flag for transaction dates here.
     if ($this->getTransactionDateBusinessDay() == TRUE) {
         $transaction_date = $this->getTransactionBusinessDay($transaction_date);
     }
     if ($transaction_date < $end_date) {
         $transaction_date = $end_date;
     }
     Debug::text('Start Date: ' . TTDate::getDate('DATE+TIME', $start_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text('Pay Date: ' . TTDate::getDate('DATE+TIME', $transaction_date), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text("<br><br>\n\n", __FILE__, __LINE__, __METHOD__, 10);
     $this->next_start_date = $start_date;
     $this->next_end_date = $end_date;
     $this->next_transaction_date = $transaction_date;
     //Its a primary pay period
     if ($insert_pay_period == 1) {
         $this->next_primary = TRUE;
     } else {
         $this->next_primary = FALSE;
     }
     return TRUE;
 }
 function getShifts($start_date, $end_date, &$holiday_data = array(), &$branch_options = array(), &$department_options = array(), &$n, &$shifts = array(), &$shifts_index = array(), $open_shift_conflict_index = array(), $permission_children_ids = NULL)
 {
     //Debug::text('Start Date: '. TTDate::getDate('DATE+TIME', $start_date) .' End Date: '. TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     $recurring_schedule_control_start_date = TTDate::strtotime($this->getColumn('recurring_schedule_control_start_date'));
     //Debug::text('Recurring Schedule Control Start Date: '. TTDate::getDate('DATE+TIME', $recurring_schedule_control_start_date),__FILE__, __LINE__, __METHOD__, 10);
     $current_template_week = $this->getColumn('remapped_week');
     $max_week = $this->getColumn('max_week');
     //Debug::text('Template Week: '. $current_template_week .' Max Week: '. $this->getColumn('max_week') .' ReMapped Week: '. $this->getColumn('remapped_week') ,__FILE__, __LINE__, __METHOD__, 10);
     if ($recurring_schedule_control_start_date == '') {
         return FALSE;
     }
     //Get week of start_date
     $start_date_week = TTDate::getBeginWeekEpoch($recurring_schedule_control_start_date, 0);
     //Start week on Sunday to match Recurring Schedule.
     //Debug::text('Week of Start Date: '. $start_date_week ,__FILE__, __LINE__, __METHOD__, 10);
     $apf = TTnew('AbsencePolicyFactory');
     $absence_policy_paid_type_options = $apf->getOptions('paid_type');
     for ($i = $start_date; $i <= $end_date; $i += 86400 + 43200) {
         //Handle DST by adding 12hrs to the date to get the mid-day epoch, then forcing it back to the beginning of the day.
         $i = TTDate::getBeginDayEpoch($i);
         if ($this->getColumn('hire_date') != '' and $i < $this->getColumn('hire_date') or $this->getColumn('termination_date') != '' and $i > $this->getColumn('termination_date')) {
             //Debug::text('Skipping due to Hire/Termination date: User ID: '. $this->getColumn('user_id') .' I: '. $i .' Hire Date: '. $this->getColumn('hire_date') .' Termination Date: '. $this->getColumn('termination_date') ,__FILE__, __LINE__, __METHOD__, 10);
             continue;
         }
         //This needs to take into account weeks spanning January 1st of each year. Where the week goes from 53 to 1.
         //Rather then use the week of the year, calculate the weeks between the recurring schedule start date and now.
         $current_week = round((TTDate::getBeginWeekEpoch($i, 0) - $start_date_week) / 604800);
         //Find out which week we are on based on the recurring schedule start date. Use round due to DST the week might be 6.9 or 7.1, so we need to round to the nearest full week.
         //Debug::text('I: '. $i .' User ID: '. $this->getColumn('user_id') .' Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week .' Start Week: '. $start_date_week,__FILE__, __LINE__, __METHOD__, 10);
         $template_week = $current_week % $max_week + 1;
         //Debug::text('Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
         if ($template_week == $current_template_week) {
             //Debug::text('Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week,__FILE__, __LINE__, __METHOD__, 10);
             //Debug::text('&nbsp;Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
             if ($this->isActiveShiftDay($i)) {
                 //Debug::text('&nbsp;&nbsp;Active Shift on this day...',__FILE__, __LINE__, __METHOD__, 10);
                 $start_time = TTDate::getTimeLockedDate($this->getStartTime(), $i);
                 $end_time = TTDate::getTimeLockedDate($this->getEndTime(), $i);
                 if ($end_time < $start_time) {
                     //Spans the day boundary, add 86400 to end_time
                     $end_time = $end_time + 86400;
                     //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Schedule spans day boundary, bumping endtime to next day: ',__FILE__, __LINE__, __METHOD__, 10);
                 }
                 $iso_date_stamp = TTDate::getISODateStamp(PayPeriodScheduleFactory::getShiftAssignedDate($start_time, $end_time, $this->getColumn('shift_assigned_day_id')));
                 //$iso_date_stamp = TTDate::getISODateStamp( $i );
                 $open_shift_multiplier = $this->getColumn('user_id') == 0 ? $this->getOpenShiftMultiplier() : 1;
                 //Debug::text('Open Shift Multiplier: '. $open_shift_multiplier,__FILE__, __LINE__, __METHOD__, 10);
                 for ($x = 0; $x < $open_shift_multiplier; $x++) {
                     //Check all non-OPEN shifts for conflicts.
                     if ($this->getColumn('user_id') > 0 and isset($shifts_index[$iso_date_stamp][$this->getColumn('user_id')])) {
                         //User has previous recurring schedule shifts, check for overlap.
                         //Loop over each employees shift for this day and check for conflicts
                         foreach ($shifts_index[$iso_date_stamp][$this->getColumn('user_id')] as $shift_key) {
                             if (isset($shifts[$iso_date_stamp][$shift_key])) {
                                 //Must use parseDateTime() when called from the API due to date formats that strtotime() fails on.
                                 if (TTDate::isTimeOverLap(defined('TIMETREX_API') ? TTDate::parseDateTime($shifts[$iso_date_stamp][$shift_key]['start_date']) : $shifts[$iso_date_stamp][$shift_key]['start_date'], defined('TIMETREX_API') ? TTDate::parseDateTime($shifts[$iso_date_stamp][$shift_key]['end_date']) : $shifts[$iso_date_stamp][$shift_key]['end_date'], $start_time, $end_time) == TRUE) {
                                     //Debug::text('&nbsp;&nbsp;Found overlapping recurring schedules! User ID: '. $this->getColumn('user_id') .' Start Time: '. $start_time,__FILE__, __LINE__, __METHOD__, 10);
                                     continue 2;
                                 }
                             }
                         }
                         unset($shift_key);
                     } elseif ($this->getColumn('user_id') == 0 and isset($shifts_index[$iso_date_stamp])) {
                         //Debug::text('    Checking OPEN shift conflicts... Date: '. $iso_date_stamp,__FILE__, __LINE__, __METHOD__, 10);
                         //Check all OPEN shifts for conflicts.
                         //This is special, since there can be multiple open shifts for the same branch,department,job,task, so we need to check if are conflicts with *any* employee.
                         //Do we allow conflicting shifts between committed and recurring OPEN shifts? For example what if there are two open shifts on the same day
                         //6AM-3PM (x2) and they want to override one of those shifts to 7AM-4PM? If we use this check:
                         //   ( $shifts[$iso_date_stamp][$shift_key]['user_id'] > 0 OR ( isset($shifts[$iso_date_stamp][$shift_key]['id']) AND $shifts[$iso_date_stamp][$shift_key]['id'] > 0 ) )
                         //That allows committed OPEN shifts to override recurring open shifts, which is great, but it prevents adding additional open shifts that may
                         //also overlap unless they override all recurring shifts first. I think this is the trade-off we have to make as its more likely that they
                         //will adjust an open shift time rather than add/remove specific shifts. Removing recurring OPEN shifts can be done by making them ABSENT.
                         //This will also affect when recurring OPEN shifts are committed by preventing the shifts from doubling up.
                         foreach ($shifts_index[$iso_date_stamp] as $tmp_index_user_id => $tmp_index_arr) {
                             foreach ($tmp_index_arr as $shift_key) {
                                 $tmp_start_date = defined('TIMETREX_API') ? TTDate::parseDateTime($shifts[$iso_date_stamp][$shift_key]['start_date']) : $shifts[$iso_date_stamp][$shift_key]['start_date'];
                                 $tmp_end_date = defined('TIMETREX_API') ? TTDate::parseDateTime($shifts[$iso_date_stamp][$shift_key]['end_date']) : $shifts[$iso_date_stamp][$shift_key]['end_date'];
                                 if (($shifts[$iso_date_stamp][$shift_key]['user_id'] > 0 or isset($shifts[$iso_date_stamp][$shift_key]['id']) and $shifts[$iso_date_stamp][$shift_key]['id'] > 0) and (!isset($open_shift_conflict_index['open'][$this->getID()][$shift_key]) and (isset($shifts[$iso_date_stamp][$shift_key]['id']) and !isset($open_shift_conflict_index['scheduled'][$shifts[$iso_date_stamp][$shift_key]['id']]))) and $this->getColumn('schedule_branch_id') == $shifts[$iso_date_stamp][$shift_key]['branch_id'] and $this->getColumn('schedule_department_id') == $shifts[$iso_date_stamp][$shift_key]['department_id'] and $this->getColumn('job_id') == $shifts[$iso_date_stamp][$shift_key]['job_id'] and $this->getColumn('job_item_id') == $shifts[$iso_date_stamp][$shift_key]['job_item_id'] and ($tmp_start_date == $start_time and $tmp_end_date == $end_time)) {
                                     //Debug::text('      Found OPEN shift conflict... Skipping...! Shift Key: '. $shift_key,__FILE__, __LINE__, __METHOD__, 10);
                                     //We need to track each shift_key that caused a conflict so it can't cause another conflict later on.
                                     //  Make sure we just track it on a per template basis though, otherwise the same $shift_key from a previous template can affect other templates.
                                     //  The above issue would show up as OPEN shifts not being overridden.
                                     //We also need to track which scheduled shift that caused a conflict so it can't cause another one later on.
                                     //  This prevents a single scheduled shift from overriding multiple OPEN shifts of different times.
                                     //However we need to be smarter about which shifts override which OPEN shifts...
                                     //  So if there are two open shifts, 10AM-4PM and 3:50PM-9PM, a 10AM-4PM scheduled shift overrides the OPEN shift that best fits it (10AM to 4PM, *not* 3:50-9PM)
                                     //  For now require an exact match to override an OPEN shift, if we start using partial schedules it gets much more complicated.
                                     //  Or we could introduce a hardcoded "fudge factor" setting (ie: 5 mins) that is always used instead.
                                     $open_shift_conflict_index['open'][$this->getID()][$shift_key] = TRUE;
                                     $open_shift_conflict_index['scheduled'][$shifts[$iso_date_stamp][$shift_key]['id']] = TRUE;
                                     continue 3;
                                 }
                                 unset($tmp_start_date, $tmp_end_date);
                             }
                         }
                         unset($tmp_index_user_id, $tmp_index_arr);
                     }
                     //This check has to occurr after the committed schedule check, otherwise no committed schedules will appear.
                     if ($this->getColumn('recurring_schedule_control_start_date') != '' and $i < TTDate::strtotime($this->getColumn('recurring_schedule_control_start_date')) or $this->getColumn('recurring_schedule_control_end_date') != '' and $i > TTDate::strtotime($this->getColumn('recurring_schedule_control_end_date'))) {
                         //Debug::text('Skipping due to Recurring Schedule Start/End date: ID: '. $this->getColumn('id') .' User ID: '. $this->getColumn('user_id') .' I: '. $i .' Start Date: '. $this->getColumn('recurring_schedule_control_start_date') .' ('. TTDate::strtotime( $this->getColumn('recurring_schedule_control_start_date') ) .') End Date: '. $this->getColumn('recurring_schedule_control_end_date') ,__FILE__, __LINE__, __METHOD__, 10);
                         continue;
                     }
                     //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start Date: '. TTDate::getDate('DATE+TIME', $start_time) .' End Date: '. TTDate::getDate('DATE+TIME', $end_time),__FILE__, __LINE__, __METHOD__, 10);
                     $status_id = $this->getColumn('status_id');
                     $absence_policy_id = $this->getColumn('absence_policy_id');
                     $absence_policy_type_id = $this->getColumn('absence_policy_type_id');
                     $absence_policy = $this->getColumn('absence_policy') != '' ? $this->getColumn('absence_policy') : NULL;
                     //Must be NULL to be converted to N/A
                     if (isset($holiday_data[$iso_date_stamp])) {
                         //We have to assume they are eligible, because we really won't know
                         //if they will have worked enough days or not. We could assume they
                         //work whatever their schedule is, but chances are they will be eligible then anyways.
                         //Debug::text('&nbsp;&nbsp;Found Holiday on this day...',__FILE__, __LINE__, __METHOD__, 10);
                         $status_id = $holiday_data[$iso_date_stamp]['status_id'];
                         if (isset($holiday_data[$iso_date_stamp]['absence_policy_id'])) {
                             $absence_policy_id = $holiday_data[$iso_date_stamp]['absence_policy_id'];
                             $absence_policy_type_id = $holiday_data[$iso_date_stamp]['type_id'];
                             $absence_policy = $holiday_data[$iso_date_stamp]['absence_policy'];
                         }
                     }
                     $hourly_rate = Misc::MoneyFormat($this->getColumn('user_wage_hourly_rate'), FALSE);
                     if ($absence_policy_id > 0 and in_array($absence_policy_type_id, $absence_policy_paid_type_options) == FALSE) {
                         //UnPaid Absence.
                         $total_time_wage = Misc::MoneyFormat(0);
                     } else {
                         $total_time_wage = Misc::MoneyFormat(bcmul(TTDate::getHours($this->getTotalTime()), $hourly_rate), FALSE);
                     }
                     //Debug::text('I: '. $i .' N: '. $n .' User ID: '. $this->getColumn('user_id') .' Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week .' Start Time: '. TTDate::getDate('DATE+TIME', $start_time ) .' Absence Policy: '. $absence_policy,__FILE__, __LINE__, __METHOD__, 10);
                     //$shifts[$iso_date_stamp][$this->getColumn('user_id').$start_time] = array(
                     $shifts[$iso_date_stamp][$n] = array('pay_period_id' => FALSE, 'user_id' => (int) $this->getColumn('user_id'), 'user_created_by' => $this->getColumn('user_created_by'), 'user_full_name' => $this->getColumn('user_id') > 0 ? Misc::getFullName($this->getColumn('first_name'), NULL, $this->getColumn('last_name'), FALSE, FALSE) : TTi18n::getText('OPEN'), 'first_name' => $this->getColumn('first_name'), 'last_name' => $this->getColumn('last_name'), 'title_id' => $this->getColumn('title_id'), 'title' => $this->getColumn('title'), 'group_id' => $this->getColumn('group_id'), 'group' => $this->getColumn('group'), 'default_branch_id' => $this->getColumn('default_branch_id'), 'default_branch' => $this->getColumn('default_branch'), 'default_department_id' => $this->getColumn('default_department_id'), 'default_department' => $this->getColumn('default_department'), 'job_id' => $this->getJob(), 'job' => $this->getColumn('job'), 'job_status_id' => $this->getColumn('job_status_id'), 'job_manual_id' => $this->getColumn('job_manual_id'), 'job_branch_id' => $this->getColumn('job_branch_id'), 'job_department_id' => $this->getColumn('job_department_id'), 'job_group_id' => $this->getColumn('job_group_id'), 'job_item_id' => $this->getJobItem(), 'job_item' => $this->getColumn('job_item'), 'type_id' => 20, 'status_id' => $status_id, 'date_stamp' => TTDate::getAPIDate('DATE', strtotime($iso_date_stamp)), 'start_date_stamp' => defined('TIMETREX_API') ? TTDate::getAPIDate('DATE', $start_time) : $start_time, 'start_date' => defined('TIMETREX_API') ? TTDate::getAPIDate('DATE+TIME', $start_time) : $start_time, 'end_date' => defined('TIMETREX_API') ? TTDate::getAPIDate('DATE+TIME', $end_time) : $end_time, 'start_time' => defined('TIMETREX_API') ? TTDate::getAPIDate('TIME', $start_time) : $start_time, 'end_time' => defined('TIMETREX_API') ? TTDate::getAPIDate('TIME', $end_time) : $end_time, 'start_time_stamp' => $start_time, 'end_time_stamp' => $end_time, 'total_time' => $this->getTotalTime(), 'hourly_rate' => $hourly_rate, 'total_time_wage' => $total_time_wage, 'note' => FALSE, 'schedule_policy_id' => $this->getSchedulePolicyID(), 'absence_policy_id' => $absence_policy_id, 'absence_policy' => $absence_policy, 'branch_id' => $this->getColumn('schedule_branch_id'), 'branch' => $this->getColumn('schedule_branch'), 'department_id' => $this->getColumn('schedule_department_id'), 'department' => $this->getColumn('schedule_department'), 'created_by_id' => $this->getColumn('recurring_schedule_control_created_by'), 'created_date' => $this->getCreatedDate(), 'updated_date' => $this->getUpdatedDate());
                     //Make sure we add in permission columns.
                     $this->getPermissionColumns($shifts[$iso_date_stamp][$n], (int) $this->getColumn('user_id'), $this->getColumn('recurring_schedule_control_created_by'), $permission_children_ids);
                     //$shifts_index[$iso_date_stamp][$this->getColumn('user_id')][] = $this->getColumn('user_id').$start_time;
                     $shifts_index[$iso_date_stamp][$this->getColumn('user_id')][] = $n;
                     $n++;
                 }
                 unset($open_shift_multiplier);
                 unset($start_time, $end_time);
             } else {
                 //Debug::text('&nbsp;&nbsp;NOT active shift on this day... ID: '. $this->getColumn('id') .' User ID: '. $this->getColumn('user_id') .' Start Time: '. TTDate::getDate('DATE+TIME', $i),__FILE__, __LINE__, __METHOD__, 10);
             }
         }
     }
     if (isset($shifts)) {
         //Debug::Arr($shifts, 'Template Shifts: ',__FILE__, __LINE__, __METHOD__, 10);
         return $shifts;
     }
     return FALSE;
 }
 function getShiftsByStartDateAndEndDate($start_date, $end_date)
 {
     //Make sure timezone isn't in the time format. Because recurring schedules
     //are timezone agnostic. 7:00AM in PST is also 7:00AM in EST.
     //This causes an issue where the previous users timezone carries over to the next
     //users timezone, causing errors.
     //TTDate::setTimeFormat('g:i A');
     if ($start_date == '') {
         return FALSE;
     }
     if ($end_date == '') {
         return FALSE;
     }
     if ($start_date < $this->getStartDate()) {
         $start_date = $this->getStartDate();
     }
     if ($this->getEndDate(TRUE) != NULL and $end_date > $this->getEndDate()) {
         $end_date = $this->getEndDate();
     }
     Debug::text('Start Date: ' . TTDate::getDate('DATE+TIME', $start_date) . ' End Date: ' . TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     //Get week data
     $rstlf = new RecurringScheduleTemplateListFactory();
     $rstlf->getByRecurringScheduleTemplateControlId($this->getRecurringScheduleTemplateControl())->getCurrent();
     $max_week = 1;
     $weeks = array();
     if ($rstlf->getRecordCount() > 0) {
         foreach ($rstlf as $rst_obj) {
             Debug::text('Week: ' . $rst_obj->getWeek(), __FILE__, __LINE__, __METHOD__, 10);
             $template_week_rows[$rst_obj->getWeek()][] = $rst_obj->getObjectAsArray();
             $weeks[$rst_obj->getWeek()] = $rst_obj->getWeek();
             if ($rst_obj->getWeek() > $max_week) {
                 $max_week = $rst_obj->getWeek();
             }
         }
     }
     $weeks = $this->ReMapWeeks($weeks);
     //Get week of start_date
     $start_date_week = TTDate::getWeek($this->getStartDate(), 0);
     //Start week on Sunday to match Recurring Schedule.
     Debug::text('Week of Start Date: ' . $start_date_week, __FILE__, __LINE__, __METHOD__, 10);
     for ($i = $start_date; $i <= $end_date; $i += 86400) {
         $current_week = TTDate::getWeek($i, 0);
         //Start week on Sunday to match Recurring Schedule.
         //Debug::text('Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week,__FILE__, __LINE__, __METHOD__, 10);
         $template_week = abs($current_week - $start_date_week) % $max_week + 1;
         //Debug::text('Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
         $day_of_week = strtolower(date('D', $i));
         //Debug::text('Day Of Week: '. $day_of_week,__FILE__, __LINE__, __METHOD__, 10);
         if (isset($weeks[$template_week])) {
             $mapped_template_week = $weeks[$template_week];
             //Debug::text('&nbsp;&nbsp;Mapped Template Week: '. $mapped_template_week,__FILE__, __LINE__, __METHOD__, 10);
             if (isset($template_week_rows[$mapped_template_week])) {
                 //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;Starting Looping...!',__FILE__, __LINE__, __METHOD__, 10);
                 foreach ($template_week_rows[$mapped_template_week] as $template_week_arr) {
                     if ($template_week_arr['days'][$day_of_week] == TRUE) {
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Found Scheduled Time: Start Time: '. TTDate::getDate('DATE+TIME', TTDate::getTimeLockedDate( $template_week_arr['start_time'], $i ) ),__FILE__, __LINE__, __METHOD__, 10);
                         $start_time = TTDate::getTimeLockedDate($template_week_arr['start_time'], $i);
                         $end_time = TTDate::getTimeLockedDate($template_week_arr['end_time'], $i);
                         if ($end_time < $start_time) {
                             //Spans the day boundary, add 86400 to end_time
                             $end_time = $end_time + 86400;
                             //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Schedule spans day boundary, bumping endtime to next day: ',__FILE__, __LINE__, __METHOD__, 10);
                         }
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start Date: '. TTDate::getDate('DATE+TIME', $start_time) .' End Date: '. TTDate::getDate('DATE+TIME', $end_time),__FILE__, __LINE__, __METHOD__, 10);
                         //$shifts[TTDate::getBeginDayEpoch($i)][] = array(
                         $shifts[TTDate::getISODateStamp($i)][] = array('status_id' => $template_week_arr['status_id'], 'start_time' => $start_time, 'raw_start_time' => TTDate::getDate('DATE+TIME', $start_time), 'end_time' => $end_time, 'raw_end_time' => TTDate::getDate('DATE+TIME', $end_time), 'total_time' => $template_week_arr['total_time'], 'schedule_policy_id' => $template_week_arr['schedule_policy_id'], 'branch_id' => $template_week_arr['branch_id'], 'department_id' => $template_week_arr['department_id'], 'job_id' => $template_week_arr['job_id'], 'job_item_id' => $template_week_arr['job_item_id']);
                         unset($start_time, $end_time);
                     } else {
                         //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;aSkipping!',__FILE__, __LINE__, __METHOD__, 10);
                     }
                 }
             } else {
                 //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;bSkipping!',__FILE__, __LINE__, __METHOD__, 10);
             }
         } else {
             //Debug::text('&nbsp;&nbsp;cSkipping!',__FILE__, __LINE__, __METHOD__, 10);
         }
     }
     //var_dump($shifts);
     if (isset($shifts)) {
         return $shifts;
     }
     return FALSE;
 }
 function isActiveTime($in_epoch, $out_epoch)
 {
     Debug::text(' Checking for Active Time with: In: ' . TTDate::getDate('DATE+TIME', $in_epoch) . ' Out: ' . TTDate::getDate('DATE+TIME', $out_epoch), __FILE__, __LINE__, __METHOD__, 10);
     Debug::text(' Raw Start TimeStamp(' . $this->getStartTime(TRUE) . '): ' . TTDate::getDate('DATE+TIME', $this->getStartTime()) . ' Raw End TimeStamp: ' . TTDate::getDate('DATE+TIME', $this->getEndTime()), __FILE__, __LINE__, __METHOD__, 10);
     $start_time_stamp = TTDate::getTimeLockedDate($this->getStartTime(), $in_epoch);
     $end_time_stamp = TTDate::getTimeLockedDate($this->getEndTime(), $in_epoch);
     //Check if end timestamp is before start, if it is, move end timestamp to next day.
     if ($end_time_stamp < $start_time_stamp) {
         Debug::text(' Moving End TimeStamp to next day.', __FILE__, __LINE__, __METHOD__, 10);
         $end_time_stamp = $end_time_stamp + 86400;
     }
     Debug::text(' Start TimeStamp: ' . TTDate::getDate('DATE+TIME', $start_time_stamp) . ' End TimeStamp: ' . TTDate::getDate('DATE+TIME', $end_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
     //Check to see if start/end time stamps are not set or are equal, we always return TRUE if they are.
     if ($start_time_stamp == '' or $end_time_stamp == '' or $start_time_stamp == $end_time_stamp) {
         Debug::text(' Start/End time not set, assume it always matches.', __FILE__, __LINE__, __METHOD__, 10);
         return TRUE;
     } else {
         //If the premium policy start/end time spans midnight, there could be multiple windows to check
         //where the premium policy applies, make sure we check all windows.
         for ($i = $start_time_stamp - 86400; $i <= $end_time_stamp + 86400; $i += 86400) {
             $tmp_start_time_stamp = $i;
             $tmp_end_time_stamp = $tmp_start_time_stamp + ($end_time_stamp - $start_time_stamp);
             if ($this->isActive($tmp_start_time_stamp, $tmp_end_time_stamp) == TRUE) {
                 //Debug::text(' Checking against Start TimeStamp: '. TTDate::getDate('DATE+TIME', $tmp_start_time_stamp) .' End TimeStamp: '. TTDate::getDate('DATE+TIME', $tmp_end_time_stamp)  , __FILE__, __LINE__, __METHOD__, 10);
                 if ($this->getIncludePartialPunch() == TRUE and TTDate::isTimeOverLap($in_epoch, $out_epoch, $tmp_start_time_stamp, $tmp_end_time_stamp) == TRUE) {
                     //When dealing with partial punches, any overlap whatsoever activates the policy.
                     Debug::text(' Partial Punch Within Active Time!', __FILE__, __LINE__, __METHOD__, 10);
                     return TRUE;
                 } elseif ($in_epoch >= $tmp_start_time_stamp and $in_epoch <= $tmp_end_time_stamp) {
                     //Non partial punches, they must punch in within the time window.
                     Debug::text(' Within Active Time!', __FILE__, __LINE__, __METHOD__, 10);
                     return TRUE;
                 }
             } else {
                 Debug::text(' Not Active on this day: ' . TTDate::getDate('DATE+TIME', $i), __FILE__, __LINE__, __METHOD__, 10);
             }
         }
     }
     Debug::text(' NOT Within Active Time!', __FILE__, __LINE__, __METHOD__, 10);
     return FALSE;
 }
 static function dragNdropPunch($company_id, $src_punch_id, $dst_punch_id, $dst_status_id = NULL, $position = 0, $action = 0, $dst_date = NULL)
 {
     /*
     	FIXME: This needs to handle batches to be able to handle all the differnet corner cases.
     	Operations to handle:
     		- Moving punch from Out to In, or In to Out in same punch pair, this is ALWAYS a move, and not a copy.
     		- Move punch from one pair to another in the same day, this can be a copy or move.
     			- Check moving AND copying Out punch from one punch pair to In in another on the same day. ie: In 8:00AM, Out 1:00PM, Out 5:00PM. Move the 1PM punch to pair with 5PM.
     		- Move punch from one day to another, inserting inbetween other punches if necessary.
     		- Move punch from one day to another without any other punches.
     
     
     		- Inserting BEFORE on a dst_punch_id that is an In punch doesn't do any splitting.
     		- Inserting AFTER on a dst_punch_id that is on a Out punch doesn't do any splitting.
     		- Overwriting should just take the punch time and overwrite the existing punch time.
     		- The first thing this function does it check if there are two punches assigned to the punch control of the destination punch, if there is, it splits the punches
     			across two punch_controls, it then attaches the src_punch_id to the same punch_control_id as the dst_punch_id.
     		- If no dst_punch_id is specified, assume copying to a blank cell, just copy the punch to that date along with the punch_control?
     		- Copying punches that span midnight work, however moving punches does not always
     			since we don't move punches in batches, we do it one at a time, and when the first punch punch
     			gets moved, it can cause other punches to follow it automatically.
     */
     $dst_date = TTDate::getMiddleDayEpoch($dst_date);
     Debug::text('Src Punch ID: ' . $src_punch_id . ' Dst Punch ID: ' . $dst_punch_id . ' Dst Status ID: ' . $dst_status_id . ' Position: ' . $position . ' Action: ' . $action . ' Dst Date: ' . $dst_date, __FILE__, __LINE__, __METHOD__, 10);
     $retval = FALSE;
     //Get source and destination punch objects.
     $plf = TTnew('PunchListFactory');
     $plf->StartTransaction();
     $plf->getByCompanyIDAndId($company_id, $src_punch_id);
     if ($plf->getRecordCount() == 1) {
         $src_punch_obj = $plf->getCurrent();
         $src_punch_date = TTDate::getMiddleDayEpoch($src_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp());
         Debug::text('Found SRC punch ID: ' . $src_punch_id . ' Source Punch Date: ' . $src_punch_date, __FILE__, __LINE__, __METHOD__, 10);
         //Get the PunchControlObject as early as possible, before the punch is deleted, as it will be cleared even if Save(FALSE) is called below.
         $src_punch_control_obj = clone $src_punch_obj->getPunchControlObject();
         if (TTDate::getMiddleDayEpoch($src_punch_date) != TTDate::getMiddleDayEpoch($src_punch_obj->getTimeStamp())) {
             Debug::text('Punch spans midnight... Source Punch Date: ' . TTDate::getDATE('DATE+TIME', $src_punch_date) . ' Source Punch TimeStamp: ' . TTDate::getDATE('DATE+TIME', $src_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
             $dst_date_modifier = 86400;
             //Bump day by 24hrs.
         } else {
             $dst_date_modifier = 0;
         }
         //If we are moving the punch, we need to delete the source punch first so it doesn't conflict with the new punch.
         //Especially if we are just moving a punch to fill a gap in the same day.
         //If the punch being moved is in the same day, or within the same punch pair, we don't want to delete the source punch, instead we just modify
         //the necessary bits later on. So we need to short circuit the move functionality when copying/moving punches within the same day.
         if ($action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date != $dst_date or $action == 1 and $src_punch_id != $dst_punch_id and $src_punch_date == $dst_date) {
             //Move
             Debug::text('Deleting original punch...: ' . $src_punch_id, __FILE__, __LINE__, __METHOD__, 10);
             $src_punch_obj->setUser($src_punch_control_obj->getUserDateObject()->getUser());
             $src_punch_obj->setDeleted(TRUE);
             //These aren't doing anything because they aren't acting on the PunchControl object?
             $src_punch_obj->setEnableCalcTotalTime(TRUE);
             $src_punch_obj->setEnableCalcSystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
             $src_punch_obj->setEnableCalcUserDateTotal(TRUE);
             $src_punch_obj->setEnableCalcException(TRUE);
             $src_punch_obj->Save(FALSE);
             //Keep object around for later.
         } else {
             Debug::text('NOT Deleting original punch, either in copy mode or condition is not met...', __FILE__, __LINE__, __METHOD__, 10);
         }
         if ($src_punch_id == $dst_punch_id or $dst_punch_id == '') {
             //Assume we are just moving a punch within the same punch pair, unless a new date is specfied.
             //However if we're simply splitting an existing punch pair, like dragging the Out punch from an In/Out pair into its own separate pair.
             if ($src_punch_date != $dst_date or $src_punch_date == $dst_date and $dst_punch_id == '') {
                 Debug::text('aCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch to a new date.
                 //Copy source punch to proper location by destination punch.
                 $src_punch_obj->setId(FALSE);
                 $src_punch_obj->setPunchControlId((int) $src_punch_control_obj->getNextInsertId());
                 $src_punch_obj->setDeleted(FALSE);
                 //Just in case it was marked deleted by the MOVE action.
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_date + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $src_punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $src_punch_obj->setActualTimeStamp($new_time_stamp);
                 $src_punch_obj->setOriginalTimeStamp($new_time_stamp);
                 if ($dst_status_id != '') {
                     $src_punch_obj->setStatus($dst_status_id);
                     //Change the status to fit in the proper place.
                 }
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 if ($src_punch_obj->isValid() == TRUE) {
                     $insert_id = $src_punch_obj->Save(FALSE);
                     $src_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days.
                     $src_punch_control_obj->user_date_obj = NULL;
                     //Need to clear user_date_obj from cache so a new one is obtained.
                     $src_punch_control_obj->setId($src_punch_obj->getPunchControlID());
                     $src_punch_control_obj->setPunchObject($src_punch_obj);
                     if ($src_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $src_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $src_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $src_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $src_punch_control_obj->setEnableCalcException(TRUE);
                         if ($src_punch_control_obj->isValid() == TRUE) {
                             if ($src_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                             }
                         }
                     }
                 }
             } else {
                 Debug::text('Copying punch within same pair/day...', __FILE__, __LINE__, __METHOD__, 10);
                 //Moving punch within the same punch pair.
                 $src_punch_obj->setStatus($src_punch_obj->getNextStatus());
                 //Change just the punch status.
                 //$src_punch_obj->setDeleted(FALSE); //Just in case it was marked deleted by the MOVE action.
                 if ($src_punch_obj->isValid() == TRUE) {
                     //Return punch_id, so Flex can base other actions on it.
                     $retval = $src_punch_obj->Save(FALSE);
                 }
             }
         } else {
             Debug::text('bCopying punch to new day...', __FILE__, __LINE__, __METHOD__, 10);
             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
             if ($plf->getRecordCount() == 1) {
                 Debug::text('Found DST punch ID: ' . $dst_punch_id, __FILE__, __LINE__, __METHOD__, 10);
                 $dst_punch_obj = $plf->getCurrent();
                 $dst_punch_control_obj = $dst_punch_obj->getPunchControlObject();
                 Debug::text('aSRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()), __FILE__, __LINE__, __METHOD__, 10);
                 $is_punch_control_split = FALSE;
                 if ($position == 0) {
                     //Overwrite
                     Debug::text('Overwriting...', __FILE__, __LINE__, __METHOD__, 10);
                     //All we need to do is update the time of the destination punch.
                     $punch_obj = $dst_punch_obj;
                 } else {
                     //Before or After
                     //Determine if the destination punch needs to split from another punch
                     if ($position == -1 and $dst_punch_obj->getStatus() == 20 or $position == 1 and $dst_punch_obj->getStatus() == 10) {
                         //Before on Out punch, After on In Punch,
                         Debug::text('Need to split destination punch out to its own Punch Control row...', __FILE__, __LINE__, __METHOD__, 10);
                         $is_punch_control_split = PunchControlFactory::splitPunchControl($dst_punch_obj->getPunchControlID());
                         //Once a split occurs, we need to re-get the destination punch as the punch_control_id may have changed.
                         //We could probably optimize this to only occur when the destination punch is an In punch, as the
                         //Out punch is always the one to be moved to a new punch_control_id
                         if ($src_punch_obj->getStatus() != $dst_punch_obj->getStatus()) {
                             $plf->getByCompanyIDAndId($company_id, $dst_punch_id);
                             if ($plf->getRecordCount() == 1) {
                                 $dst_punch_obj = $plf->getCurrent();
                                 Debug::text('Found DST punch ID: ' . $dst_punch_id . ' Punch Control ID: ' . $dst_punch_obj->getPunchControlID(), __FILE__, __LINE__, __METHOD__, 10);
                             }
                         }
                         $punch_control_id = $dst_punch_obj->getPunchControlID();
                     } else {
                         Debug::text('No Need to split destination punch, simply add a new punch/punch_control all on its own.', __FILE__, __LINE__, __METHOD__, 10);
                         //Check to see if the src and dst punches are the same status though.
                         $punch_control_id = (int) $dst_punch_control_obj->getNextInsertId();
                     }
                     //Take the source punch and base our new punch on that.
                     $punch_obj = $src_punch_obj;
                     //Copy source punch to proper location by destination punch.
                     $punch_obj->setId(FALSE);
                     $punch_obj->setDeleted(FALSE);
                     //Just in case it was marked deleted by the MOVE action.
                     $punch_obj->setPunchControlId($punch_control_id);
                 }
                 //$new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getTimeStamp()+$dst_date_modifier );
                 $new_time_stamp = TTDate::getTimeLockedDate($src_punch_obj->getTimeStamp(), $dst_punch_obj->getPunchControlObject()->getUserDateObject()->getDateStamp() + $dst_date_modifier);
                 Debug::text('SRC TimeStamp: ' . TTDate::getDate('DATE+TIME', $src_punch_obj->getTimeStamp()) . ' DST TimeStamp: ' . TTDate::getDate('DATE+TIME', $dst_punch_obj->getTimeStamp()) . ' New TimeStamp: ' . TTDate::getDate('DATE+TIME', $new_time_stamp), __FILE__, __LINE__, __METHOD__, 10);
                 $punch_obj->setTimeStamp($new_time_stamp, FALSE);
                 $punch_obj->setActualTimeStamp($new_time_stamp);
                 $punch_obj->setOriginalTimeStamp($new_time_stamp);
                 $src_punch_obj->setStation(NULL);
                 //When drag&drop copying punches, clear the station.
                 //Need to take into account copying a Out punch and inserting it BEFORE another Out punch in a punch pair.
                 //In this case a split needs to occur, and the status needs to stay the same.
                 //Status also needs to stay the same when overwriting an existing punch.
                 Debug::text('Punch Status: ' . $punch_obj->getStatus() . ' DST Punch Status: ' . $dst_punch_obj->getStatus() . ' Split Punch Control: ' . (int) $is_punch_control_split, __FILE__, __LINE__, __METHOD__, 10);
                 if ($position != 0 and $is_punch_control_split == FALSE and $punch_obj->getStatus() == $dst_punch_obj->getStatus() and $punch_obj->getPunchControlID() == $dst_punch_obj->getPunchControlID()) {
                     Debug::text('Changing punch status to opposite: ' . $dst_punch_obj->getNextStatus(), __FILE__, __LINE__, __METHOD__, 10);
                     $punch_obj->setStatus($dst_punch_obj->getNextStatus());
                     //Change the status to fit in the proper place.
                 }
                 if ($punch_obj->isValid() == TRUE) {
                     $insert_id = $punch_obj->Save(FALSE);
                     $dst_punch_control_obj->shift_data = NULL;
                     //Need to clear the shift data so its obtained from the DB again, otherwise shifts will appear on strange days, or cause strange conflicts.
                     $dst_punch_control_obj->setID($punch_obj->getPunchControlID());
                     $dst_punch_control_obj->setPunchObject($punch_obj);
                     if ($dst_punch_control_obj->isValid() == TRUE) {
                         Debug::Text(' Punch Control is valid, saving...: ', __FILE__, __LINE__, __METHOD__, 10);
                         //We need to calculate new total time for the day and exceptions because we are never guaranteed that the gaps will be filled immediately after
                         //in the case of a drag & drop or something.
                         $dst_punch_control_obj->setEnableStrictJobValidation(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateID(TRUE);
                         $dst_punch_control_obj->setEnableCalcTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcSystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcWeeklySystemTotalTime(TRUE);
                         $dst_punch_control_obj->setEnableCalcUserDateTotal(TRUE);
                         $dst_punch_control_obj->setEnableCalcException(TRUE);
                         if ($dst_punch_control_obj->isValid() == TRUE) {
                             if ($dst_punch_control_obj->Save(TRUE, TRUE) == TRUE) {
                                 //Force isNew() lookup.
                                 //Return newly inserted punch_id, so Flex can base other actions on it.
                                 $retval = $insert_id;
                                 //$retval = TRUE;
                             }
                         }
                     }
                 }
             }
         }
     }
     if ($retval == FALSE) {
         $plf->FailTransaction();
     }
     //$plf->FailTransaction();
     $plf->CommitTransaction();
     Debug::text('Returning: ' . (int) $retval, __FILE__, __LINE__, __METHOD__, 10);
     return $retval;
 }
 function setTransactionDate($epoch)
 {
     $epoch = trim($epoch);
     if ($epoch != '') {
         //Make sure all pay periods transact at noon.
         $epoch = TTDate::getTimeLockedDate(strtotime('12:00:00', $epoch), $epoch);
         //Unless they are on the same date as the end date, then it should match that.
         if ($this->getEndDate() != '' and $this->getEndDate() > $epoch) {
             $epoch = $this->getEndDate();
         }
     }
     if ($this->Validator->isDate('transaction_date', $epoch, TTi18n::gettext('Incorrect transaction date'))) {
         $this->data['transaction_date'] = $epoch;
         return TRUE;
     }
     return FALSE;
 }
 function getShifts($start_date, $end_date, &$holiday_data = array(), &$branch_options = array(), &$department_options = array(), &$shifts = array(), &$shifts_index = array())
 {
     //Debug::text('Start Date: '. TTDate::getDate('DATE+TIME', $start_date) .' End Date: '. TTDate::getDate('DATE+TIME', $end_date), __FILE__, __LINE__, __METHOD__, 10);
     $recurring_schedule_control_start_date = TTDate::strtotime($this->getColumn('recurring_schedule_control_start_date'));
     //Debug::text('Recurring Schedule Control Start Date: '. TTDate::getDate('DATE+TIME', $recurring_schedule_control_start_date),__FILE__, __LINE__, __METHOD__, 10);
     $current_template_week = $this->getColumn('remapped_week');
     $max_week = $this->getColumn('max_week');
     //Debug::text('Template Week: '. $current_template_week .' Max Week: '. $this->getColumn('max_week') .' ReMapped Week: '. $this->getColumn('remapped_week') ,__FILE__, __LINE__, __METHOD__, 10);
     if ($recurring_schedule_control_start_date == '') {
         return FALSE;
     }
     //Get week of start_date
     $start_date_week = TTDate::getWeek($recurring_schedule_control_start_date, 0);
     //Start week on Sunday to match Recurring Schedule.
     //Debug::text('Week of Start Date: '. $start_date_week ,__FILE__, __LINE__, __METHOD__, 10);
     for ($i = $start_date; $i <= $end_date; $i += 86400 + 43200) {
         //Handle DST by adding 12hrs to the date to get the mid-day epoch, then forcing it back to the beginning of the day.
         $i = TTDate::getBeginDayEpoch($i);
         if ($this->getColumn('hire_date') != '' and $i <= $this->getColumn('hire_date') or $this->getColumn('termination_date') != '' and $i > $this->getColumn('termination_date')) {
             //Debug::text('Skipping due to Hire/Termination date: User ID: '. $this->getColumn('user_id') .' I: '. $i .' Hire Date: '. $this->getColumn('hire_date') .' Termination Date: '. $this->getColumn('termination_date') ,__FILE__, __LINE__, __METHOD__, 10);
             continue;
         }
         $current_week = TTDate::getWeek($i, 0);
         //Start week on Sunday to match Recurring Schedule.
         //Debug::text('I: '. $i .' User ID: '. $this->getColumn('user_id') .' Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week,__FILE__, __LINE__, __METHOD__, 10);
         $template_week = abs($current_week - $start_date_week) % $max_week + 1;
         //Debug::text('Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
         if ($template_week == $current_template_week) {
             //Debug::text('Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week,__FILE__, __LINE__, __METHOD__, 10);
             //Debug::text('&nbsp;Template Week: '. $template_week .' Max Week: '. $max_week,__FILE__, __LINE__, __METHOD__, 10);
             if ($this->isActiveShiftDay($i)) {
                 //Debug::text('&nbsp;&nbsp;Active Shift on this day...',__FILE__, __LINE__, __METHOD__, 10);
                 $iso_date_stamp = TTDate::getISODateStamp($i);
                 $start_time = TTDate::getTimeLockedDate($this->getStartTime(), $i);
                 $end_time = TTDate::getTimeLockedDate($this->getEndTime(), $i);
                 if ($end_time < $start_time) {
                     //Spans the day boundary, add 86400 to end_time
                     $end_time = $end_time + 86400;
                     //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Schedule spans day boundary, bumping endtime to next day: ',__FILE__, __LINE__, __METHOD__, 10);
                 }
                 if (isset($shifts_index[$iso_date_stamp][$this->getColumn('user_id')])) {
                     //User has previous recurring schedule shifts, check for overlap.
                     //Loop over each employees shift for this day and check for conflicts
                     foreach ($shifts_index[$iso_date_stamp][$this->getColumn('user_id')] as $shift_key) {
                         if (isset($shifts[$iso_date_stamp][$shift_key])) {
                             if (TTDate::isTimeOverLap($shifts[$iso_date_stamp][$shift_key]['start_time'], $shifts[$iso_date_stamp][$shift_key]['end_time'], $start_time, $end_time) == TRUE) {
                                 //Debug::text('&nbsp;&nbsp;Found overlapping recurring schedules! User ID: '. $this->getColumn('user_id') .' Start Time: '. $start_time,__FILE__, __LINE__, __METHOD__, 10);
                                 continue 2;
                             }
                         }
                     }
                     unset($shift_key);
                 }
                 //This check has to occurr after the committed schedule check, otherwise no committed schedules will appear.
                 if ($this->getColumn('recurring_schedule_control_start_date') != '' and $i < TTDate::strtotime($this->getColumn('recurring_schedule_control_start_date')) or $this->getColumn('recurring_schedule_control_end_date') != '' and $i > TTDate::strtotime($this->getColumn('recurring_schedule_control_end_date'))) {
                     //Debug::text('Skipping due to Recurring Schedule Start/End date: ID: '. $this->getColumn('id') .' User ID: '. $this->getColumn('user_id') .' I: '. $i .' Start Date: '. $this->getColumn('recurring_schedule_control_start_date') .' ('. TTDate::strtotime( $this->getColumn('recurring_schedule_control_start_date') ) .') End Date: '. $this->getColumn('recurring_schedule_control_end_date') ,__FILE__, __LINE__, __METHOD__, 10);
                     continue;
                 }
                 //Debug::text('&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Start Date: '. TTDate::getDate('DATE+TIME', $start_time) .' End Date: '. TTDate::getDate('DATE+TIME', $end_time),__FILE__, __LINE__, __METHOD__, 10);
                 $status_id = 10;
                 //Working
                 $absence_policy_id = FALSE;
                 $absence_policy = NULL;
                 if (isset($holiday_data[$iso_date_stamp])) {
                     //We have to assume they are eligible, because we really won't know
                     //if they will have worked enough days or not. We could assume they
                     //work whatever their schedule is, but chances are they will be eligible then anyways.
                     Debug::text('&nbsp;&nbsp;Found Holiday on this day...', __FILE__, __LINE__, __METHOD__, 10);
                     $status_id = $holiday_data[$iso_date_stamp]['status_id'];
                     if (isset($holiday_data[$iso_date_stamp]['absence_policy_id'])) {
                         $absence_policy_id = $holiday_data[$iso_date_stamp]['absence_policy_id'];
                         $absence_policy = $holiday_data[$iso_date_stamp]['absence_policy'];
                     }
                 }
                 //Debug::text('I: '. $i .' User ID: '. $this->getColumn('user_id') .' Current Date: '. TTDate::getDate('DATE+TIME', $i) .' Current Week: '. $current_week .' Start Time: '. TTDate::getDate('DATE+TIME', $start_time ),__FILE__, __LINE__, __METHOD__, 10);
                 $shifts[$iso_date_stamp][$this->getColumn('user_id') . $start_time] = array('user_id' => $this->getColumn('user_id'), 'user_full_name' => Misc::getFullName($this->getColumn('first_name'), NULL, $this->getColumn('last_name'), FALSE, FALSE), 'user_created_by' => $this->getColumn('user_created_by'), 'status_id' => $status_id, 'date_stamp' => TTDate::getAPIDate('DATE', $start_time), 'start_date' => defined('TIMETREX_API') ? TTDate::getAPIDate('DATE+TIME', $start_time) : $start_time, 'end_date' => defined('TIMETREX_API') ? TTDate::getAPIDate('DATE+TIME', $end_time) : $end_time, 'start_time' => defined('TIMETREX_API') ? TTDate::getAPIDate('TIME', $start_time) : $start_time, 'end_time' => defined('TIMETREX_API') ? TTDate::getAPIDate('TIME', $end_time) : $end_time, 'total_time' => $this->getTotalTime(), 'schedule_policy_id' => $this->getSchedulePolicyID(), 'absence_policy_id' => $absence_policy_id, 'absence_policy' => $absence_policy, 'branch_id' => $this->getColumn('schedule_branch_id'), 'branch' => Option::getByKey($this->getColumn('schedule_branch_id'), $branch_options, NULL), 'department_id' => $this->getColumn('schedule_department_id'), 'department' => Option::getByKey($this->getColumn('schedule_department_id'), $department_options, NULL), 'job_id' => $this->getJob(), 'job_item_id' => $this->getJobItem());
                 $shifts_index[$iso_date_stamp][$this->getColumn('user_id')][] = $this->getColumn('user_id') . $start_time;
                 unset($start_time, $end_time);
             } else {
                 //Debug::text('&nbsp;&nbsp;NOT active shift on this day... ID: '. $this->getColumn('id') .' User ID: '. $this->getColumn('user_id') .' Start Time: '. TTDate::getDate('DATE+TIME', $i),__FILE__, __LINE__, __METHOD__, 10);
             }
         }
     }
     if (isset($shifts)) {
         //Debug::Arr($shifts, 'Template Shifts: ',__FILE__, __LINE__, __METHOD__, 10);
         return $shifts;
     }
     return FALSE;
 }