This topic is locked

working days

10/30/2007 1:18:57 PM
PHPRunner General questions
M
morpheus author

I have a database that is used for booking holidays off work, basically I need a query that does the following
calculates the number of days between two dates

then removes weekends

displays the result (ie the number of work days used)
on each holiday request there is a a date_from field, date_to field and a working days field, if I can calculate the working days when the records are entered then I can calculate the total remaining days holiday from that value.
regards
Morpheus

Q
quasimidi 10/31/2007

Using custom php code make this possible. It easier to use php than use a trigger/procedure in sql for this.

I have a database that is used for booking holidays off work, basically I need a query that does the following

calculates the number of days between two dates

then removes weekends

displays the result (ie the number of work days used)
on each holiday request there is a a date_from field, date_to field and a working days field, if I can calculate the working days when the records are entered then I can calculate the total remaining days holiday from that value.
regards
Morpheus

J
Jane 10/31/2007

Hi,
to calculate working days field use Before record added or Before record updated event on the Events tab.

You can find some examples in the PHP documentation:

http://php.net/manual/en/ref.datetime.php

srao 4/20/2008

Before record added[/b] or Before record updated event on the Events tab.

You can find some examples in the PHP documentation:

http://php.net/manual/en/ref.datetime.php


Hello,
I have inserted and that takes into account holiday dates.

This was obtained from the great URL you mentioned above : http://php.net/manual/en/ref.datetime.php
Problem: the function returns ZERO days.
Please see the code below which I have inserted in the Before record added or Before record updated [color=#808080]Events as suggested above :

global $data,$startDate,$endDate,$holidays,$conn;
$values['modifiedBy']=$_SESSION["UserID"];
// calculated field is age and CalDays : HERE : age is in years; CalDays is in days

$values["age"] = (strtotime($values["modifiedDate"])-strtotime($values["dob"]))/(60*60*24*365);

$values["CalDays"] = (strtotime($values["endDate"])-strtotime($values["startDate"]))/(60*60*24);
// calculated field is bmi

$values['bmi']= $values["weight"]/($values["height"]*$values["height"]/10000);
// holidays are defined here

$holidays=array("2007-12-25","2008-12-25","2008-12-08","2008-09-30",

"2008-09-11","2008-08-01","2008-05-12","2008-05-01","2008-03-24","2008-03-21","2008-01-01");
/*****************************************************************************/ // START OF FUNCTION getWorkingDays
// Gets the floating point difference in working days between two dates.

// want to calculate workingDays using a function from mariodivece@yahoo.com ( posted at [url="http://ch2.php.net/manual/fr/function.date.php)"]http://ch2.php.net/manual/fr/function.date.php)[/url];

function getWorkingDays($startDate, $endDate, $holidays){

// global $startDate, $endDate, $holidays;
// Calculate weekday number. Monday is 1, Sunday is 7

$firstWeekdayNumber = date("N", strtotime($startDate));

$lastWeekdayNumber = date("N", strtotime($endDate));
// Normalize the dates if they're weekends or holidays as they count for full days (24 hours)

if ($firstWeekdayNumber == 6 || $firstWeekdayNumber == 7 || in_array( date("Y-m-d", strtotime($startDate)), $holidays ))

$startDate = date("Y-m-d 00:00:00", strtotime($startDate));

if ($lastWeekdayNumber == 6 || $lastWeekdayNumber == 7 || in_array( date("Y-m-d", strtotime($endDate)), $holidays ))

$endDate = date("Y-m-d 00:00:00", strtotime("+1 days", strtotime( $endDate )));
// Compute the floating-point differences in the dates

$daysDifference = (strtotime($endDate) - strtotime($startDate)) / 86400;

$fullWeeksDifference = floor($daysDifference / 7);

$remainingDaysDifference = fmod($daysDifference, 7);
// Subtract the weekends; In the first case the whole interval is within a week, in the second case the interval falls in two weeks.

if ($firstWeekdayNumber <= $lastWeekdayNumber){

if ($firstWeekdayNumber <= 6 && 6 <= $lastWeekdayNumber && $remainingDaysDifference >= 1) $remainingDaysDifference--;

if ($firstWeekdayNumber <= 7 && 7 <= $lastWeekdayNumber && $remainingDaysDifference >= 1) $remainingDaysDifference--;

}

else{

if ($firstWeekdayNumber <= 6 && $remainingDaysDifference >= 1) $remainingDaysDifference--;

// In the case when the interval falls in two weeks, there will be a Sunday for sure

$remainingDaysDifference--;

}
// Compute the working days based on full weeks +

$workingDays = $fullWeeksDifference * 5;

if ($remainingDaysDifference > 0 )

$workingDays += $remainingDaysDifference;
// Subtract the holidays

foreach($holidays as $holiday)

{

$holidayTimeStamp=strtotime($holiday);

// If the holiday doesn't fall in weekend

if (strtotime($startDate) <= $holidayTimeStamp && $holidayTimeStamp <= strtotime($endDate) && date("N",$holidayTimeStamp) != 6 && date("N",$holidayTimeStamp) != 7 && $workingDays >= 1)

$workingDays--;

}
// example of how to use the function

//echo getWorkingDays("2006-12-22","2007-01-06",$holidays)

// => will return 8


// End of calculation, return the result now

return $workingDays;



}

/**************************************************************************** END OF FUNCTION */
// RUNNING THE FUNCTION
echo "working days: " . " " .getWorkingDays($startDate,$endDate,$holidays) . " ?";echo "<br/>";
$values["workingDays"] = getWorkingDays($startDate,$endDate,$holidays); // OUTPUT ?
// Inherent phpr data validation

//split into an array (year,month,day,hour,minute,second)

{
//split into an array (year,month,day,hour,minute,second)

$arr = db2time($values["startDate"]);
//convert to datetime

$start = mktime($arr[3],$arr[4],$arr[5],$arr[1],$arr[2],$arr[0]);
//split into an array (year,month,day,hour,minute,second)

$arr = db2time($values["endDate"]);
$end = mktime($arr[3],$arr[4],$arr[5],$arr[1],$arr[2],$arr[0]);
if ($end<$start)

{

echo "Error: endDate CANNOT BE EARLIER THAN startDate";

return false;

}

else {

return true;

}

}
// WHEN DEBUGGING SEK USE THIS:

echo "values passed to the database before UPDATING record : ";echo "<br>";

print "<PRE>";

print_r($values);

print "</PRE>";
return true;


Not very sure that it is a good idea to put the getWorkingDays function within function beforeEdit.

Been working on this for quite a few hours and not getting the right result.

Do you have any hints please ?

srao 5/13/2008

Hello everyone,
Here's the solution, in case it can be of use to <img src='https://asprunner.com/forums/file.php?topicimage=1&fieldname=reply&id=29173&image=1&table=forumreplies' class='bbcemoticon' alt='<<' /> somebody.
[codebox]<?php

global $data,$conn;

global $startDate,$endDate,$holidays;
// 2007-2008 holidays are defined here

$holidays=array("2007-01-01","2007-04-06","2008-04-09",

"2007-05-17","2007-05-28","2007-08-01","2007-09-06","2007-10-12",

"2007-12-20","2007-12-25","2008-01-01","2008-03-21","2008-03-24",

"2008-05-01","2008-05-12","2008-08-01","2008-09-11","2008-09-30",

"2008-12-08","2008-12-25");
/* **START OF FUNCTION getWorkingDays***** /
//The function returns the no. of working days between two dates and it skips the holidays

function getWorkingDays($values,$startDate,$endDate,$holidays)

{

$startDate=$values['startDate'];

$endDate=$values['endDate'];
//The total number of days between the two dates. We compute the no. of seconds and divide it to 60
6024

//We add one to inlude both dates in the interval.

$days = (strtotime($endDate) - strtotime($startDate)) / 86400 + 1;
$no_full_weeks = floor($days / 7);

$no_remaining_days = fmod($days, 7);
//It will return 1 if it's Monday,.. ,7 for Sunday

$the_first_day_of_week = date("N",strtotime($startDate));

$the_last_day_of_week = date("N",strtotime($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 ($the_first_day_of_week <= $the_last_day_of_week){

if ($the_first_day_of_week <= 6 && 6 <= $the_last_day_of_week)

$no_remaining_days--;

if ($the_first_day_of_week <= 7 && 7 <= $the_last_day_of_week)

$no_remaining_days--;

}

else{

if ($the_first_day_of_week <= 6)

$no_remaining_days--;

//In the case when the interval falls in two weeks, there will be a Sunday for sure

$no_remaining_days--;

}
//The no. of working 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 = $no_full_weeks 5;

if ($no_remaining_days > 0 )

{

$workingDays += $no_remaining_days;

}
//We subtract the holidays

foreach($holidays as $holiday){

$time_stamp=strtotime($holiday);

//If the holiday doesn't fall in weekend

if (strtotime($startDate) <= $time_stamp && $time_stamp <= strtotime($endDate)

&& date("N",$time_stamp) != 6 && date("N",$time_stamp) != 7)

$workingDays--;

}
return $workingDays;

}

/
*
END OF FUNCTION** */
// RUNNING THE FUNCTION : OUTPUT !

$values['workingDays'] = getWorkingDays($values,$startDate,$endDate,$holidays);
?>[/codebox]
my credit <img src='https://asprunner.com/forums/file.php?topicimage=1&fieldname=reply&id=29173&image=2&table=forumreplies' class='bbc_emoticon' alt=':rolleyes:' /> goes to Marius : http://ch2.php.net/manual/en/function.date.php#72952