30Answers
  • 15
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

name Punditsdkoslkdosdkoskdo

PHP get number of week for month

So I have a script that returns the number of weeks in a particular month and year. How can I take a specific day from that month and determine if it is part of week 1,2,3,4 or 5 of that month?

The most frustrating thing I have ever tried to get working - but here it is!

<?php

    /**
     * Returns the amount of weeks into the month a date is
     * @param $date a YYYY-MM-DD formatted date
     * @param $rollover The day on which the week rolls over
     */
    function getWeeks($date, $rollover)
    {
        $cut = substr($date, 0, 8);
        $daylen = 86400;

        $timestamp = strtotime($date);
        $first = strtotime($cut . "00");
        $elapsed = ($timestamp - $first) / $daylen;

        $weeks = 1;

        for ($i = 1; $i <= $elapsed; $i++)
        {
            $dayfind = $cut . (strlen($i) < 2 ? '0' . $i : $i);
            $daytimestamp = strtotime($dayfind);

            $day = strtolower(date("l", $daytimestamp));

            if($day == strtolower($rollover))  $weeks ++;
        }

        return $weeks;
    }


    //
    echo getWeeks("2011-06-11", "sunday"); //outputs 2, for the second week of the month
?>
  • 46
Reply Report
    • WOW, Works almost perfect. I just see one issue. When I change the rollover to Saturday, it marks April 30th as the sixth week but the 29th the 5th even though they are the same weeks. The 30th is the rollover day. If I change the rollover to Sunday it does some thing similar in May for the first day. Counts May 1st as the second week instead of the first week.
      • 2
    • Hmmmm.. Damn, so close. Maybe if you added a small if statement to see if the rollover day is the first day of the month or not? I'm stumped.
      • 2
    • That's exactly what I thought. I'm going to determine if the rollover is the first day or last day and make an adjustment there. I think it should work off of that.
      • 2
    • +1 for the original solution, in addition to Abhilash's fix, I'd like to pay my tribute also by suggesting using date("D") for $day and sanitizing the rollover with substr(strtolower($rollover),0,3) at the start of the function. (So 'Monday', 'mon', 'Monster' would all work as rollover for Monday)

Edit: so much for "single line" - needed variables to avoid recomputation with the conditional. Tossed in a default argument while I was at it.

function weekOfMonth($when = null) {
    if ($when === null) $when = time();
    $week = date('W', $when); // note that ISO weeks start on Monday
    $firstWeekOfMonth = date('W', strtotime(date('Y-m-01', $when)));
    return 1 + ($week < $firstWeekOfMonth ? $week : $week - $firstWeekOfMonth);
}

Please note that weekOfMonth(strtotime('Oct 31, 2011')); will return 6; some rare months have 6 weeks in them, contrary to OP's expectation. January 2017 is another month with 6 ISO weeks - Sunday the 1st falls in the last year's week, since ISO weeks start on Monday.

For starshine531, to return a 0 indexed week of the month, change the return 1 + to return 0 + or return (int).

