####やりたいこと
年次有給休暇の発効処理。
入社年月日の6か月後(半年後)の応当日、以後そこからさらに1年後(入社から1年半後)、2年後(入社から2年半後)・・・というように日付を取得したい。
####試したこと
本番環境ではデータベースに登録してある入社年月日から順に取得し、システムにアクセスした日を超えたらループを終了することを想定しています。
日付を正しく取得できるかを確かめるための以下のテストでは、2019-01-01から2019-12-31までの1年間の日付に対して、半年後~10年半後までを生成してみました。
PHP
1<?php 2ini_set( 'display_errors', 1 ); 3 $base_dates = array(); 4 $st = new DateTimeImmutable('2019-01-01'); 5 $date = new DateTime('2019-01-01'); 6 $ed = new DateTimeImmutable('2019-12-31'); 7 $stop = 0; 8 $array = array(); 9 echo "<pre>"; 10 print_r($date); 11 echo "</pre>"; 12// exit; 13 while($stop<1)://一致するまで繰り返す 14 $day = $date->format('Y-m-d'); 15 $hantoshi = new DateTime($day); 16 $hantoshi = $hantoshi->modify('+6 months')->format('Y-m-d'); 17 $y1 = new DateTime($day); 18 $y1 = $y1->modify('+6 months +1 year')->format('Y-m-d'); 19 $y2 = new DateTime($day); 20 $y2 = $y2->modify('+6 months +2 year')->format('Y-m-d'); 21 $y3 = new DateTime($day); 22 $y3 = $y3->modify('+6 months +3 year')->format('Y-m-d'); 23 $y4 = new DateTime($day); 24 $y4 = $y4->modify('+6 months +4 year')->format('Y-m-d'); 25 $y5 = new DateTime($day); 26 $y5 = $y5->modify('+6 months +5 year')->format('Y-m-d'); 27 $y6 = new DateTime($day); 28 $y6 = $y6->modify('+6 months +6 year')->format('Y-m-d'); 29 $y7 = new DateTime($day); 30 $y7 = $y7->modify('+6 months +7 year')->format('Y-m-d'); 31 $y8 = new DateTime($day); 32 $y8 = $y8->modify('+6 months +8 year')->format('Y-m-d'); 33 $y9 = new DateTime($day); 34 $y9 = $y9->modify('+6 months +9 year')->format('Y-m-d'); 35 $y10 = new DateTime($day); 36 $y10 = $y10->modify('+6 months +10 year')->format('Y-m-d'); 37 $array[$day]['半年後'] = $hantoshi; 38 $array[$day]['1年半後'] = $y1; 39 $array[$day]['2年半後'] = $y2; 40 $array[$day]['3年半後'] = $y3; 41 $array[$day]['4年半後'] = $y4; 42 $array[$day]['5年半後'] = $y5; 43 $array[$day]['6年半後'] = $y6; 44 $array[$day]['7年半後'] = $y7; 45 $array[$day]['8年半後'] = $y8; 46 $array[$day]['9年半後'] = $y9; 47 $array[$day]['10年半後'] = $y10; 48 49 $date = $date->modify('+1 day'); 50 if($date>$ed): 51 ++$stop; 52 endif; 53 endwhile; 54 55 echo "<pre>"; 56 print_r($array); 57 echo "</pre>"; 58 exit; 59?>
これだと結果として月末が31日まである月とそうではない月とで、月末応当日が期待した結果になりません。
例:5/31の半年後は11/30としたいが、12/1になってしまう。
そこで、次のやり方を試みました。
PHP
1<?php 2ini_set( 'display_errors', 1 ); 3 $base_dates = array(); 4 $st = new DateTimeImmutable('2010-01-01'); 5 $date = new DateTime('2010-01-01'); 6 $ed = new DateTimeImmutable('2010-12-31'); 7 $now = new DateTimeImmutable(); 8 $today = $now->format('Y-m-d');//対象日 9 $stop = 0; 10 $array = array(); 11 12 while($stop<1)://一致するまで繰り返す 13 $day = $date->format('Y-m-d'); 14 $d = $date->format('d');//日付のみ抽出 15 $h = new DateTime($day); 16 $h = $h->modify('+6 months'); 17 $h_d = $h->format('d'); 18 if($h_d!=$d)://異なる日が返った 19 $h = $h->modify('last day of last month');//前月の月末日 20 endif; 21 $array[$day]['半年後'] = $h->format('Y-m-d');//半年後の日付。$hは半年後のDateTimeオブジェクト 22 //対象日と一致するか過去の日付群 23 $stop2 = 0; 24 $cnt = 1; 25 while($stop2<1): 26 $h->modify('+1 year');//1年後ろへ 27 if($h>=$now)://超えた 28 ++$stop2; 29 else://超えてない 30 $array[$day][$cnt] = $h->format('Y-m-d'); 31 ++$cnt; 32 endif; 33 endwhile; 34 $date = $date->modify('+1 day'); 35 if($date>$ed): 36 ++$stop; 37 endif; 38 endwhile; 39 40 echo "<pre>"; 41 print_r($array); 42 echo "</pre>"; 43 exit; 44?>
(こちらでは先ほどと違い、2010-01-01~2010-12-31の各日付に対しての、半年後~〇年半後を生成していき、今日の日付に到達したら処理を止めるようにしてあります)
この方法だと、5/31の半年後応当日は意図した通り11/30になっており、概ね良好なのですが、
8/29~8/31が入社日となった場合、平年はこれらは全て各年の2/28が応当日として正解ですが、閏年の場合は2/29を応当日としなければいけません。
入社年月日の月と日を取り出し、月が8でかつ日が29以上で、なおかつ生成した応当日の年が閏年の場合は・・・・と力業で解決する以外に、なにかもっとスマートに応当日を求める方法はないものでしょうか。
回答2件
あなたの回答
tips
プレビュー