Find weekly periods (starting on a Monday) for a month

前端 未结 3 1374
南方客
南方客 2020-12-09 14:13

I\'m trying to find the weekly periods for a given month and year. Dates should start on a Monday and end on a Sunday. If the 1st of the month is a Sunday (Ex May 2011), it

相关标签:
3条回答
  • 2020-12-09 14:50

    If you need all weeks for selected month, and all dates for selected week, then this is all you need:

    function getWeekDays($month, $year)
    {
        $p = new DatePeriod(
            DateTime::createFromFormat('!Y-n-d', "$year-$month-01"),
            new DateInterval('P1D'),
            DateTime::createFromFormat('!Y-n-d', "$year-$month-01")->add(new DateInterval('P1M'))
        );
    
        $datesByWeek = array();
        foreach ($p as $d) {
            $dateByWeek[ $d->format('W') ][] = $d;
        }
        return $dateByWeek;
    }
    

    getWeekDays() function returns multi dimension array. first key is week number. 2 level is array, that has dates saved as DateTime object.

    Fetch example:

    print_r( getWeekDays(5, 2011) ); # May 2011
    print_r( getWeekDays(9, 2012) ); # Sep 2012
    

    I had a little time extra, so I written an example ;-)

    $datesByWeek = getWeekDays(8, 2012);
    $o = '<table border="1">';
    $o.= '<tr><th>Week</th><th>Monday</th><th>Tuesday</th><th>Wednesday</th><th>Thursday</th><th>Friday</th><th>Saturday</th><th>Sunday</th></tr>';
    foreach ($datesByWeek as $week => $dates) {
        $firstD = $dates[0];
        $lastD = $dates[count($dates)-1];
    
        $o.= "<tr>";
        $o.= "<td>" . $firstD->format('M d') . ' - ' . $lastD->format('M d') . "</td>";
        $N = $firstD->format('N');
        for ($i = 1; $i < $N; $i++) {
            $o.= "<td>-</td>";
        }
        foreach ($dates as $d) {
            $o.= "<td>" . $d->format('d.') . " / 0.00</td>";
                # for selected date do you magic
        }
        $N = $lastD->format('N');
        for ($i = $N; $i < 7; $i++) {
            $o.= "<td>-</td>";
        }
        $o.= "</tr>";
    }
    $o.= '</table>';
    echo $o;
    

    Output looks like: enter image description here

    0 讨论(0)
  • 2020-12-09 14:50

    this works perfect!!! phpfiddle here

    <?php
    // start and end must be timestamps !!!!
    $start = 1346976000;  //  Thu 2012-09-06
    $end   = 1348704000;  //  Tue 2012-09-26
    
    // generate the weeks 
    $weeks = generateweeks($start, $end);
    
    // diaplay the weeks
    echo 'From: '.fDate($start).'<br>';
    foreach ($weeks as $week){
       echo fDate($week['start']).' '.fDate($week['end']).'<br>';
    }
    echo 'To: '.fDate($end).'<br>';
    
    /*   outputs this:
    From: Thu 2012-09-06
    Thu 2012-09-06 Sun 2012-09-09
    Mon 2012-09-10 Sun 2012-09-16
    Mon 2012-09-17 Sun 2012-09-23
    Mon 2012-09-24 Wed 2012-09-26
    To: Wed 2012-09-26
    */
    
    
    // $start and $end must be unix timestamps (any range)
    //  returns an array of arrays with 'start' and 'end' elements set 
    //  for each week (or part of week) for the given interval
    //  return values are also in timestamps
    function generateweeks($start,$end){
        $ret = array();
        $start = E2D($start);
        $end = E2D($end);
    
        $ns = nextSunday($start);
    
        while(true){
            if($ns>=$end) {insert($ret,$start,$end);return $ret;}
            insert($ret,$start,$ns);
            $start = $ns +1;
            $ns+=7;
        }
    }
    
    
    
    // helper function to append the array and convert back to unix timestamp
    function insert(&$arr, $start, $end){$arr[] = array('start'=>D2E($start), 'end'=>D2E($end));}
    // recives any date on CD format returns next Sunday on CD format
    function nextSunday($Cdate){return $Cdate + 6  - $Cdate % 7;}
    // recives any date on CD format returns previous Monday on CD format // finaly not used here
    function prevMonday($Cdate){return $Cdate      - $Cdate % 7;}   
    // recives timestamp returns CD
    function E2D($what){return floor($what/86400)+2;}     // floor may be optional in some circunstances
    // recives CD returns timestamp
    function D2E($what){return ($what-2)*86400;}          // 24*60*60
    // just format the timestamp for output, you can adapt it to your needs
    function fDate($what){return date('D Y-m-d',$what);}
    
    0 讨论(0)
  • 2020-12-09 15:09

    The following assumes that the user can pick the month and year for which they wan to run the report (the value posted being 1-12 for month and YYYY for year). There may be a more elegant way to do it, but this seems to work for me. Also, at the top of your post, you say that you want the weeks to be Monday - Sunday. However, your example/screenshot at the bottom shows weeks being Sunday to Saturday. The below is for the originally-stated goal of Monday - Sunday.

    $month = $_POST["month"];
    $year = $_POST["year"];
    
    $endDate = date("t", strtotime($year."-".$month."-01"));
    
    $dayOfWeekOfFirstOfMonth = date("w", strtotime($year."-".$month."-01"));
    $lastDayOfFirstWeek = 8 - $dayOfWeekOfFirstOfMonth;
    
    $weeksArray = array(array("firstDay"=>1, "lastDay"=>$lastDayOfFirstWeek));
    
    $loopDate = $lastDayOfFirstWeek + 1;
    
    while($loopDate < $endDate)
    {
        $weeksArray[] = array("firstDay"=>$loopDate, "lastDay"=>($loopDate+6 > $endDate ? $endDate : $loopDate+6));
        $loopDate+=7;
    }
    
    foreach($weeksArray as $week)
    {
        echo date("M d", strtotime($year."-".$month."-".$week["firstDay"])) . " - " . date("M d", strtotime($year."-".$month."-".$week["lastDay"])) . "\n";
    }
    
    0 讨论(0)
提交回复
热议问题