For Justin Stayton, for weeks starting on Sunday instead of Monday I would use strftime('%U' instead of date('W', as follows:

function weekOfMonth($when = null) {
    if ($when === null) $when = time();
    $week = strftime('%U', $when); // weeks start on Sunday
    $firstWeekOfMonth = strftime('%U', strtotime(date('Y-m-01', $when)));
    return 1 + ($week < $firstWeekOfMonth ? $week : $week - $firstWeekOfMonth);
}

For this version, 2017-04-30 is now in week 6 of April, while 2017-01-31 is now in week 5.

  • 25
Reply Report
      • 2
    • @starshine531 The week in month is indexed starting at 1 instead of 0 - looking at a calendar for December 2015 with that in mind it would appear that 4 is the correct value.
      • 1
    • Keep in mind that W uses Monday as the start of the week, so this won't work if you use Sunday as the start of the week.
      • 1
    • I'd probably use ((int) strftime("%U", $day)) - ((int) strftime("%U", strtotime(date('Y-m-01', $day)))) + 1 then, though I've not tested it extensively.
      • 1
    • @JoshMountain yeah, date("W", strtotime('2017-01-01)) returns 52. I'll have to add a special check for January, since days can fall into the last week of the prior year. Can't use simple modular arithmetic due to "leap weeks" either: en.wikipedia.org/wiki/ISO_week_date. I'll update it in the next few days.
public function getWeeks($timestamp)
{
    $maxday    = date("t",$timestamp);
    $thismonth = getdate($timestamp);
    $timeStamp = mktime(0,0,0,$thismonth['mon'],1,$thismonth['year']);    //Create time stamp of the first day from the give date.
    $startday  = date('w',$timeStamp);    //get first day of the given month
    $day = $thismonth['mday'];
    $weeks = 0;
    $week_num = 0;

    for ($i=0; $i<($maxday+$startday); $i++) {
        if(($i % 7) == 0){
            $weeks++;
        }
        if($day == ($i - $startday + 1)){
            $week_num = $weeks;
        }
      }     
    return $week_num;
}

Hello all i have been struggling for the whole day trying to figure this code out, i finally figured it out so i thought i would share it with you all.

all you need to do is put a time stamp into the function and it will return the week number back to you.

thanks

  • 13
Reply Report

there is a problem with this method. if the passing date (Lets say 2012/01/01 which is a Sunday) and "$rollover" day is "Sunday", then this function will return 2. where its actually is 1'st week. i think i have fixed it in following function. please add comments to make it better.

function getWeeks($date, $rollover)
{
    $cut        = substr($date, 0, 8);
    $daylen     = 86400;
    $timestamp  = strtotime($date);
    $first      = strtotime($cut . "01");   
    $elapsed    = (($timestamp - $first) / $daylen)+1;
    $i          = 1;
    $weeks      = 0;
    for($i==1; $i<=$elapsed; $i++)
    {
        $dayfind        = $cut . (strlen($i) < 2 ? '0' . $i : $i);
        $daytimestamp   = strtotime($dayfind);
        $day            = strtolower(date("l", $daytimestamp));
        if($day == strtolower($rollover))
        {
            $weeks++;  
        }
    } 
    if($weeks==0)
    {
        $weeks++; 
    }
    return $weeks;  
}
  • 6
Reply Report

This is a solution based on sberry's mathematical solution but using the PHP DateTime class instead.

function week_of_month($date) {
    $first_of_month = new DateObject($date->format('Y/m/1'));
    $day_of_first = $first_of_month->format('N');
    $day_of_month = $date->format('j');
    return floor(($day_of_first + $day_of_month - 1) / 7) + 1;
}
  • 5
Reply Report
    • Not sure which version of PHP you're using, but mine has a DateTime class, but not a DateObject class, but changing that was easy. Also, this has to be passed a DateTime object in order to function. This function would be better if it could accept either a DateTime object or a string date.

Just Copy and Past the code and pass month and year.

e.g month=04 year=2013.

That's exactly what You Need.

$mm= $_REQUEST['month'];
$yy= $_REQUEST['year'];
$startdate=date($yy."-".$mm."-01") ;
$current_date=date('Y-m-t');
$ld= cal_days_in_month(CAL_GREGORIAN, $mm, $yy);
$lastday=$yy.'-'.$mm.'-'.$ld;
$start_date = date('Y-m-d', strtotime($startdate));
$end_date = date('Y-m-d', strtotime($lastday));
$end_date1 = date('Y-m-d', strtotime($lastday." + 6 days"));
$count_week=0;
$week_array = array();

for($date = $start_date; $date <= $end_date1; $date = date('Y-m-d', strtotime($date. ' + 7 days')))
{
    $getarray=getWeekDates($date, $start_date, $end_date);
echo "<br>";
$week_array[]=$getarray;
    echo "\n";
$count_week++;

}

// its give the number of week for the given month and year
echo $count_week;
//print_r($week_array);

function getWeekDates($date, $start_date, $end_date)
{
    $week =  date('W', strtotime($date));
    $year =  date('Y', strtotime($date));
    $from = date("Y-m-d", strtotime("{$year}-W{$week}+1"));
    if($from < $start_date) $from = $start_date;

    $to = date("Y-m-d", strtotime("{$year}-W{$week}-6")); 
    if($to > $end_date) $to = $end_date;

$array1 = array(
        "ssdate" => $from,
        "eedate" => $to,
);

return $array1;

   // echo "Start Date-->".$from."End Date -->".$to;
}

for($i=0;$i<$count_week;$i++)
{   
$start= $week_array[$i]['ssdate'];
echo "--";

$week_array[$i]['eedate'];
echo "<br>";
}

OUTPUT:

week( 0 )=>2013-03-01---2013-03-02

week( 1 )=>2013-03-03---2013-03-09

week( 2 )=>2013-03-10---2013-03-16

week( 3 )=>2013-03-17---2013-03-23

week( 4 )=>2013-03-24---2013-03-30

week( 5 )=>2013-03-31---2013-03-31
  • 4
Reply Report

This is the snippet that I made to fulfill my requirements for the same. Hope this will help you.

function getWeek($timestamp) {
 $week_year = date('W',$timestamp);
 $week = 0;//date('d',$timestamp)/7;
 $year = date('Y',$timestamp);
 $month = date('m',$timestamp);
 $day = date('d',$timestamp);
 $prev_month = date('m',$timestamp) -1;
if($month != 1 ){
    $last_day_prev = $year."-".$prev_month."-1";
    $last_day_prev = date('t',strtotime($last_day_prev));
    $week_year_last_mon = date('W',strtotime($year."-".$prev_month."-".$last_day_prev));
    $week_year_first_this = date('W',strtotime($year."-".$month."-1"));
    if($week_year_first_this == $week_year_last_mon){
        $week_diff = 0;
    }
    else{
        $week_diff = 1;
    }
    if($week_year ==1 && $month == 12 ){
    // to handle December's last two days coming in first week of January
        $week_year = 53;
    }
    $week = $week_year-$week_year_last_mon + 1 +$week_diff;
}
else{
 // to handle first three days January coming in last week of December.
    $week_year_first_this = date('W',strtotime($year."-01-1"));
    if($week_year_first_this ==52 || $week_year_first_this ==53){
        if($week_year == 52 || $week_year == 53){
            $week =1;
        }
        else{
            $week = $week_year + 1;
        }
    }
    else{
        $week = $week_year;
    }
}
return $week;

}

  • 3
Reply Report

I think I found an elegant solution

$time = time(); // or whenever
$week_of_the_month = ceil(date('d', $time)/7);
  • 3
Reply Report
      • 2
    • This will only work if you are trying to count 7 day intervals in a month, or if the month happens to start on the same day as the week does.
      • 2
    • This is the solution I was looking for however to be fair it is more about telling what number of any particular week day it is in the month rather than what week it is.

For a Monday-Sunday (ISO 8601) week (or, if you simply don't care), you can do this in one line:

function get_week_of_month($date) {
 return date('W', $date) - date('W', strtotime(date("Y-m-01", $date))) + 1;
}

(Source)

For anything else, (e.g. a Sunday-Saturday week), you just need to tweak $date inside the function:

function get_week_of_month($date) {
 $date += 86400; //For weeks starting on Sunday
 return date('W', $date) - date('W', strtotime(date("Y-m-01", $date))) + 1;
}

(Thanks to these guys/gals)

NOTE: You may run into some issues at the end of the year (e.g. around 12/31, 1/1, etc.). Read more here.

  • 3
Reply Report
      • 1
    • i like this answer because it does the simplistic approach that @liridayn took, plus makes it into a function, and explains how to tweak the week start day

This is probably not a good way to do this but it's my first thought and I'm really tired.

Put all your dates into an array. The date object must have a day name (Monday). Create a method that searches the array and when ever you hit a Sunday you add 1 to a week counter. Once you find the date you're looking for return the week counter. That is the week the day falls in of the year. For the week in the month you have to reset the week counter every time you get to the last day in each month.

  • 2
Reply Report

Thought I'd share my function as well. This returns an array of weeks. Every week is an array with weeks day (0..6) as key and months day (1..31) as value.

Function assumes that week starts with Sunday.

Enjoy!

function get_weeks($year, $month){

    $days_in_month = date("t", mktime(0, 0, 0, $month, 1, $year));
    $weeks_in_month = 1;
    $weeks = array();

    //loop through month
    for ($day=1; $day<=$days_in_month; $day++) {

        $week_day = date("w", mktime(0, 0, 0, $month, $day, $year));//0..6 starting sunday

        $weeks[$weeks_in_month][$week_day] = $day;

        if ($week_day == 6) {
            $weeks_in_month++;
        }

    }

    return $weeks;

}
  • 1
Reply Report

My 5 cents:

/**
* calculate number of weeks in a particular month
*/
function weeksInMonth($month=null,$year=null){

    if( null==($year) ) {
        $year =  date("Y",time());  
    }

    if(null==($month)) {
        $month = date("m",time());
    }

    // find number of days in this month
    $daysInMonths =  date('t',strtotime($year.'-'.$month.'-01'));

    $numOfweeks = ($daysInMonths%7==0?0:1) + intval($daysInMonths/7);

    $monthEndingDay= date('N',strtotime($year.'-'.$month.'-'.$daysInMonths));

    $monthStartDay = date('N',strtotime($year.'-'.$month.'-01'));

    if($monthEndingDay<$monthStartDay){

        $numOfweeks++;

    }

    return $numOfweeks;
}
  • 1
Reply Report

I create this function, from brazil :) I hope it is useful

function weekofmonth($time) {

    $firstday       = 1;
    $lastday        = date('j',$time);
    $lastdayweek = 6; //Saturday

    $week = 1;
    for ($day=1;$day<=$lastday;$day++) {
        $timetmp = mktime(0, 0, 0, date('n',$time), $day, date('Y',$time));
        if (date('N',$timetmp) == $lastdayweek) {
            $week++;
        }
    }
    if (date('N',$time)==$lastdayweek) {
        $week--;
    }

    return $week;
}

$time = mktime(0, 0, 0, 9, 30, 2014);
echo weekofmonth($time);
  • 1
Reply Report

I found a easy way to determine what week of the month today is in, and it would be a small change to have it work on any other date. I'm adding my two cents in here as I think my way is much more compact then the methods listed.

$monthstart = date("N",strtotime(date("n/1/Y")));
$date =( date("j")+$monthstart ) /7;
$ddate= floor( $date );
if($ddate != date) {$ddate++;}

and $ddate contains the week number you could modify it like so

function findweek($indate)
{
  $monthstart = date("N",strtotime(date("n/1/Y",strtotime($indate))));
  $date =( date("j",strtotime($indate))+$monthstart ) /7;
  $ddate= floor( $date );
  if($ddate != $date) {$ddate++;}
  return $ddate;
}

and it would return what week of the month any date you give it is. what it does is first find the number of days from the start of the week to the first of the month. then adds that on to the current date then divides the new date by 7 and that will give you how many weeks have passed since the start of the month, including a decimal place for the part of the the current week that has passed. so what I do next is round down that number, then compare the rounded down version to the original if the two match your at the end of the week so it's already in the number. if they don't then just add one to the rounded down number and voila you have the current week number.

  • 1
Reply Report

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions