0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【PHP】月初~月末の日付配列と休祝日【Laravel10】

Posted at

日付ごとの配列を作りたい

 日付ごとにデータを格納してViewに渡し、View側で日付ごとの表でデータを表示する、というパターンがよくある。そのために日付ごとの配列を生成して返すメソッドの配列パターンまとめ。Carbonを使うのでLaravelで使うことを想定。

よく書き忘れる
use Carbon\Carbon;
変数の初期化
$year = Carbon::now()->year;
$month = Carbon::now()->month;

1次元配列

1次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
    $start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
    $end_day = $start_day->copy()->endOfMonth();
    $dateArray = [];
    for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
        $dateArray[$current_day->format('Y-m-d')] = $current_day;
    }
    return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定

// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate];

2次元配列

2次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
    $start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
    $end_day = $start_day->copy()->endOfMonth();
    $dateArray = [];
    for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
        $dateArray[$current_day->format('Y-m-d')] = [
            // $current_dayは文字列になるのでCarbonを入れとくと便利
            'carbonDate' => $current_day,
//          'other_key' => $value,
        ];
    }
    return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定

// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate]['carbonDate'];

3次元配列

3次元配列の場合
public function generateDaysOfMonthArray($year, $month) {
    $start_day = Carbon::createFromDate($year, $month, 1)->startOfMonth();
    $end_day = $start_day->copy()->endOfMonth();
    $dateArray = [];
    for ($current_day = $start_day; $current_day <= $end_day; $current_day->addDay()) {
        $dateArray[$current_day->format('Y-m-d')] = [
            'carbon_date_time' => [
                'carbonDate' => $current_day,
//              'key1' => $value1,
//              'key2' => $value2,
            ],
//            'other_key' => [
//                'key3' => $value3,
//                'key4' => $value4,
            ],
        ];
    }
    return $dateArray;
}
$targetDate = '2023-11-15'; // 例として、取り出したい日付を指定

// $targetDateに対応する$current_dayを取り出す
$specificCurrentDay = $dateArray[$targetDate]['carbon_date_time']['carbonDate'];

Controllerで使う

 たとえば2次元配列をコントローラーで使う。

public function showDataPage(Request $request) {
// $yearと$monthは定義するなり$requestで受け取るなりする。

    $dateArray = generateDaysOfMonthArray($year, $month);

    foreach($dateArray as $date => $dataForDate) {
        $dataArray['key1'] = [
            // なんか定義する
        ];
    }

    return view('data_page', compact('dataArray'));
}

Viewで使う

<table>
    <thead>
        <tr>
            <th> タイトル </th>
        </tr>
    </thead>
    <tbody>
        @foreach ($dateArray as $date => $dataForDate)
            <tr>
                <td>
                    <span>{{ $dataForDate['key1']['key2'] }}</span>
                </td>
            </tr>
        @endforeach
    </tbody>
</table>

 とこんな感じで各データをループ処理して表示する。

休祝日を定義する

 日付の配列生成時に休祝日のtrue:falseや、判定できる曜日を入れておくと便利。テキスト色の指定はtailwind cssの記述構文です。状況によってメソッドはstaticで定義するのもアリ。$this使ってるので書き直さないとstaticにはできません。

 春分の日秋分の日天皇誕生日は日付が変わる可能性があるので、別に仕組みを実装する必要がある。なんかのAPI使うか、毎年定義をコードで追記するかDBテーブルを作って日付を登録するかして読み込む。

class Holiday extends Model {  // DBに登録するならモデルとして実装
    use HasFactory;
    protected $fillable = ['date', 'column1', 'column2', 'column3'];
    // その他リレーションとか必要な記述

