// The ttTimeHelper is a class to help with time-related values.
class ttTimeHelper {
+ // isWeekend determines if $date falls on weekend.
+ static function isWeekend($date) {
+ $weekDay = date('w', strtotime($date));
+ return ($weekDay == WEEKEND_START_DAY || $weekDay == (WEEKEND_START_DAY + 1) % 7);
+ }
+
+ // isHoliday determines if $date falls on a holiday.
+ static function isHoliday($date) {
+ global $i18n;
+ // $date is expected as string in DB_DATEFORMAT.
+ $month = date('m', strtotime($date));
+ $day = date('d', strtotime($date));
+ if (in_array($month.'/'.$day, $i18n->holidays))
+ return true;
+
+ return false;
+ }
+
// isValidTime validates a value as a time string.
static function isValidTime($value) {
if (strlen($value)==0 || !isset($value)) return false;
return $row['quota'];
// If we did not find a record, return a calculated monthly quota.
- $holidaysWithYear = array();
- foreach ($this->holidays as $day) {
- $parts = explode("/", $day);
- $holiday = "$year-$parts[0]-$parts[1]";
- array_push($holidaysWithYear, $holiday);
- }
-
- $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year);
- return $this->getWorkingDays("$year-$month-01", "$year-$month-$daysInMonth", $holidaysWithYear) * $this->getWorkdayHours();
+ $numWorkdays = $this->getNumWorkdays($month, $year);
+ return $numWorkdays * $this->getWorkdayHours();
}
// getMany - returns an array of quotas for a given year for team.
return $result;
}
- // The function returns the number of business days between two dates skipping holidays.
- private function getWorkingDays($startDate, $endDate, $holidays) {
- // TODO: this function needs a fix, as it assumes Sat + Sun weekends,
- // and will not work properly for other week types (ex. Arabic weeks).
-
- // do strtotime calculations just once
- $endDate = strtotime($endDate);
- $startDate = strtotime($startDate);
-
- //The total number of days between the two dates. We compute the no. of seconds and divide it to 60*60*24
- //We add one to inlude both dates in the interval.
- $days = ($endDate - $startDate) / 86400 + 1;
+ // getNumWorkdays returns a number of work days in a given month.
+ private function getNumWorkdays($month, $year) {
- $noOfFullWeeks = floor($days / 7);
- $noOfRemainingDays = fmod($days, 7);
+ $daysInMonth = cal_days_in_month(CAL_GREGORIAN, $month, $year); // Number of calendar days in month.
- //It will return 1 if it's Monday,.. ,7 for Sunday
- $firstDayofWeek = date("N", $startDate);
- $lastDayofWeek = date("N", $endDate);
-
- //---->The two can be equal in leap years when february has 29 days, the equal sign is added here
- //In the first case the whole interval is within a week, in the second case the interval falls in two weeks.
- if ($firstDayofWeek <= $lastDayofWeek) {
- if ($firstDayofWeek <= 6 && 6 <= $lastDayofWeek) {
- $noOfRemainingDays--;
- }
-
- if ($firstDayofWeek <= 7 && 7 <= $lastDayofWeek) {
- $noOfRemainingDays--;
- }
+ $workdaysInMonth = 0;
+ // Iterate through all.
+ for ($i = 1; $i <= $daysInMonth; $i++) {
+ $date = "$year-$month-$i";
+ if (!ttTimeHelper::isWeekend($date) && !ttTimeHelper::isHoliday($date)) {
+ $workdaysInMonth++;
}
- else {
- // (edit by Tokes to fix an edge case where the start day was a Sunday
- // and the end day was NOT a Saturday)
-
- // the day of the week for start is later than the day of the week for end
- if ($firstDayofWeek == 7) {
- // if the start date is a Sunday, then we definitely subtract 1 day
- $noOfRemainingDays--;
-
- if ($lastDayofWeek == 6) {
- // if the end date is a Saturday, then we subtract another day
- $noOfRemainingDays--;
- }
- }
- else {
- // the start date was a Saturday (or earlier), and the end date was (Mon..Fri)
- // so we skip an entire weekend and subtract 2 days
- $noOfRemainingDays -= 2;
- }
- }
-
- //T he no. of business days is: (number of weeks between the two dates) * (5 working days) + the remainder
- // ---->february in none leap years gave a remainder of 0 but still calculated weekends between first and last day, this is one way to fix it
- $workingDays = $noOfFullWeeks * 5;
- if ($noOfRemainingDays > 0 ) {
- $workingDays += $noOfRemainingDays;
- }
-
- // We subtract the holidays
- foreach($holidays as $holiday){
- $timeStamp = strtotime($holiday);
- // If the holiday doesn't fall in weekend
- // TODO: add handling for countries where they move non working day to first working day if holiday is on weekends
- if ($startDate <= $timeStamp && $timeStamp <= $endDate && date("N", $timeStamp) != 6 && date("N", $timeStamp ) != 7)
- $workingDays--;
- }
-
- return $workingDays;
+ }
+ return $workdaysInMonth;
}
}