2017-10-26 9 views
0

私は、労働者のチームが(この場合は16従業員の時間を)毎日仕事することができますどのように多くの時間、開始日を使用して返却日を計算しようとするとどのように多くの総予算の時間土曜日と日曜日をスキップして、プロジェクトに割り当てられています。以下は 作業日の開始日、労働力、および予算時間に基づいて予測日を返すにはどうすればよいですか?

は「(それは予算時間(5000+)

function projectionDate($Date, $Budget_Hours) { 
    if (date('l', $Date->format("Y-m-d")) == 'Saturday' 
     || date('l', $Date->format("Y-m-d")) == 'Sunday') { 
    return projectionDate($Date->add(new DateInterval('P1D'))); 
    } 

    if ($Budget_Hours <= 16) { 
    return $Date->format("Y-m-d"); 
    } else { 
    return projectionDate($Date->add(new DateInterval('P1D')), $Budget_Hours - 16); 
    } 
} 

エコーprojectionDate(新しいDateTimeの過剰な量を使用して、戻りの日付のために実行されません、しかし、これらの時間を計算するための仕事関数であります2017年10月26' 日、 '1000年')
2017年12月27日

+1

は、この場合には適切ではありません。あまりにも多くのメモリを使用しており、再帰呼び出しが多すぎます。 https://stackoverflow.com/questions/336127/calculate-business-daysのような別の方法をお試しください。利用可能なすべてのソリューション、特に休日を考慮したソリューションを検討することを強くお勧めします。 – Dimi

+0

フォーマット指定子 'N'は、日曜日の月曜日〜7日に1を与えます。したがって、' N <6'をチェックするだけで週末はスキップします。必要な勤務時間に達するまで、一度にDateTimeオブジェクトに1日追加するだけで、ループを継続してください。国/祝祭日も考慮したい場合は、始めに簡単にするために、いくつかのウェブサイト(コピー&ペースト)から関連データを取得し、次の2年間の日付を配列を単純な 'yyyy-mm-dd'形式で作成し、in_arrayを使用して同じ形式の現在のループ日付をチェックします。動作してはならない - - – CBroe

答えて

1
function projectionDate($Date, $Budget_Hours, $Workforce_Hours = 8, $Holidays = array()){ 
    $oneDayDateInterval = new DateInterval('P1D'); 
    while($Budget_Hours > $Workforce_Hours || in_array($Date->format('Y-m-d'),$Holidays)){ 
    if($Date->format("N") < 6 && !in_array($Date->format('Y-m-d'), $Holidays)){ 
     $Budget_Hours -= $Workforce_Hours; 
    } 
    $Date = $Date->add($oneDayDateInterval); 
    } 
    return $Date->format("Y-m-d"); 
} 

ここも米国連邦休日を行うための怠惰な方法です。ホーそれは今年だけを処理するため、プロデューサーの日付を後退させます。再帰を使用して

function getHolidaysThisYear($Holidays = array()){ 
    $oneDayDateInterval = new DateInterval('P1D'); 
    $MartinLutherKing = new DateTime(date("Y")."-01-15"); 
    while($MartinLutherKing->format("l") != "Monday"){$MartinLutherKing->add($oneDayDateInterval);} 
    $WashingtonBirthday = new DateTime(date("Y")."-02-15"); 
    while($WashingtonBirthday->format("l") != "Monday"){$WashingtonBirthday->add($oneDayDateInterval);} 
    $MemorialDay = new DateTime(date("Y")."-05-25"); 
    while($MemorialDay->format("l") != "Monday"){$MemorialDay->add($oneDayDateInterval);} 
    $LaborDay = new DateTime(date("Y")."-09-01"); 
    while($LaborDay->format("l") != "Monday"){$LaborDay->add($oneDayDateInterval);} 
    $ColombusDay = new DateTime(date("Y")."-10-08"); 
    while($ColombusDay->format("l") != "Monday"){$ColombusDay->add($oneDayDateInterval);} 
    $ThanksGiving = new DateTime(date("Y")."-11-22"); 
    while($ThanksGiving->format("l") != "Thursday"){$ThanksGiving->add($oneDayDateInterval);} 
    $Holidays = array_merge($Holidays,array(date("Y") . "-01-01",date("Y") . "-06-04",date("Y") . "-11-11",date("Y"). "-12-25",$MartinLutherKing->format("Y-m-d"),$WashingtonBirthday->format("Y-m-d"),$MemorialDay->format("Y-m-d"),$LaborDay->format("Y-m-d"),$ColombusDay->format("Y-m-d"),$ThanksGiving->format("Y-m-d"))); 
    return $Holidays; 
} 
+0

'日付( 'L'、$タのデータ>フォーマット( "Y-M-D")は、) '' date'は、2番目のパラメータとして、UNIXタイムスタンプではなく、' YYYY-MM-dd'文字列値を期待します。 – CBroe

+0

'new DateInterval( 'P1D')' - これはいつでも同じ値になっているので、毎回新しいオブジェクト_を作成する必要はありません。ループの前に '$ oneDayDateInterval = new DateInterval( 'P1D');を初期化し、それを' $ Date-> add'呼び出しの中で使用します。 – CBroe

+0

そして、あなたは同じことをやっています - 日に日を追加する - は、ifとelseブランチの両方で2回続けます。ロジックを反転させます。週末でない場合( '$ Date-> format( 'N')<6')、_then_は営業時間から16時間を引いています。他の支店と_Away_、代わりにそれは私のコードでは、それはしかし動作し、奇妙である無条件日に1日追加し、ループ本体の端 '}' ... $タのデータ>フォーマットについては – CBroe

関連する問題