Getting first weekday in a month with strtotime

I’m trying to figure out the first wednesday of a given month using strtotime, but the “first wednesday” argument fails whenever the first wednesday happens to fall on the 1st.

For a more general illustration of this problem, see the following code and result:

$mon = strtotime("December 2010 first monday");
$tue = strtotime("December 2010 first tuesday");
$wed = strtotime("December 2010 first wednesday");
$thu = strtotime("December 2010 first thursday");
$fri = strtotime("December 2010 first friday");
$sat = strtotime("December 2010 first saturday");
$sun = strtotime("December 2010 first sunday");

echo strftime("%m/%d/%y", $mon) . "<br>";
echo strftime("%m/%d/%y", $tue) . "<br>";
echo strftime("%m/%d/%y", $wed) . "<br>";
echo strftime("%m/%d/%y", $thu) . "<br>";
echo strftime("%m/%d/%y", $fri) . "<br>";
echo strftime("%m/%d/%y", $sat) . "<br>";
echo strftime("%m/%d/%y", $sun) . "<br>";

Results in:

12/06/10
12/07/10
12/08/10
12/02/10
12/03/10
12/04/10
12/05/10

Notice something? Shouldn’t one day of the week coincide with the 1st of the month? But it never does, and instead the second instance of the day, on the 8th, is always returned.

Anyone have an explanation for this?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Building off the answers provided, one needs to be aware of differences in relative date formatting between php 5.2 and php 5.3.

TEST:

$date1 = strtotime("first wednesday of 2010-12");
$date2 = strtotime("first wednesday 2010-12");
$date3 = strtotime("wednesday 2010-12");

5.2 Results:

1969-12-31
2010-12-08
2010-12-01

5.3 Results:

2010-12-01
2010-12-08
2010-12-01

Therefore only the third method returns correct results across PHP 5 versions.

Solution 2

I don’t have any explanation as I’m also dazzled, but I managed to find out how you get the correct date by omitting the “first”, like so:

$ php -r 'echo date("m/d/y", strtotime("December 2010 Wednesday"));'
12/01/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Thursday"));'
12/02/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Friday"));'
12/03/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Saturday"));'
12/04/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Sunday"));'
12/05/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Monday"));'
12/06/10

$ php -r 'echo date("m/d/y", strtotime("December 2010 Tuesday"));'
12/07/10

Solution 3

It’s just your formatting that is incorrect. You need to include of:

echo strftime("%m/%d/%y", strtotime("first Monday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Tuesday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Wednesday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Thursday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Friday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Saturday of December 2010"));
echo strftime("%m/%d/%y", strtotime("first Sunday of December 2010"));

Prints:

12/06/10
12/07/10
12/01/10
12/02/10
12/03/10
12/04/10
12/05/10

The accepted solution works, but you would encounter problems if you wanted to find the second weekday:

echo strftime("%m/%d/%y", strtotime("December 2010 second Wednesday"));

Prints:

12/15/10

There are some examples given in the docs:

http://www.php.net/manual/en/datetime.formats.relative.php

The second block of notes in the above documentation explains how of affects the date calculation process:

Also observe that the “of” in “ordinal
space dayname space ‘of’ ” and “‘last’
space dayname space ‘of’ ” does
something special.

  1. It sets the day-of-month to 1.
  2. “ordinal dayname ‘of’ ” does not advance to another day. (Example:
    “first tuesday of july 2008” means
    “2008-07-01”).
  3. “ordinal dayname ” does advance to another day. (Example: “first
    tuesday july 2008” means “2008-07-08”,
    see also point 4 in the list above).
  4. “‘last’ dayname ‘of’ ” takes the last dayname of the current month.
    (Example: “last wed of july 2008”
    means “2008-07-30”)
  5. “‘last’ dayname” takes the last dayname from the current day.
    (Example: “last wed july 2008” means
    “2008-06-25”; “july 2008” first sets
    the current date to “2008-07-01” and
    then “last wed” moves to the previous
    Wednesday which is “2008-06-25”).

Solution 4

I found this note in the PHP manual.

“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.”

Solution 5

PHP 5.5.11

$firstWeekdayOfMonth = new DateTime('first weekday 0 jun 2016');

I don’t know why, but the zero kind of force the strtotime parser to start at the beginning of the month considering the first day.

Solution 6

I believe it’s the order in which you are placing values.
When you write “December 2010”, it already is going to 12/01/2010. When adding “first
{day}”, function goes for that very first day, after the 12/01/2010. I think if you declare the “first {day}” value and then “december 2010” it should work fine.

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply