Viewed   75 times

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?

 Answers

3

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
Friday, September 2, 2022
 
1

How can I make it return today's date in that case?

pseudocode:

if (today == monday)
    return today;
else
    return strtotime(...);

Btw, this trick also could work:

strtotime('last monday', strtotime('tomorrow'));
Saturday, December 24, 2022
4

Why don't you get first monday, and do a loop adding 7 days to it until it is next year?

$first = strtotime("first monday of $year[$j]");
$lastday = mktime(0, 0, 0, 12, 31, $year[$j]);

$day = $first;
do {
    echo date('M d, Y', $day);
    $day += 7 * 86400;

} while ($day < $lastday);
Tuesday, August 16, 2022
 
pnuts
 
2

strtotime doesn't "output" anything, btw : it returns false in case of an error ; see the manual :

Return Values

Returns a timestamp on success, FALSE otherwise. Previous to PHP 5.1.0, this function would return -1 on failure.

What doesn't output anything is echo : false is considered as an empty string, and nothing get outputed.

strtotime's documentation also gives the valid range for dates :

Note: The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.) Additionally, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch. This means that e.g. dates prior to Jan 1, 1970 will not work on Windows, some Linux distributions, and a few other operating systems. PHP 5.1.0 and newer versions overcome this limitation though.

'0000-00-00' is outside of this range, so it's not considered a valid date ; hence the false return value.


As a sidenote, to really know what's inside a variable, you can use var_dump.
As a bnus, used with Xdebug, it'll get you a nice-formated output ;-)

Sunday, August 7, 2022
4

I'm afraid you have fallen into one of the numerous traps of object mutation. :)

The problem is that, in the line "var nextday = ...", you are changing the date saved in "curr" on every iteration by calling setDate(). That is no problem as long as next is within the range of the current month; curr.setDate(next) is equivalent to going forward one in this case.

The problems begin when next reaches 30. There is no February 30, so setDate() wraps around to the next month, yielding the 1st of March - so far so good. Unfortunately, the next iteration calls curr.setDate(31), and as curr is the 1st of March (remember that the object referenced by curr is changed in each iteration), we get... March 31! The other strange values can be explained the same way.

A way to fix this is to copy curr on each iteration and then call setDate(), like so:

for (var i = 1; i < 7; i++) {
    var next = new Date(curr.getTime());
    next.setDate(first + i);
    alert(next.toString());
}
Friday, August 19, 2022
 
stol
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :