巨大な日付の間の就業日を計算する必要があります。したがって、私はそれがすぐに休暇のない就業日をPHPで速く計算する
はすべての休日を設定しない機能を探しています:
public function getArrayOfHolidays($year, $holidays= array(), $format = 'Y-m-d')
{
$special1= new DateTime('2017-10-31');
array_push($holidays, $special1->format($format));
$newyear= new DateTime();
$newyear->modify('1 january ' . $year);
array_push($holidays, $newyear->format($format));
$holyThreeKings= new DateTime();
$holyThreeKings->modify('6 january ' . $year);
array_push($holidays, $holyThreeKings->format($format));
$layborDay= new DateTime();
$layborDay->modify('1 may ' . $year);
array_push($holidays, $layborDay->format($format));
$unityDay= new DateTime();
$unityDay->modify('3 october ' . $year);
array_push($holidays, $unityDay->format($format));
$allSaintsDay= new DateTime();
$allSaintsDay->modify('1 november ' . $year);
array_push($holidays, $allSaintsDay->format($format));
$christmasEve= new DateTime();
$christmasEve->modify('24 december ' . $year);
array_push($holidays, $christmasEve->format($format));
$christmas1 = new DateTime();
$christmas1->modify('25 december ' . $year);
array_push($holidays, $christmas1->format($format));
$christmas2 = new DateTime();
$christmas2->modify('26 december ' . $year);
array_push($holidays, $christmas2->format($format));
$silvester = new DateTime();
$silvester->modify('31 december ' . $year);
array_push($holidays, $silvester->format($format));
$easterSunday= new DateTime(date('Y-m-d', easter_date($year)));
$easterSunday->modify('+1 day');
array_push($holidays, $easterSunday->format($format));
$goodFriday = new DateTime($ostersonntag->format('Y-m-d'));
$goodFriday->modify('last friday');
array_push($holidays, $goodFriday->format($format));
$easterMonday= new DateTime($ostersonntag->format('Y-m-d'));
$easterMonday->modify('next monday');
array_push($holidays, $easterMonday->format($format));
$ascensionOfJesus= new DateTime($ostersonntag->format('Y-m-d'));
$ascensionOfJesus->modify('+39 days');
array_push($holidays, $ascensionOfJesus->format($format));
$pentecostSunday= new DateTime($ostersonntag->format('Y-m-d'));
$pentecostSunday->modify('+49 days');
array_push($holidays, $pentecostSunday->format($format));
$pentecostMonday= new DateTime($ostersonntag->format('Y-m-d'));
$pentecostMonday->modify('+50 days');
array_push($holidays, $pentecostMonday->format($format));
$corpusChristi = new DateTime($pentecostMonday->format('Y-m-d'));
$corpusChristi ->modify('next sunday');
$corpusChristi ->modify('next thursday');
array_push($holidays, $corpusChristi ->format($format));
return $holidays;
}
これが存在する場合、私は、以前のためのすべてのholydaysと来年を持っていることを確認するために3回の最大値を実行します年の間に計算された日付。したがって、それほど大きなインパクトはないはずです。私はまだそれを行うより良い方法があるので、それを見せたいと思っていましたか?私は次のX年をprecalcしてデータベースに保存することができます。多分もっと良いでしょう。今、その関数はウィッヒが20secsほどかかりループでは約40.000回呼び出され
public function getWorkingDays($startDate, $endDate, $holidays)
{
// 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;
$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", $startDate);
$the_last_day_of_week = 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 ($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 {
// (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 ($the_first_day_of_week == 7) {
// if the start date is a Sunday, then we definitely subtract 1 day
$no_remaining_days--;
if ($the_last_day_of_week == 6) {
// if the end date is a Saturday, then we subtract another day
$no_remaining_days--;
}
} 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
$no_remaining_days -= 2;
}
}
//The 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 = $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 ($startDate <= $time_stamp && $time_stamp <= $endDate && date("N", $time_stamp) != 6 && date("N", $time_stamp) != 7)
$workingDays--;
}
return $workingDays;
}
:
は今、これは私が平日の計算に使用する機能です。それを行うより効率的な方法はありますか?それをキャッシュする唯一のオプションですか?
実際にこのコードに_problem_はありますか?それとも期待どおりに働いていますか?あなたのコードは動作していますが、それを改善しようとしているなら、SOは聞く場所ではありません。 [コードレビュー](https://codereview.stackexchange.com/)には、このような質問があります。 – icecub
コードは一般的に働いていますが、私はレビューのための余分な場所があることを知らなかった。私は間違ったフォーラムに投稿して申し訳ありません=( – user3665396
これは良いm8です。私はここであなたの質問をdownvotedものではなかった。私は単に正しい方向にあなたを指摘:)あなたが必要なものを見つけることを願っています。 – icecub