    // 'YYYY-MM-DD'の日付を渡すと休祝日を判定するメソッド
    // 休祝日ならtrue、それ以外はfalseを返す
    public function isHoliday($carbonDate)
    {
        $carbonDate = Carbon::parse($carbonDate);

        // DBに休日が登録されている場合
        $holidayRecords = Holiday::where('date', $carbonDate->format('Y-m-d'))->exists();
        if ($holidayRecords) {
            return true;
        }
        
        // 日曜日
        if ($carbonDate->dayOfWeek == Carbon::SUNDAY) {
            return true;
        }

        // 年によって変わる休日の設定
        $yearUniequeHolidays = [
            // Carbon::parse('2023-1-9')->toDateString(),      // 2023_成人の日(1月第2月曜日)
            Carbon::parse('2023-2-23')->toDateString(),     // 2023_天皇誕生日(2018までは12-23)
            Carbon::parse('2023-3-21')->toDateString(),     // 2023_春分の日
            // Carbon::parse('2023-7-17')->toDateString(),     // 2023_海の日(7月第3月曜日)
            // Carbon::parse('2023-9-18')->toDateString(),     // 2023_敬老の日(9月第3月曜日)
            Carbon::parse('2023-9-23')->toDateString(),     // 2023_秋分の日
            // Carbon::parse('2023-10-9')->toDateString(),     // 2023_スポーツの日(10月第2月曜日)
        ];

        // 年によって変わる休日(設定済み)の判定
        if (in_array($carbonDate->toDateString(), $yearUniequeHolidays)) {
            return true;
        }

        // 年によって変わるが定義が存在する休日の判定
        if ($this->isSpecialMonday($carbonDate)) {
            return true;
        }

        // 年によって変わらない休日の設定
        $yearlyHolidays = [
            Carbon::create($carbonDate->year, 1, 1)->format('m-d'),    // 元日
            Carbon::create($carbonDate->year, 1, 2)->format('m-d'),    // 元日
            Carbon::create($carbonDate->year, 1, 3)->format('m-d'),    // 元日
            Carbon::create($carbonDate->year, 2, 11)->format('m-d'),   // 建国記念の日
            Carbon::create($carbonDate->year, 4, 29)->format('m-d'),   // 昭和の日(1989年から2006年までは"みどりの日")
            Carbon::create($carbonDate->year, 5, 3)->format('m-d'),    // 憲法記念日
            Carbon::create($carbonDate->year, 5, 4)->format('m-d'),    // みどりの日(2006年までは"国民の休日")
            Carbon::create($carbonDate->year, 5, 5)->format('m-d'),    // こどもの日
            Carbon::create($carbonDate->year, 8, 11)->format('m-d'),   // 山の日 (2016年に新設、特に山の意味はないらしい)
            Carbon::create($carbonDate->year, 11, 3)->format('m-d'),   // 文化の日
            Carbon::create($carbonDate->year, 11, 23)->format('m-d'),  // 勤労感謝の日
            Carbon::create($carbonDate->year, 12, 30)->format('m-d'),  // 年末休暇
            Carbon::create($carbonDate->year, 12, 31)->format('m-d'),  // 年末休暇
        ];

        // 年によって変わらない休日の判定
        if (in_array($carbonDate->format('m-d'), $yearlyHolidays)) {
            return true;
        }

        // 振替休日の判定
        if ($carbonDate->dayOfWeek == Carbon::MONDAY) {
            $prevDay = $carbonDate->copy()->addDay(-1);
            if (in_array($prevDay->format('m-d'), $yearlyHolidays)) {
                return true;
            }
        }

        // 上記の条件に当てはまらない場合は休日ではないと判定
        return false;
    }

    private function isSpecialMonday($carbonDate)
    {
        // 指定された日が1月の第2月曜日、7月の第3月曜日、9月の第3月曜日、または10月の第2月曜日に該当するかどうかを判定
        return (
            // 1月の第2月曜日
            ($carbonDate->month == 1 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 2) ||
            // 7月の第3月曜日
            ($carbonDate->month == 7 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 3) ||
            // 9月の第3月曜日
            ($carbonDate->month == 9 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 3) ||
            // 10月の第2月曜日
            ($carbonDate->month == 10 && $carbonDate->dayOfWeek == Carbon::MONDAY && $carbonDate->weekOfMonth == 2)
        ) ?? false;
    }
}

 配列を生成する例。

   private function generateDateArray($year, $month)
   {
       $startDate = Carbon::createFromDate($year, $month, 1)->startOfMonth();
       $endDate = $startDate->copy()->endOfMonth();
       $dateArray = [];
       $daysOfWeekInJapanese = ['日', '月', '火', '水', '木', '金', '土'];
       $myHoliday = new Holiday();    // isHolidayをstaticメソッドにする場合この行は不要

       // 日付をキーとした多次元配列を構築
       for ($currentDate = $startDate; $currentDate->lte($endDate); $currentDate->addDay()) {
           $dayOfWeek = $currentDate->dayOfWeek;                            // 曜日を数値で取得
           $holidayFlag = $myHoliday->isHoliday($currentDate);              // 休祝日フラグ
           $textColor = '';                                                 // viewで使うテキストの文字色

           if ($dayOfWeek == 0 || $holidayFlag == true) {
               $textColor = 'text-red-400';    // 休日は赤で表示
           } elseif ($dayOfWeek == 6) {
               $textColor = 'text-cyan-400';   // 土曜日は青で表示
           }

           $dateArray[$currentDate->format('Y-m-d')] = [
               'carbonDate' => Carbon::parse($currentDate),
               'stringDate' => Carbon::parse($currentDate)->format('Y-m-d'),
               'formattedDate' => Carbon::parse($currentDate)->format('Y-m-d (') . $daysOfWeekInJapanese[$dayOfWeek] . ')',
               'holiday_flag' => $holidayFlag,
               'dayOfWeek' => $dayOfWeek,
               'textColor' => $textColor,
           ];
       }

       return $dateArray;
   }

 Viewでのテキスト色指定の例。

<span class="{{ $dataForDate['textColour'] }}">テキスト<span>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?