2

私はこれを過度に複雑にしていると確信していますが、別の方法でそれを行う方法がわかりません。

月の週数をキー、曜日を値とした配列を作成したいと考えています。

この関数を使用して、すべての曜日を取得しています。

public function getDaysOfWeek($year, $month, $day)
{
    $firstMondayThisWeek = new DateTime($year . '/' . $month . '/' . $day, new DateTimeZone("Europe/Berlin"));
    $firstMondayThisWeek->modify('tomorrow');
    $firstMondayThisWeek->modify('last Monday');

    $nextSevenDays = new DatePeriod(
        $firstMondayThisWeek,
        DateInterval::createFromDateString('+1 day'),
        6
    );

    return $nextSevenDays;
}

そして、配列を構築するこの関数:

public function getWeekAndDays($year, $month)
{
    $weeksInMonth = Carbon::createFromDate($year, $month)->endOfMonth()->weekOfMonth;   
    $weekBegin = Carbon::createFromDate($year, $month)->startOfMonth();

    $weeks = [];

    for($i=1; $i<=$weeksInMonth; $i++)
    {
        $collection = new \stdClass();
        $collection->week = $i;
        $collection->days = $this->getDaysOfWeek($year, $month, $weekBegin->day);

        $weekBegin->addWeek(0);

        $weeks[] = $collection;
    }

    return $weeks;
}

2月を除くすべての月で、私は5週間を取得しています. 2 月は 4 週間あるので、月が重なる日を保存することはできません。

ここで私は完全に間違っていますか?このタスクを解決するために可能な方法は何ですか?

4

2 に答える 2

8

友よ、私はあなたの痛みを感じています。カレンダーデータを操作するのは面倒です。これは、月で区切られた週と日の配列を構築する、私がしばらく前に書いた関数です。これは最もクリーンなコードではありませんが、機能します。

「Ymd」として渡された日付$today(またはデフォルトで現在の日付)から開始し、現在の月の最初の週に戻り、そこから開始して、最初に月ごとに$scheduleMonthsインデックス付けされた配列を構築する月を進めますそして週ごと。

ここで説明するのは少し難しいですが、自己完結型であるため、コードにコピーして貼り付けdd()、出力を確認して、それがどのように機能するかを確認し、そこから変更することができます。私の特定のユースケースではそのように行われたため、調整が必要なフォーマットがいくつかありますが、ビジネスロジックは健全である必要があります。

出力から特定の月の週数を抽出できるはずです (それが必要な場合は、機能していることを確認したら、これを単純化できます)。

public function getWeeks($today = null, $scheduleMonths = 6) {

    $today = !is_null($today) ? Carbon::createFromFormat('Y-m-d',$today) : Carbon::now();

    $startDate = Carbon::instance($today)->startOfMonth()->startOfWeek()->subDay(); // start on Sunday
    $endDate = Carbon::instance($startDate)->addMonths($scheduleMonths)->endOfMonth();
    $endDate->addDays(6 - $endDate->dayOfWeek);

    $epoch = Carbon::createFromTimestamp(0);
    $firstDay = $epoch->diffInDays($startDate);
    $lastDay = $epoch->diffInDays($endDate);

    $week=0;
    $monthNum = $today->month;
    $yearNum = $today->year;
    $prevDay = null;
    $theDay = $startDate;
    $prevMonth = $monthNum;

    $data = array();

    while ($firstDay < $lastDay) {

        if (($theDay->dayOfWeek == Carbon::SUNDAY) && (($theDay->month > $monthNum) || ($theDay->month == 1))) $monthNum = $theDay->month;
        if ($prevMonth > $monthNum) $yearNum++;

        $theMonth = Carbon::createFromFormat("Y-m-d",$yearNum."-".$monthNum."-01")->format('F Y');

        if (!array_key_exists($theMonth,$data)) $data[$theMonth] = array();
        if (!array_key_exists($week,$data[$theMonth])) $data[$theMonth][$week] = array(
            'day_range' => '',
        );

        if ($theDay->dayOfWeek == Carbon::SUNDAY) $data[$theMonth][$week]['day_range'] = sprintf("%d-",$theDay->day);
        if ($theDay->dayOfWeek == Carbon::SATURDAY) $data[$theMonth][$week]['day_range'] .= sprintf("%d",$theDay->day);

        $firstDay++;
        if ($theDay->dayOfWeek == Carbon::SATURDAY) $week++;
        $theDay = $theDay->copy()->addDay();
        $prevMonth = $monthNum;
    }

    $totalWeeks = $week;

    return array(
        'startDate' => $startDate,
        'endDate' => $endDate,
        'totalWeeks' => $totalWeeks,
        'schedule' => $data,
    );

}

これが少なくとも始めるのに役立つことを願っています!

于 2014-08-08T16:34:12.430 に答える