【问题标题】:Get the number of weeks in a month and the corresponding days获取一个月的周数和对应的天数
【发布时间】:2014-10-01 16:41:19
【问题描述】:

我很确定我过于复杂了,但 atm 我不知道如何以另一种方式做到这一点。

我想创建一个数组,其中包含一个月中的星期数作为键,本周的天数作为值。

我正在使用这个函数来获取一周中的所有天数:

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 周的时间,所以我无法保存月份重叠的日子。

我在这里完全错了吗?解决此任务的可能方法是什么?

【问题讨论】:

    标签: php laravel laravel-4 php-carbon


    【解决方案1】:

    我的朋友,我感到你很痛苦,处理日历数据很烦人。这是我不久前编写的一个函数,它构建了一个以月分隔的周数和天数数组。这不是最干净的代码,但它可以工作。

    它将从您以“Ymd”(或默认为当前日期)传入$today 的日期开始,然后返回到当月的第一周,从那里开始,然后前进到@987654322 @months 构建一个数组,先按月索引,然后按周索引。

    这里有点难以解释,但它是独立的,因此您可以将其复制/粘贴到您的代码中,然后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,
        );
    
    }
    

    我希望这至少可以帮助您入门!

    【讨论】:

    • 对不起,我的回答迟了。该代码对我帮助很大。不仅是为了将代码实现到我的项目中,也是为了更好地理解日期格式的怪异和令人困惑的世界:D 谢谢!
    • 我会...但为此我需要 4 个以上的声望点。
    • 关于如何排除周末的任何指示? (周六和周日)
    • @AmirAsyraf 在 while 循环中,您可以添加一个计数器 $weekdays 并使用 dayOfWeek() 属性来检查星期六/星期日并跳过递增该计数器,因为该示例有效地循环了所有天。有关类似示例,请参阅我检查 Carbon::SATURDAY 以增加 $week 计数器的行。
    【解决方案2】:

    这样的?

    function weekOfMonth($date) {
    
        $firstOfMonth = strtotime(date("Y-m-01", $date));
        $lastWeekNumber = (int)date("W", $date);
        $firstWeekNumber = (int)date("W", $firstOfMonth);
        if (12 === (int)date("m", $date)) {
            if (1 == $lastWeekNumber) {
                $lastWeekNumber = (int)date("W", ($date - (7*24*60*60))) + 1;
            }
        } elseif (1 === (int)date("m", $date) and 1 < $firstWeekNumber) {
            $firstWeekNumber = 0;
        }
        return $lastWeekNumber - $firstWeekNumber + 1;
    }
    
    function weeks($month, $year){
        $lastday = date("t", mktime(0, 0, 0, $month, 1, $year));
        return weekOfMonth(strtotime($year.'-'.$month.'-'.$lastday));
    }
    
    $result = [];
    
    for ($year = 2017; $year < 2020; $year++){
        for ($month = 1; $month < 13; $month++) {
            $numOfWeeks = weeks($month, $year);
            $result[$year][$month]['numOfWeeks'] = $numOfWeeks;
            $daysInFirstWeek = 8 - date('N', strtotime($year.'-'.$month.'-01'));
            $result[$year][$month]['daysPerWeek']['week_1'] = $daysInFirstWeek;
            $startDay = date('d', strtotime('next Monday', strtotime($year.'-'.$month.'-01')));
            for ($i = 1; $i < ($numOfWeeks - 1); $i++) {
                $startDay += 7;
                $result[$year][$month]['daysPerWeek']['week_'.($i+1)] = 7;
            }
    
            //last week
            $result[$year][$month]['daysPerWeek']['week_'.($i+1)] = date('t', strtotime($year.'-'.$month.'-01')) - $startDay + 1;
        }
    }
    
    echo json_encode($result)."\n";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-03
      • 2011-10-19
      相关资源
      最近更新 更多