计算两个日期之间的工作时间
我需要一种基于8小时工作日计算两个日期之间工作时间的PHP方法,不包括周末和银行假期。计算两个日期之间的工作时间
例如,在工作时间和2012-01-01T08:30:00
2012-01-05T10:30:00
之间的差异实际上是26的工作时间,因为前两天是周末/银行假日刚刚离开3个工作日和2小时即3*8+2=26
时间differnce。
我已经使用@flamingLogos excellent answer to a previous question但无法让它考虑到时间和日期。
也许你可以使用此功能:
function work_hours_diff($date1,$date2) {
if ($date1>$date2) { $tmp=$date1; $date1=$date2; $date2=$tmp; unset($tmp); $sign=-1; } else $sign = 1;
if ($date1==$date2) return 0;
$days = 0;
$working_days = array(1,2,3,4,5); // Monday-->Friday
$working_hours = array(8.5, 17.5); // from 8:30(am) to 17:30
$current_date = $date1;
$beg_h = floor($working_hours[0]); $beg_m = ($working_hours[0]*60)%60;
$end_h = floor($working_hours[1]); $end_m = ($working_hours[1]*60)%60;
// setup the very next first working timestamp
if (!in_array(date('w',$current_date) , $working_days)) {
// the current day is not a working day
// the current timestamp is set at the begining of the working day
$current_date = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date));
// search for the next working day
while (!in_array(date('w',$current_date) , $working_days)) {
$current_date += 24*3600; // next day
}
} else {
// check if the current timestamp is inside working hours
$date0 = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date));
// it's before working hours, let's update it
if ($current_date<$date0) $current_date = $date0;
$date3 = mktime($end_h, $end_m, 59, date('n',$current_date), date('j',$current_date), date('Y',$current_date));
if ($date3<$current_date) {
// outch ! it's after working hours, let's find the next working day
$current_date += 24*3600; // the day after
// and set timestamp as the begining of the working day
$current_date = mktime($beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date));
while (!in_array(date('w',$current_date) , $working_days)) {
$current_date += 24*3600; // next day
}
}
}
// so, $current_date is now the first working timestamp available...
// calculate the number of seconds from current timestamp to the end of the working day
$date0 = mktime($end_h, $end_m, 59, date('n',$current_date), date('j',$current_date), date('Y',$current_date));
$seconds = $date0-$current_date+1;
printf("\nFrom %s To %s : %d hours\n",date('d/m/y H:i',$date1),date('d/m/y H:i',$date0),$seconds/3600);
// calculate the number of days from the current day to the end day
$date3 = mktime($beg_h, $beg_m, 0, date('n',$date2), date('j',$date2), date('Y',$date2));
while ($current_date < $date3) {
$current_date += 24*3600; // next day
if (in_array(date('w',$current_date) , $working_days)) $days++; // it's a working day
}
if ($days>0) $days--; //because we've allready count the first day (in $seconds)
printf("\nFrom %s To %s : %d working days\n",date('d/m/y H:i',$date1),date('d/m/y H:i',$date3),$days);
// check if end's timestamp is inside working hours
$date0 = mktime($beg_h, 0, 0, date('n',$date2), date('j',$date2), date('Y',$date2));
if ($date2<$date0) {
// it's before, so nothing more !
} else {
// is it after ?
$date3 = mktime($end_h, $end_m, 59, date('n',$date2), date('j',$date2), date('Y',$date2));
if ($date2>$date3) $date2=$date3;
// calculate the number of seconds from current timestamp to the final timestamp
$tmp = $date2-$date0+1;
$seconds += $tmp;
printf("\nFrom %s To %s : %d hours\n",date('d/m/y H:i',$date2),date('d/m/y H:i',$date3),$tmp/3600);
}
// calculate the working days in seconds
$seconds += 3600*($working_hours[1]-$working_hours[0])*$days;
printf("\nFrom %s To %s : %d hours\n",date('d/m/y H:i',$date1),date('d/m/y H:i',$date2),$seconds/3600);
return $sign * $seconds/3600; // to get hours
}
我放的printf()来显示它的完成(你可以删除它们)
你把它叫做这样的:
date_default_timezone_set("America/Los_Angeles");
$dt2 = strtotime("2012-01-01 05:25:00");
$dt1 = strtotime("2012-01-19 12:40:00");
echo work_hours_diff($dt1 , $dt2);
下面的函数计算两个日期之间的工作时间,以“2013-11-27 13:40”之类的文本格式提供,工作日从9日到17日(可更改)。
function get_working_hours($from,$to)
{
// timestamps
$from_timestamp = strtotime($from);
$to_timestamp = strtotime($to);
// work day seconds
$workday_start_hour = 9;
$workday_end_hour = 17;
$workday_seconds = ($workday_end_hour - $workday_start_hour)*3600;
// work days beetwen dates, minus 1 day
$from_date = date('Y-m-d',$from_timestamp);
$to_date = date('Y-m-d',$to_timestamp);
$workdays_number = count(get_workdays($from_date,$to_date))-1;
$workdays_number = $workdays_number<0 ? 0 : $workdays_number;
// start and end time
$start_time_in_seconds = date("H",$from_timestamp)*3600+date("i",$from_timestamp)*60;
$end_time_in_seconds = date("H",$to_timestamp)*3600+date("i",$to_timestamp)*60;
// final calculations
$working_hours = ($workdays_number * $workday_seconds + $end_time_in_seconds - $start_time_in_seconds)/86400 * 24;
return $working_hours;
}
还有两个附加功能。其中一个返回工作日内阵列...
function get_workdays($from,$to)
{
// arrays
$days_array = array();
$skipdays = array("Saturday", "Sunday");
$skipdates = get_holidays();
// other variables
$i = 0;
$current = $from;
if($current == $to) // same dates
{
$timestamp = strtotime($from);
if (!in_array(date("l", $timestamp), $skipdays)&&!in_array(date("Y-m-d", $timestamp), $skipdates)) {
$days_array[] = date("Y-m-d",$timestamp);
}
}
elseif($current < $to) // different dates
{
while ($current < $to) {
$timestamp = strtotime($from." +".$i." day");
if (!in_array(date("l", $timestamp), $skipdays)&&!in_array(date("Y-m-d", $timestamp), $skipdates)) {
$days_array[] = date("Y-m-d",$timestamp);
}
$current = date("Y-m-d",$timestamp);
$i++;
}
}
return $days_array;
}
和第二 - 返回假期阵列
function get_holidays()
{
// arrays
$days_array = array();
// You have to put there your source of holidays and make them as array...
// For example, database in Codeigniter:
// $days_array = $this->my_model->get_holidays_array();
return $days_array;
}
优秀的优秀代码,hajlabajla! 但有一点奇怪,如果有一个优雅的方式使用半天(0900-1300)为周六 – Roy 2014-11-06 14:05:08
,如果你选择在非工作日或时间开始或结束的其他两项建议不工作。这是我的代码在9:00到20:00的工作日以及周六和周日的休息日获得的结果。
get_working_hours('2016-10-08 08:00:00', '2016-10-08 21:00:00'); //Saturday: 0 hrs
get_working_hours('2016-10-10 08:00:00', '2016-10-10 21:00:00'); //Monday: 11 hrs
get_working_hours('2016-10-10 10:00:00', '2016-10-10 19:00:00'); //Monday: 9 hrs
get_working_hours('2016-10-07 19:00:00', '2016-10-10 10:00:00'); //fri-mon: 2 hrs
get_working_hours('2016-10-08 19:00:00', '2016-10-10 10:00:00'); //sat-mon: 1 hrs
get_working_hours('2016-10-07 19:00:00', '2016-10-09 10:00:00'); //fri-sun: 1 hrs
function get_working_hours($ini_str,$end_str){
//config
$ini_time = [9,0]; //hr, min
$end_time = [20,0]; //hr, min
//date objects
$ini = date_create($ini_str);
$ini_wk = date_time_set(date_create($ini_str),$ini_time[0],$ini_time[1]);
$end = date_create($end_str);
$end_wk = date_time_set(date_create($end_str),$end_time[0],$end_time[1]);
//days
$workdays_arr = get_workdays($ini,$end);
$workdays_count = count($workdays_arr);
$workday_seconds = (($end_time[0] * 60 + $end_time[1]) - ($ini_time[0] * 60 + $ini_time[1])) * 60;
//get time difference
$ini_seconds = 0;
$end_seconds = 0;
if(in_array($ini->format('Y-m-d'),$workdays_arr)) $ini_seconds = $ini->format('U') - $ini_wk->format('U');
if(in_array($end->format('Y-m-d'),$workdays_arr)) $end_seconds = $end_wk->format('U') - $end->format('U');
$seconds_dif = $ini_seconds > 0 ? $ini_seconds : 0;
if($end_seconds > 0) $seconds_dif += $end_seconds;
//final calculations
$working_seconds = ($workdays_count * $workday_seconds) - $seconds_dif;
echo $ini_str.' - '.$end_str.'; Working Hours:'.($working_seconds/3600).b();
return $working_seconds/3600; //return hrs
}
function get_workdays($ini,$end){
//config
$skipdays = [6,0]; //saturday:6; sunday:0
$skipdates = []; //eg: ['2016-10-10'];
//vars
$current = clone $ini;
$current_disp = $current->format('Y-m-d');
$end_disp = $end->format('Y-m-d');
$days_arr = [];
//days range
while($current_disp <= $end_disp){
if(!in_array($current->format('w'),$skipdays) && !in_array($current_disp,$skipdates)){
$days_arr[] = $current_disp;
}
$current->add(new DateInterval('P1D')); //adds one day
$current_disp = $current->format('Y-m-d');
}
return $days_arr;
}
8小时工作日什么时间开始和结束? – 2012-01-18 17:40:06
工作日是8.30-5.30。 – user1156756 2012-01-19 08:44:32