FilChi Weblog

Getting the first monday of the month

Posted on: February 27, 2008


I thought I should share with my fellows this function I just created to get the first monday of the month using PHP.

function get_firstmonday($month,$year) {

$num = date(“w”,mktime(0,0,0,$month,1,$year));
if($num>1)
return date(“Y-M-d H:i:s”,mktime(0,0,0,$month,1,$year)+(86400*(8-$num)));
else
return date(“Y-M-d H:i:s”,mktime(0,0,0,$month,1,$year));
}

To use this function, simply provide your month as a number ranging from 1~12 and $year ranging from 1970 ~ future:

echo get_firstmonday(5,2008);

Update: please go to the comments for the correction of this function.
Thanks to Ben Donoghue for the correction!

Advertisements

36 Responses to "Getting the first monday of the month"

Hey,

Just had a nosey at your function and cool, it works great…

…except when you try something like

echo get_firstmonday(6,2008);

This gives 2008-06-09 00:00:00 which is the second Monday. This is because date(‘w’) gives the days of the week STARTING ON SUNDAY as 0. Therefore, any month starting on a Sunday will not work correctly. For myself I’ve made a small change if you’re interested:

function get_firstmonday($month,$year){

	$num = date("w",mktime(0,0,0,$month,1,$year));
	if($num==1)
		return date("Y-M-d H:i:s",mktime(0,0,0,$month,1,$year));
	elseif($num>1)
		return date("Y-M-d H:i:s",mktime(0,0,0,$month,1,$year)+(86400*(8-$num)));
	else
		return date("Y-M-d H:i:s",mktime(0,0,0,$month,1,$year)+(86400*(1-$num)));

}

I’ve not tried it but you may be able to use date(‘N’) in your original function to get Sunday as 7 instead of 0.

Cheers for it!

@Ben,

First of all, thank you very much for visiting my site.

Yes, you are right about my function. I overlooked it in that way.

And thanks for the correction.

How about getting the second, third and fourth Mondays?
Can you please help me?

@karlamarie,
thanks for visiting my site.

after getting the first monday of the month, maybe, you can just add up
7 days to the first monday to get second monday of the month. and, another 7 days to the second monday to get the third monday of the month, and so on.

for example, after calling the function, change it back to unix timestamp. And then, add (7*60*60*24) to it, and then calculate it with PHP date function.

Hi

i have a posted date and day number (sunday=0, monday=1 etc),
i want a function that calculate next immediate date depending on the day number passed to the function.

I have a function which calculate the first, last,second ,forth day of current month… but i this function wont work if i give the posted date .

$answer=strftime(“%d-%m-%Y”, get_first_day($daym, $cur_month, $cur_year,$onthe));

function get_first_day($day_number, $month, $year, $onthe)
{
$month = ($month === false) ? strftime(“%m”): $month;
$year = ($year === false) ? strftime(“%Y”): $year;

$first_day = 1 + ((7+$day_number – strftime(“%w”, mktime(0,0,0,$month, 1, $year)))%7);
if($onthe ==’1′)
{
$set_value =””;
}
elseif($onthe ==’2′)
{
$set_value =”7″;
}
elseif($onthe ==’3′)
{
$set_value =”14″;
}
elseif($onthe ==’4′)
{
$set_value =”21″;
}
elseif($onthe ==’5′)
{
//if current day of week is sunday, than only we manupulate this otherwise it will take $set_value =”21″;
$set_value =”21″;
}
return mktime(0,0,0,$month, $first_day+$set_value, $year);
}

This will give you any occurrence of a day of week. For example, the third Tuesday of the month, the last Friday of the month, the second Monday of the month… you get the picture.

$DOW = day of the week (0 = Sunday, 6 = Saturday).
$X = occurence (1 = first, 2 = third, etc..). If the given month does not have the occurrence, then it will return the last. For example, if you ask for the 7th occurrence of Friday, it will return the last Friday of the month.
$M = month
$Y = year

Example, get_Xth_DOW(2,3,7,2009) will return the third Tuesday of July 2009. It just returns the day. If you want the date you can just do
$D = get_Xth_DOW($DOW,$X,$M,$Y);
echo $M . “/” . $D . “/” . $Y;

function get_Xth_DOW($DOW,$X,$M,$Y) {
$numDays = date(‘t’,mktime(0,0,0,$M,1,$Y));
$add = 7*($X – 1);
$firstDOW = date(‘w’,mktime(0,0,0,$M,1,$Y));
$diff = $firstDOW – $DOW;
$d = 1;
if($diff > 0) { $d += (7 – $diff); }
else if ($diff $numDays) { $d -= 7; }
return $d;
}

I just realized that I didn’t post the entire code. Sorry, here is the entire function.

function get_Xth_DOW($DOW,$X,$M,$Y) {
$numDays = date(‘t’,mktime(0,0,0,$M,1,$Y));
$add = 7*($X – 1);
$firstDOW = date(‘w’,mktime(0,0,0,$M,1,$Y));
$diff = $firstDOW – $DOW;
$d = 1;
if($diff > 0) { $d += (7 – $diff); }
else if ($diff $numDays) { $d -= 7; }
return $d;
}

@JoeDundas, the next to last line of your function (else if) is missing a comparison operator between $diff and $numDays, no?

@joe dundas

Your code was a bit flawed, with some calculations totally overlooked. For one, the missing comparison operator that kook pointed out. Two, you declared and assigned $add but never used it anywhere. It should have been used in the comparisons at the end of the function where the numeral 7 was written. Three, if the elseif statement was true, the re-assigned variable of $d (in your case) would not have been assigned a meaningful result without further manipulation.

Nevertheless, I read the intended meaning of your code, and took it upon myself to correct it for all those unsure of the required modifications, as your function is still pretty handy.

The code below is the corrected version of joe’s function, for anyone that needs this functionality but couldn’t get the desired results.

function get_xth_dow($dow, $occurence, $m, $y)
{
$numdays = date(‘t’, mktime(0, 0, 0, $m, 1, $y));
$add = 7 * ($occurence – 1);
$firstdow = date(‘w’,mktime(0, 0, 0, $m, 1, $y));
$diff = $firstdow – $dow;

$day_of_month = 1;
if($diff > 0)
{
$day_of_month += ($add – $diff);
}
elseif ($diff < $numdays)
{
$day_of_month -= ($diff – $add);
}
return $day_of_month;
}

Alright–completely disregard the last piece of code I posted. It doesn’t work–it only worked for the month of March 2009. Outside of that month, it simply did not work. After several hours of coding, trying to make it possible to get the date within a month from the name of day in that month, and moreover its nth occurrence, I have written the following from scratch. I guarantee it works, as it was tested with dozens of month, name day, and year combinations.

The function works with timestamps. You can replace date(‘d’, $date_of_occurrence) with $date_of_occurrence to simply return the timestamp of the result date, otherwise it will return a two-digit representation of the date with a leading 0 if date is only one digit.

$occurrence represents the first, second, third, fourth, or fifth occurrence of $name_of_day in the given month

$name_of_day represented by numerals 1 to 7 (Monday to Sunday, respectively)
—————————————————————————–

function date_from_nameday($occurrence, $name_of_day, $month, $year)
{
$one_day = 24 * 60 *60;
$one_week = 7 * $one_day;

$one = mktime(0, 0, 0, $month, 1, $year);
$two = $one + $one_day;
$three = $two + $one_day;
$four = $three + $one_day;
$five = $four + $one_day;
$six = $five + $one_day;
$seven = $six + $one_day;

$first = date(‘N’, $one);
$second = date(‘N’, $two);
$third = date(‘N’, $three);
$fourth = date(‘N’, $four);
$fifth = date(‘N’, $five);
$sixth = date(‘N’, $six);
$seventh = date(‘N’, $seven);

switch($name_of_day)
{
case $first: $first_occurrence = $one; break;
case $second: $first_occurrence = $two; break;
case $third: $first_occurrence = $three; break;
case $fourth: $first_occurrence = $four; break;
case $fifth: $first_occurrence = $five; break;
case $sixth: $first_occurrence = $six; break;
case $seventh: $first_occurrence = $seven; break;
}

$date_of_occurrence = ($occurrence > 1) ? $first_occurrence + ($one_week * ($occurrence – 1)) : $first_occurrence;

return date(‘d’, $date_of_occurrence); // manipulate timestamp
}

—————————————————————————-
Example usage

Get the second Sunday in March for DST:

$second_sunday_of_march = date_from_nameday(2, 7, 3, 2009);

My site contains my email if you have any questions.

Although your code is correct but it doesn’t return last day if we need to get that. For instance try this

echo date_from_nameday(5,1,4,2009);

you will get day of next month, I have corrected your code and here is the correct function .. Tested and working!

function date_from_nameday($occurrence, $name_of_day, $month, $year)
{
$one_day = 24 * 60 *60;
$one_week = 7 * $one_day;

$one = mktime(0, 0, 0, $month, 1, $year);
$two = $one + $one_day;
$three = $two + $one_day;
$four = $three + $one_day;
$five = $four + $one_day;
$six = $five + $one_day;
$seven = $six + $one_day;

$first = date(‘N’, $one);
$second = date(‘N’, $two);
$third = date(‘N’, $three);
$fourth = date(‘N’, $four);
$fifth = date(‘N’, $five);
$sixth = date(‘N’, $six);
$seventh = date(‘N’, $seven);

switch($name_of_day)
{
case $first: $first_occurrence = $one; break;
case $second: $first_occurrence = $two; break;
case $third: $first_occurrence = $three; break;
case $fourth: $first_occurrence = $four; break;
case $fifth: $first_occurrence = $five; break;
case $sixth: $first_occurrence = $six; break;
case $seventh: $first_occurrence = $seven; break;
}

$date_of_occurrence = ($occurrence > 1) ? $first_occurrence + ($one_week * ($occurrence – 1)) : $first_occurrence;

$day_to_return = date(‘d’, $date_of_occurrence);
$month_of_day = date(‘m’, $date_of_occurrence);
if ($month_of_day != $month)
return -1;
else
return $day_to_return;
}

Getting the first monday of the month in Ruby

def self.find_by_year_month(year, month)
d = Date.parse(“01-#{month}-#{year}”)

# Get the beginning of the month.
new_date = d.at_beginning_of_week
if new_date < d
new_date = new_date.next_week
end

new_date
end

Hi Steven, thanks for your comment.

I appreciate you try doing that in ruby. I still have to study your code if it runs well.

Yeah, something happened both times on my copy and paste. The first time, a whole chunk of the end was left off. Next time, it looks like some other pieces were left out. Sorry about the $add remnant, I took it out.

here it is again.

function get_Xth_DOW($DOW,$X,$M,$Y) {
$numDays = date(‘t’,mktime(0,0,0,$M,1,$Y));
$add = 7*($X – 1);
$firstDOW = date(‘w’,mktime(0,0,0,$M,1,$Y));
$diff = $firstDOW – $DOW;
$d = 1;
if($diff > 0) { $d += (7 – $diff); }
else if ($diff $numDays) { $d -= 7; }
return $d;
}

Frick. I have to make it printable in HTML. Lets see if this comes out right.

function get_Xth_DOW($DOW,$X,$M,$Y) {
$numDays = date(‘t’,mktime(0,0,0,$M,1,$Y));
$add = 7*($X – 1);
$firstDOW = date(‘w’,mktime(0,0,0,$M,1,$Y));
$diff = $firstDOW – $DOW;
$d = 1;
if($diff > 0) { $d += (7 – $diff); }
else if ($diff < 0) { $d += -1*$diff; }
$d = $d + $add;
while($d > $numDays) { $d -= 7; }
return $d;
}

Hi folks,

I was looking for a php code, that gives me every first saturday of each month.

Sorry I am a noob to php and don´t get it right.

Could somebody supply me the altered code from the original working function?

I greatly appreciate your help.

Greetings from Germany!
EBA

Hi EBA,

Use my get_Xth_DOW($DOW,$X,$M,$Y) code above. Just call it in a loop.

$Y = 2009;
for($M=1; $M<=12; $M++) {
$firstSat = get_Xth_DOW(6,1,$M,$Y);
}

How about this?

function getStartDay($day,$month,$year){

return date(‘d/m/Y’,strtotime(‘First ‘.$day.’ ‘.date(”.$month.’/01/’.$year.”)));

}

echo getStartDay(‘Monday’,9,2009);

Actually, this is better than the last comment – as it’ll return the correct date if the first Saturday (for example) is on the 1st (i.e. First Saturday in August 2009)

function getStartDay($day,$month,$year){

$firstWeekDay = date(‘d/m/Y’,strtotime(‘First ‘.$day.’ ‘.date(”.$month.’/01/’.$year.”)));
$firstDay = mktime(0,0,0,$month, 1, $year);
$firstDayMonth = date(‘l’, $firstDay);

if ($day==$firstDayMonth) { return “01/”.$month.”/”.$year.””; }
else { return $firstWeekDay; }

}

echo getStartDay(‘Saturday’,1,2009);

There’s a very simple way to do this in PHP.

strtotime(“monday october”);

will return the first monday in october. If you want to get the second or third you could do the following:

$first_monday = strtotime(“monday october”);
$third_monday = strtotime(“+2 weeks”, $third_monday);

Sure, these are in epoch time (Seconds from 1/1970) but you can easily convert them using the date() function.

Cheers,
J

Hi Jordan.

You are correct that getting the first monday in PHP can be simply done using strtotime.

but take note that as it is stated in the documentation,
“In PHP 5 prior to 5.2.7, requesting a given occurrence of a given weekday in a month where that weekday was the first day of the month would incorrectly add one week to the returned timestamp. This has been corrected in 5.2.7 and later versions. ”

because of this, I tried this code: (my php version is 5.2.6)

   strtotime("first monday -1 week");

and it works!

echo $newdate = date(‘l, Y-m-d’,strtotime(date(“Y-m-d”, strtotime(‘first sunday june’)) . ” -1 week”));

[…] />”; Share this post! Twitter Digg Facebook Delicious StumbleUpon Google Bookmarks LinkedIn Technorati […]

Here is the best, and easiest, way i could come up with..

<?php

// date May 5 2010
$month = 5;
$day = 15;
$year = 2010;
$dayName = 'Wednesday';

/*
Alternatively, manually set dayName from a date
$dayName = date('l', strtotime("$month/$day/$year"));
*/

// Call function and print results
$myDays = get_days($month, $dayName, $year);
print_r($myDays);

function get_days($Month, $DayName, $Year) {

// Calculate the Number of Days in the Month
$numDays = date('t', strtotime("$Month/1/$Year"));
$arrCount = 0;

// Loop through every Day in the Month
for ($i=0; $i

Output:

Array ( [0] => 05/05/2010 [1] => 05/12/2010 [2] => 05/19/2010 [3] => 05/26/2010 )

Thus, the first Wednesday in May would be $myDays[0], the second $myDays[1], etc, etc..

correction..

for ($i=0; $i<$numDays; $i++){

should be

for ($i=0; $i<=$numDays; $i++){

Thanks for this post, been saving it for a while knowing I would need it one day soon.

Really interesting comments too.

When I found Jordan’s simple solution I thought that would be easier, along with phpcurious’ tweak. When I run Jordan’s code for June 2010, it returns June 8 as the first tuesday (should be June 1), and phpcurious’ solutions fixes that, but my system is running php 5.2.9.

I’m going to use it to regulate a cron (the cron will run every Tuesday, the page will check if it’s the first Tuesday), and it’s pretty important it be accurate.

So beware, there still seems to be some holes in it.

Don’t know if it’s a bug, but despite what the manual says, this is not fixed in version 5.2.9. phpcurious’ -1 week doesn’t work unless the first XX of the month is on the first of the month either, so 5.2.9 is between a rock and a hard place.

I found this in the comments section of strtotime in the manual which seems to work flawlessly to find the first tuesday …

Of course for my purposes it’s easy to use variables for the month and year to see if, when the cron runs the page every tuesday, is this tuesday the first one of the month.

I tested it from June 2010 to May 2011 and the results were perfect. Note that in June ’10, Feb ’11 and Mar ’11 the first tuesday is on the 1st, no problem.

Hope this is useful, and cheers to Leon F on the 4th Nov 09 over at the manual.

D’oh…

echo date(“d/m/y”, strtotime(‘+0 week tue january 2011’));

I am glad that you found it helpful. 😀

phpcurious

I got a lot out of this post, but none of the solutions posted worked for me fully, so I did a little work and came up with this solution which worked for me. Required variables to pass are a date (any form), and day of week (weekday, format ‘w’, 0-6). Optional variables are which occurrence, assumed 1st if not provided, max of 5 allowed. If a valid weekday isn’t passed, or if occurrence isn’t valid or doesn’t exist (i.e., 5th week doesn’t exist), then the function returns false. Otherwise the date of the month is returned. Thanks to all who provided this info to help me. I’m saying thanks by handing this code back.

function dateOfMonth ($theDate,$weekDay=-1,$x=1) {
// process input
$theDate = date(‘U’,strtotime($theDate));
$theDate = (isset($theDate)) ? $theDate : date(‘U’);
$weekDay = intval($weekDay);
if ($weekDay < 0) { return false;
} elseif ($weekDay > 6) { return false;
}
$x = intval($x);
if ($x < 1) { return false;
} elseif ($x > 5) { return false;
}
// set working vars
$year = date(‘Y’,$theDate);
$month = date(‘n’,$theDate);
$monthDays = date(‘t’,$theDate);
$monthFirstWeekDay = date(‘w’,mktime(0,0,0,$month,1,$year));
$daysAdd = 7*($x-1);
$daysDiff = $weekDay – $monthFirstWeekDay;
// set first occurence of weekday
if ($daysDiff < 0) { $weekDayFirst = 8 + $daysDiff;
} else { $weekDayFirst = 1 + $daysDiff;
}
$day = $weekDayFirst + $daysAdd;
if ($day > $monthDays) { return false; }
return $day;
}

Thanks for the contributions here – none of them worked fully for me but they gave me ideas and here is my code.

You pass the function a year, a month and a three letter representation of the day you are interested in (Mon, Tue, etc).

The return value is an array with the first element as a dummy so if you want the second Tuesday of July 2010 you would call;

$dates = get_month_days(2010, 7, Tue);

The second Tuesday would be $dates[2] – no reason for making the first element a dummy other than keeping things simple.

I have tested this and it works well for me – comments appreciated.

function get_month_days($year, $month, $day){
$max = cal_days_in_month(CAL_GREGORIAN, $month, $year);

$dates = array();
$dates[] = ‘dummy’;
for ($i = 1; $i <= $max; $i++){
$temp_day = date('D', mktime(0, 0, 0, $month, $i, $year));
if ($temp_day == $day){
$dates[] = date("$year-$month-$i");
}
}

return $dates;
}

Excellent – best one here!

Sweet! This one was very helpful, thanks!!

Here is a solution in Ruby. You can call the methods like this: ‘mydate = Weekday.first_monday(2010,10)’ (or ..Weekday.third_friday(2010,10) or ..Weekday.fifth_saturday(2010,10)

require ‘date’
class Weekday
COUNTWORDS = %w(first second third fourth fifth last)
DAYNAMES = %w(sunday monday tuesday wednesday thursday friday saturday)
PREV = %w(nil nil) + COUNTWORDS

def self.method_missing(m, *args)
# p “#{m} aufgerufen args=#{args}”
count,weekday = m.to_s.split(‘_’)
unless COUNTWORDS.include?(count)
raise NoMethodError, “undefined method `#{m}'”
end
count = COUNTWORDS.index(count)+1
wnum = DAYNAMES.index(weekday)
unless wnum
raise NoMethodError, “undefined method `#{m}'”
end
if count == COUNTWORDS.index(COUNTWORDS[-1])+1
d = Date.new(args[0],args[1],-1)
while not d.wday == wnum do
d -= 1
end
return d
end
case count
when 1
d = Date.new(args[0],args[1],1)
while not d.wday == wnum do
d += 1
end
return d
when 2..5
m_name = (PREV[count] + ‘_’ + weekday).to_sym
prev = self.send((PREV[count] + ‘_’ + weekday),args[0],args[1])
result = if prev
prev + 7
else
nil
end
unless result and result.month == args[1]
result = nil
end
return result
else
raise NoMethodError, “undefined method `#{m}'”
end
end
end

the simple move can be solved by this code..

echo $newdate = date(‘l, Y-m-d’,strtotime(date(“Y-m-d”, strtotime(‘first sunday june’)) . ” -1 week”));

How can i find the first sunday of the given month?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Flickr Photos

%d bloggers like this: