2017-12-05 5 views
-1

巨大な日付の間の就業日を計算する必要があります。したがって、私はそれがすぐに休暇のない就業日を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; 
    } 

は今、これは私が平日の計算に使用する機能です。それを行うより効率的な方法はありますか?それをキャッシュする唯一のオプションですか?

+1

実際にこのコードに_problem_はありますか?それとも期待どおりに働いていますか?あなたのコードは動作していますが、それを改善しようとしているなら、SOは聞く場所ではありません。 [コードレビュー](https://codereview.stackexchange.com/)には、このような質問があります。 – icecub

+0

コードは一般的に働いていますが、私はレビューのための余分な場所があることを知らなかった。私は間違ったフォーラムに投稿して申し訳ありません=( – user3665396

+0

これは良いm8です。私はここであなたの質問をd​​ownvotedものではなかった。私は単に正しい方向にあなたを指摘:)あなたが必要なものを見つけることを願っています。 – icecub

答えて

0

私はあなたがこれを行うにはflorianv /ビジネス作曲ライブラリを使用することを示唆している:

https://github.com/florianv/business

ドキュメントが良好であり、それは私が自分で出ている何よりも速く実行されます。

パラメータ(一日、休日の営業時間)を定義したら、「タイムライン」機能を使用して、ビジネスの2つの日付の間の日数を決定します。

+0

タンクをチェックします。 – user3665396

関連する問題