简体   繁体   English

获取一个月中的星期数以及相应的天数

[英]Get the number of weeks in a month and the corresponding days

I'm pretty sure I'm overcomplicating this but atm I have no clue how to do it in another way. 我很确定我使这个问题复杂化了,但是atm我不知道如何以其他方式来做到这一点。

I want to create an array which contains the number of a week in a month as a key and the days of this week as the value. 我想创建一个数组,其中包含一个月中的一周数作为键,并包含本周的天数作为值。

I'm using this function to get all days of a week: 我正在使用此功能来获取一周中的所有时间:

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;
}

And this function to build the array: 并使用此函数来构建数组:

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;
}

For all months except february I'm getting 5 weeks. 除2月外的所有月份,我都有5周的时间。 For February I'm getting 4 weeks and so I'm not able to save the month-overlapping days. 对于2月,我要花4周的时间,因此无法保存重叠月份。

Am I completely wrong here? 我在这里完全错了吗? What is a possible way to solve this task? 解决此任务的可能方法是什么?

My friend I feel your pain, working with calendar data is annoying. 我的朋友,我感到您很痛苦,使用日历数据很烦人。 Here's a function I wrote a while back that builds an array of weeks and days, separated by months. 这是我不久前写的一个函数,它构建了数周和数天的数组,间隔数月。 It's not the cleanest code but it works. 这不是最干净的代码,但是可以工作。

It will start from the date you pass in $today as "Ymd" (or default to the current date), then work back to the first week of the current month, start there, and then go forward for $scheduleMonths months building an array indexed first by month and then by week. 它将从您$today$today传递“ Ymd”(或默认为当前日期)的日期开始,然后再回到当月的第一周,从那里开始,然后进行$scheduleMonths个月构建一个数组首先按月索引,然后按周索引。

It's a bit hard to explain here, but it's self-contained so you can just copy/paste it into your code and then dd() the output to see what it looks like and if it works for you, and modify it from there. 这里很难解释,但是它是独立的,因此您可以将其复制/粘贴到您的代码中,然后对输出进行dd() ,以查看其外观以及是否对您有用,然后从那里进行修改。 There's some formatting you may need to adjust as it was done that way for my specific use case, but the business logic should be sound. 对于我的特定用例,您可能需要调整某些格式,因为这种方式已经完成,但是业务逻辑应该是合理的。

You should be able to extract the number of weeks in a given month from the output (so if that's all you need you can prob simplify this once you confirm it's working). 您应该能够从输出中提取给定月份中的星期数(因此,如果仅此而已,则可以在确认其正常工作后进行简化)。

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,
    );

}

I hope this helps you at least get started! 我希望这至少可以帮助您入门!

Something like this? 像这样吗

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";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM