PHP: Calculating past and future dates
The strtotime function in PHP is incredibly powerful but very much underutilised - mainly because some aspects can be a bit confusing and people are more confident 'doing things the hard way'. The strtotime function doesn't just convert date strings to timestamp values but also has its own 'language' to let you specify just about any date or time you want.
Calculating dates for past and future days
The easiest and most common calculations are based on seconds, minutes, hours and days. Months and years are also valid input but not always useful in calculations as they're not all of equal length because of the way our calendar works.
Shown below are the results of various strings passed to strtotime and converted to date strings.
For example:
echo date('l jS F (Y-m-d)', strtotime('-3 days'));
- 3 days ago
- Thursday 19th December (2024-12-19)
- -3 days
- Thursday 19th December (2024-12-19)
- -2 days
- Friday 20th December (2024-12-20)
- yesterday
- Saturday 21st December (2024-12-21)
- now
- Sunday 22nd December (2024-12-22)
- today
- Sunday 22nd December (2024-12-22)
- tomorrow
- Monday 23rd December (2024-12-23)
- +2 days
- Tuesday 24th December (2024-12-24)
- +3 days
- Wednesday 25th December (2024-12-25)
As always there are often different ways to achieve the same result. In the list above you can see that '3 days ago' is equivalent to '-3 days'. Also 'yesterday' is the same as '-1 days' or '1 day ago'. The 's' on the end of 'days', 'years' or other measurements can be left off if you want.
The 'now' and 'today' input values in the list above are superfluous as if we leave off the second paramater of the date function it will default to the current time anyway.
Working with days of the week
Sometimes we work with days of the week and need to know the last/next occurrence of, for example, a Saturday:
- -2 weeks Saturday
- Saturday 14th December (2024-12-14)
- last Saturday
- Saturday 21st December (2024-12-21)
- Saturday
- Saturday 28th December (2024-12-28)
- this Saturday
- Saturday 28th December (2024-12-28)
- first Saturday
- Saturday 28th December (2024-12-28)
- next Saturday
- Saturday 28th December (2024-12-28)
- third Saturday
- Saturday 11th January (2025-01-11)
- +2 weeks Saturday
- Saturday 11th January (2025-01-11)
In the list above we can see that 'Saturday', 'this Saturday' and 'first Saturday' are all equivalent. The 'this' and 'first' keywords are only used to improve readability.
Now it gets a bit complicated to explain. The following appears on the PHP website:
In PHP 5 up to 5.0.2, "now" and other relative times are wrongly computed from today's midnight. It differs from other versions where it is correctly computed from current time.
In addition, they've introduced 'second' as in 'second Saturday' and seem to have changed the meaning of 'next' to mean the same as 'first'. Finally, the return value on failure is now FALSE instead of -1. This last change is the most likely to cause problems in legacy applications.
The table below shows how the output has changed:
Older versions of PHP: | PHP 5.0.2 and higher: |
---|---|
|
|
Using offsets to get the right day
Another problem is when you want to find the previous or next occurence of a certain day of the week. For example, today being a Sunday we can run the following:
- last Sunday
- Sunday 15th December (2024-12-15)
- Sunday
- Sunday 22nd December (2024-12-22)
- this Sunday
- Sunday 22nd December (2024-12-22)
- first Sunday
- Sunday 29th December (2024-12-29)
- next Sunday
- Sunday 29th December (2024-12-29)
- third Sunday
- Sunday 12th January (2025-01-12)
Older versions of PHP: | PHP 5.0.2 and higher: |
---|---|
|
|
You can see in the table above that, while 'next Sunday' returns the same result, the 'first', 'second', 'third', ... modifiers have all changed in meaning - thankfully to a more logical state.
You may notice also that this only occurs when you're calculating from the current day and not in the previous examples (unless today is Saturday). Whenever you do calculations based on days you should test as many possibilities as possible: Does it work today? yesterday? tomorrow? and so on.
Sometimes you want to find the last occurence of a day before today, or before yesterday or before 2 days ago. The following examples show the syntax you can use for this:
- -3 days last Saturday
- Wednesday 18th December (2024-12-18)
- -2 days last Saturday
- Thursday 19th December (2024-12-19)
- yesterday last Saturday
- Friday 20th December (2024-12-20)
- tomorrow Saturday
- Sunday 29th December (2024-12-29)
- +2 days Saturday
- Monday 30th December (2024-12-30)
- +3 days Saturday
- Tuesday 31st December (2024-12-31)
Now that you understand the inner workings of strtotime you should be able to drastically reduce the amount of code required to calculate past and future dates.
Checking if a date is in the Past or Future
The strtotime function returns an integer value so it's a simple matter to see if a date is in the past or in the future.
if(strtotime(dateString) > time()) {
# date is in the future
}
if(strtotime(dateString) < time()) {
# date is in the past
}
if(strtotime(dateString) == time()) {
# date is right now
}
time() is equivalent to date('U') and returns the current timestamp to the nearest second.
You might want to replace time() with strtotime('0:00') if you want to compare a date string to the current date rather than the current date and time.
References
User Comments
Most recent 20 of 26 comments:
Post your comment or question
Henry 5 February, 2019
For my server;
date('l jS F (Y-m-d)', strtotime('+$kac days'))
gives me;
Thursday 1st January (1970-01-01)
where is the problem for 1970 date ?
You need to use double quotes when the string contains a variable:
date('l jS F (Y-m-d)', strtotime("+{$kac} days"));
hanumesh 12 April, 2018
$result = mysql_query("select * from lead_generate where assignedTo = '".$_SESSION['userId']."' AND status != '5' AND nextFollowup BETWEEN '".date('Y-m-d')." 00:00:00' AND '".date('Y-m-d')." 23:59:59'");
this query for fetching values on current date. I want to fetch values from previous day to past 5 years and also from tomorrow date to future 5 years. Please help me out with this. Thanks in advance.
In PostgreSQL you can use:
... BETWEEN CURRENT_DATE - INTERVAL '5 years + 1 day' AND CURRENT_DATE +
INTERVAL '5 years + 1 day' ...
MySQL should be similar.
Dana 6 June, 2017
I am trying to create a formula that will provide the sabbatical date every six years from hire date. For example, if an employee's hire date was 9/30/1993, what would the formula be to indicate that another sabbatical is due as of 9/30/2017?
Shayne 1 June, 2017
I am trying to create a form that when submitted until 0600 the next day still returns the previous day's date.
This is for security guard shift work. The officer starts his shift on feb 02 @ 1800 and works until 0600 on Feb 03. Everything he submits all night should reflect the correct time but default to the starting date (Feb 02). Starting 0601 Feb 03 until 0600 Feb 04 would result in a date of Feb 03.
I hope I haven't confused anyone... lol
Something like this should work:
$date = date('Y-m-d', strtotime('-6 hours'))
$time = date('H:i:s');
naim 17 April, 2016
how to calculate next working day exclude weekend and holiday and check the next working day falls on working day or holiday, and if fall on holidays check until it fall on working day again
Parimala Rai 2 October, 2015
Hi
How do I get the date where the condition is given for eg.,"Last Saturday of the month" assuming for OCT 15
Regards
This might be what you're after:
$last_saturday_this_month = date('l jS F', strtotime("next month last Saturday"));
Beatrice 24 January, 2014
Thank you so much for that, simple clear and concise, I am presently in the first quarter of a php/SQL programming certificate, labs can be nightmarish and every time I find some help like this I am so grateful
Neil 6 August, 2013
I need to display the date for the next meeting that occurs on the second Monday of the month. For example on 1st August 2013, show 12th August 2013, on 13th August 2013 show 9th September 2013. I would also like it to ignore January & July (meetings do not occur those months) and display the February/August meeting dates instead. Any help appreciated.
Obviously you will need a function for this and not just a single strotime command. This should get you started:
$lastday = date('Y-m-d', strtotime("last day of last month"));
$thismeeting = date('Y-m-d', strtotime("$lastday second Monday"));
$lastday = date('Y-m-d', strtotime("last day of this month"));
$nextmeeting = date('Y-m-d', strtotime("$lastday second Monday"));
You can replace "last month" with "2013-08" if you want to loop through the year.
danny 13 July, 2013
I want to calculate every 5days from when a user signed up. How do I go abtt this..
Something like this should work:
<?PHP
$start = "2013-02-22";
for($i=1; $i < 10; $i++) {
echo date("Y-m-d", strtotime("$start + " . ($i*5) . " day")) . "<br>
";
}
?>
Jim 14 March, 2013
Thanks for the clear explanation & examples, just thought I'd share my experience to hopefully save a few hours of frustration for others:
I was using the Unix timestamp integer returned by strtotime('this Friday') and subtracting the number of seconds in a week (604800) to get the value for last Friday (which I have to do for the most recent five Fridays). Problem was, it just so happens that the Sunday between this Friday and last Friday is when Daylight Savings Time bumped us forward an hour, thereby making all of my "previous Friday" Unix timestamp calculations an hour off! Using strtotime('-1 weeks Friday') then -2 etc. fixed everything up nicely. Thanks again!
Rahul 13 August, 2012
When a month has five saturday's then
date('Y-m-d', strtotime( date('M Y ').'second saturday')) is giving vaule of third saturday, any idea friends ?
If the 1st of a month is Saturday then "second saturday" will return the third Saturday in that month. You need to start from the last day of the previous month to get it right in this case.
gaver 9 May, 2012
Nice article - very helpful!
Wondering if you could help me understand why the results of this code is off by one (1) for actual day of year?
echo date('z', strtotime('2012-5-9'));
// shows 129 and s/b 130?
...
I figured it out...
I don't know why they don't mention this - but the array of days of yearusing the php date(z) function begins with 0 for Jan 1, 2012.
So... Dec 31, 2012 is 365 (off by one because of leap year).
I have to pad the results by 1 to get actual calendar day of year...
shalin nathan 1 December, 2011
how to calcutate the day of the future year..and what is the main logic behind this calculation and how does it flow in that method
as if the day i want to calcute is 26 feb 2028 and today is 1 dec 2011 so what will be the day on 26 feb 2028..
It's really not as complicated as you think:
$dayofweek = date('l', strtotime('26 feb 2028')); // Saturday
Sumit Mathur 7 October, 2011
Really a great Post! Thanks. It helped me in handling such kind of date and day issues!
Richard Cummings 31 August, 2011
I may have commented here before but I keep coming back to this page when I am searching for PHP date information and it is always right on the money with the syntax I need. Thx
James Philips 30 March, 2011
Bug?
I have the code:
$tUnixTime= strtotime('second sunday may 2011');
echo $sGMTMySqlString = gmdate("Y-m-d H:i:s", $tUnixTime);
The real answer should be:
2011-05-08 04:00:00
The program is giving:
2011-05-15 04:00:00
what I am doing bad?
The following strtotime examples should explain it:
In short, 'may 2011' is already a Sunday, so the counting starts from there. What you could use instead is '30 april 2011 second Sunday' to get the value you're after.
Richard Cummings 7 March, 2011
I have just been doing some work with dates today and this page has helped me immensely. Thank you
Ian 22 February, 2011
After looking at some other methods of doing this when I came to yours I thought this couldn't possibly work...but it did! Simple script works flawlessy, thanks man will be using it in my projects!
Catherine Lea 17 February, 2011
If we have an event that is always the second Saturday in July, how many numbers will we need for banners? e.g. 2009 11th, 2010 10th, 2011 9th, which other numbers will we need?
<?PHP
for($year=2000; $year <= 2050; $year++) {
echo date('l jS F, Y', strtotime("{$year}-07-01 second Saturday")) . "<br>";
}
?>
Victor 1 February, 2011
Today is 31 January 2011.
I try to calculate the next month:
date('F',strtotime('+1 months'));
The answer is: March ???
A common problem. According to PHP, 1 month after 31 January 2011 will be 31 February. In our calendar that actually means 3 March. To avoid this you need to calculate the offset from the start of the current month.