我们有一个基于PHP的时间表系统,该系统是在内部开发的,经过多年的发展,但向用户提供的一条信息是每个项目剩余的工作日数。
目前,我只需取当前日期和项目结束日期之间的差值,除以7,乘以5。这在很长一段时间内已经足够了,对于周一至周五全职工作的员工来说也足够准确。然而,我们现在有一些员工每周只工作一天。
时间表系统知道员工的工作日,这些信息存储在用户类中的字符串中,对于全职员工,其值为NNYYYYY
(意思是ssMTWTF
(。
我可以很容易地将两个日期之间的差值除以7,然后乘以它们的工作天数,从而使结果更加准确,但在做出这一改变的同时,我正在考虑产生一种更准确的计算实际价值的方法。
脑海中浮现的最简单的方法是在两个日期之间使用一个循环,将一周中的哪一天与用户的工作模式进行比较,并在用户当天工作的日子的计数器中添加一个。
考虑到由于时间表上的项目数量,这种计算平均每个页面视图必须执行约30次,并且项目一次可以跨越12或18个月(每次页面加载都需要大量循环(,我想知道是否有更有效的PHP方法来实现这一点?
这段代码可能会有所帮助:
<?php
//get current month for example
$beginday = date("Y-m-01");
$lastday = date("Y-m-t");
$nr_work_days = getWorkingDays($beginday, $lastday);
echo $nr_work_days;
function getWorkingDays($startDate, $endDate)
{
$begin = strtotime($startDate);
$end = strtotime($endDate);
if ($begin > $end) {
echo "startdate is in the future! <br />";
return 0;
} else {
$no_days = 0;
$weekends = 0;
while ($begin <= $end) {
$no_days++; // no of days in the given interval
$what_day = date("N", $begin);
if ($what_day > 5) { // 6 and 7 are weekend days
$weekends++;
};
$begin += 86400; // +1 day
};
$working_days = $no_days - $weekends;
return $working_days;
}
}
另一种解决方案可以是:获取两个日期之间的日期范围(不包括周末(
您可以使用以下函数查找工作日数。
在这里你可以看到现场演示。
function number_of_working_days($startDate, $endDate)
{
$workingDays = 0;
$startTimestamp = strtotime($startDate);
$endTimestamp = strtotime($endDate);
for ($i = $startTimestamp; $i <= $endTimestamp; $i = $i + (60 * 60 * 24)) {
if (date("N", $i) <= 5) $workingDays = $workingDays + 1;
}
return $workingDays;
}
如果您想用工作日选项查找两个日期之间的总工作日。那么这将有助于
$startDate = '2016-10-01';
$endDate = '2016-10-31';
$weekdays = array('1','2','3','4','5','6'); //this i think monday-saturday
$begin = new DateTime($startDate);
$end = new DateTime($endDate);
$end = $end->modify( '+1 day' ); //add one day so as to include the end date of our range
$interval = new DateInterval('P1D'); // 1 Day
$dateRange = new DatePeriod($begin, $interval, $end);
$total_days = 0;
//this will calculate total days from monday to saturday in above date range
foreach ($dateRange as $date) {
if (in_array($date->format("N"),$weekdays)) {
$total_days++;
}
}
我尝试了一些解决方案,但它们对我不起作用(给了我包括周末在内的结果(,所以我写了这个解决方案:
function number_of_working_days($from, $to) {
$target = strtotime($from);
$days = 0;
while ($target < strtotime(date("Y-m-d",strtotime($to)))) {
if(date("N",$target) <= 5) $days++;
$target += (60*60*24); /* move forward by 1 day */
}
return $days;
}
其中$from
和$to
是mySQL表中的日期。
function workingDaysBetweenDates(startDate, endDate) {
// Validate input
if (endDate < startDate)
return 0;
// Calculate days between dates
var millisecondsPerDay = 86400 * 1000; // Day in milliseconds
startDate.setHours(0,0,0,1); // Start just after midnight
endDate.setHours(23,59,59,999); // End just before midnight
var diff = endDate - startDate; // Milliseconds between datetime objects
var days = Math.ceil(diff / millisecondsPerDay);
// Subtract two weekend days for every week in between
var weeks = Math.floor(days / 7);
days = days - (weeks * 2);
// Handle special cases
var startDay = startDate.getDay();
var endDay = endDate.getDay();
// Remove weekend not previously removed.
if (startDay - endDay > 1)
days = days - 2;
// Remove start day if span starts on Sunday but ends before Saturday
if (startDay == 0 && endDay != 6) {
days = days - 1;
}
// Remove end day if span ends on Saturday but starts after Sunday
if (endDay == 6 && startDay != 0) {
days = days - 1;
}
return days;
}
$('#results').html(workingDaysBetweenDates(new Date('6/03/2019'), new Date('6/17/2019')));
希望这能有所帮助。