PHP 5.3.13 strtotime() behavior using days of the week as frames of reference (Windows & Linux)

Say you want to get a set of timestamps so that you can query a database for all records that fall between the start of this week, and the end of this week.

One would logically try something like:

$start_of_week = strtotime("this monday"); // Or "monday this week"
$end_of_week = strtotime("next monday - 1 second"); // Or "monday next week - 1 second"
That will, in theory, give you a date range of Monday at 00:00:00, and Sunday at 23:59:59. Unforunately, that is not always the case.

It turns out trying to find relative time references with strtotime is wonky. Depending on which day it currently is, and what day you're trying to use as a frame of reference, you will get different results when using 'this monday' or 'tuesday next week' etc... The results are unintuitive, but more importantly, inconsistent in most cases.

Since strtotime() lets us do lazy math to get timestamps (e.g. 'this monday - 1 week'), all we need to do is find some date string that works consistently 7 days of the week, and then we can reliably find other timestamps relative to that string. Any date string that does not have the same results for all 7 days, cannot be used as a frame of reference, as its value will change depending on what day it is!

From the tables below, we can see that the following three strings can be safely used as frames of reference in strtotime():

strtotime("next monday");
strtotime("this sunday");
strtotime("last sunday");

My suspicion is that certain strings consider Sunday to be the start of the week, while others consider Monday to be the start of the week, and probably round the time up or down in different ways.

Note that I have arbitrarily chosen Monday - March 4th, 2013 through Sunday - March 10th, 2013 as the week to test. Though given how wonky strtotime()'s behavior is, there's a possibility that the behavior shown below varies from one week to the next! However, I did test various times throughout each day (e.g. 00:00:00 and 23:59:59) and thankfully the results were consistent.

So going back to our problem of getting timestamps for the start and end of this week, the cleanest and most reliable solution is this:

$start_of_week = strtotime("next monday - 1 week"); // Will return Monday of the current week starting at 00:00:00"
$end_of_week = strtotime("next monday - 1 second"); // Will return Sunday of the current week ending at 23:59:59"
Using Monday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this monday") =March 4thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11th
strtotime("monday this week") =March 4thMarch 4thMarch 4thMarch 4thMarch 4thMarch 4thMarch 4th
strtotime("next monday") =March 11thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11th
strtotime("monday next week") =March 11thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11thMarch 11th
strtotime("last monday") =February 25thMarch 4thMarch 4thMarch 4thMarch 4thMarch 4thMarch 4th
strtotime("monday last week") =February 25thFebruary 25thFebruary 25thFebruary 25thFebruary 25thFebruary 25thFebruary 25th
Using Tuesday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this tuesday") =March 5thMarch 5thMarch 12thMarch 12thMarch 12thMarch 12thMarch 12th
strtotime("tuesday this week") =March 5thMarch 5thMarch 5thMarch 5thMarch 5thMarch 5thMarch 5th
strtotime("next tuesday") =March 5thMarch 12thMarch 12thMarch 12thMarch 12thMarch 12thMarch 12th
strtotime("tuesday next week") =March 12thMarch 12thMarch 12thMarch 12thMarch 12thMarch 12thMarch 12th
strtotime("last tuesday") =February 26thFebruary 26thMarch 5thMarch 5thMarch 5thMarch 5thMarch 5th
strtotime("tuesday last week") =February 26thFebruary 26thFebruary 26thFebruary 26thFebruary 26thFebruary 26thFebruary 26th
Using Wednesday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this wednesday") =March 6thMarch 6thMarch 6thMarch 13thMarch 13thMarch 13thMarch 13th
strtotime("wednesday this week") =March 6thMarch 6thMarch 6thMarch 6thMarch 6thMarch 6thMarch 6th
strtotime("next wednesday") =March 6thMarch 6thMarch 13thMarch 13thMarch 13thMarch 13thMarch 13th
strtotime("wednesday next week") =March 13thMarch 13thMarch 13thMarch 13thMarch 13thMarch 13thMarch 13th
strtotime("last wednesday") =February 27thFebruary 27thFebruary 27thMarch 6thMarch 6thMarch 6thMarch 6th
strtotime("wednesday last week") =February 27thFebruary 27thFebruary 27thFebruary 27thFebruary 27thFebruary 27thFebruary 27th
Using Thursday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this thursday") =March 7thMarch 7thMarch 7thMarch 7thMarch 14thMarch 14thMarch 14th
strtotime("thursday this week") =March 7thMarch 7thMarch 7thMarch 7thMarch 7thMarch 7thMarch 7th
strtotime("next thursday") =March 7thMarch 7thMarch 7thMarch 14thMarch 14thMarch 14thMarch 14th
strtotime("thursday next week") =March 14thMarch 14thMarch 14thMarch 14thMarch 14thMarch 14thMarch 14th
strtotime("last thursday") =February 28thFebruary 28thFebruary 28thFebruary 28thMarch 7thMarch 7thMarch 7th
strtotime("thursday last week") =February 28thFebruary 28thFebruary 28thFebruary 28thFebruary 28thFebruary 28thFebruary 28th
Using Friday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this friday") =March 8thMarch 8thMarch 8thMarch 8thMarch 8thMarch 15thMarch 15th
strtotime("friday this week") =March 8thMarch 8thMarch 8thMarch 8thMarch 8thMarch 8thMarch 8th
strtotime("next friday") =March 8thMarch 8thMarch 8thMarch 8thMarch 15thMarch 15thMarch 15th
strtotime("friday next week") =March 15thMarch 15thMarch 15thMarch 15thMarch 15thMarch 15thMarch 15th
strtotime("last friday") =March 1stMarch 1stMarch 1stMarch 1stMarch 1stMarch 8thMarch 8th
strtotime("friday last week") =March 1stMarch 1stMarch 1stMarch 1stMarch 1stMarch 1stMarch 1st
Using Saturday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this saturday") =March 9thMarch 9thMarch 9thMarch 9thMarch 9thMarch 9thMarch 16th
strtotime("saturday this week") =March 9thMarch 9thMarch 9thMarch 9thMarch 9thMarch 9thMarch 9th
strtotime("next saturday") =March 9thMarch 9thMarch 9thMarch 9thMarch 9thMarch 16thMarch 16th
strtotime("saturday next week") =March 16thMarch 16thMarch 16thMarch 16thMarch 16thMarch 16thMarch 16th
strtotime("last saturday") =March 2ndMarch 2ndMarch 2ndMarch 2ndMarch 2ndMarch 2ndMarch 9th
strtotime("saturday last week") =March 2ndMarch 2ndMarch 2ndMarch 2ndMarch 2ndMarch 2ndMarch 2nd
Using Sunday as a frame of reference
If today =Mon, March 4thTue, March 5thWed, March 6thThu, March 7thFri, March 8thSat, March 9thSun, March 10th
strtotime("this sunday") =March 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 10th
strtotime("sunday this week") =March 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 10th
strtotime("next sunday") =March 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 10thMarch 17th
strtotime("sunday next week") =March 17thMarch 17thMarch 17thMarch 17thMarch 17thMarch 17thMarch 17th
strtotime("last sunday") =March 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rd
strtotime("sunday last week") =March 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rdMarch 3rd