Please note: This script was written some time ago and does have quirks and bugs. Several improved versions can be found in the comments on this post.
VBScript's "DateDiff" function is very useful, allowing you to quickly determine time intervals between customer dates. PHP, unfortunately, had no function to perform the same task. Instead, you must rely on a combination of the date() function and it's power and timestamps - not always the most effective way to handle dates and times.
With this in mind, the PHP DateDiff function below is intended to allow you to very quickly make the most of the power of PHP, and give you quick access to time interval functions. It is based upon the VBScript function of the same name, with a couple of small changes.
To use the below, call it like a normal function. There are four arguments. The first determines what you want to measure the date difference in - years, months, quarters, etc - and the allowed values of this are listed in the first few lines of the function. The next two are the dates themselves. Any valid date should work just fine. You can also use timestamps as dates, although if you do, you must set the last of the four arguments to "true". You can call it like so:
echo datediff('w', '9 July 2003', '4 March 2004', false);
Which will tell you the number of weekdays between the 9th July 2003 and the 4th of March 2004.
<?php
function datediff($interval, $datefrom, $dateto, $using_timestamps = false) {
/*
$interval can be:
yyyy - Number of full years
q - Number of full quarters
m - Number of full months
y - Difference between day numbers
(eg 1st Jan 2004 is "1", the first day. 2nd Feb 2003 is "33". The datediff is "-32".)
d - Number of full days
w - Number of full weekdays
ww - Number of full weeks
h - Number of full hours
n - Number of full minutes
s - Number of full seconds (default)
*/
if (!$using_timestamps) {
$datefrom = strtotime($datefrom, 0);
$dateto = strtotime($dateto, 0);
}
$difference = $dateto - $datefrom; // Difference in seconds
switch($interval) {
case 'yyyy': // Number of full years
$years_difference = floor($difference / 31536000);
if (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom), date("j", $datefrom), date("Y", $datefrom)+$years_difference) > $dateto) {
$years_difference--;
}
if (mktime(date("H", $dateto), date("i", $dateto), date("s", $dateto), date("n", $dateto), date("j", $dateto), date("Y", $dateto)-($years_difference+1)) > $datefrom) {
$years_difference++;
}
$datediff = $years_difference;
break;
case "q": // Number of full quarters
$quarters_difference = floor($difference / 8035200);
while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($quarters_difference*3), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
$months_difference++;
}
$quarters_difference--;
$datediff = $quarters_difference;
break;
case "m": // Number of full months
$months_difference = floor($difference / 2678400);
while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($months_difference), date("j", $dateto), date("Y", $datefrom)) < $dateto) {
$months_difference++;
}
$months_difference--;
$datediff = $months_difference;
break;
case 'y': // Difference between day numbers
$datediff = date("z", $dateto) - date("z", $datefrom);
break;
case "d": // Number of full days
$datediff = floor($difference / 86400);
break;
case "w": // Number of full weekdays
$days_difference = floor($difference / 86400);
$weeks_difference = floor($days_difference / 7); // Complete weeks
$first_day = date("w", $datefrom);
$days_remainder = floor($days_difference % 7);
$odd_days = $first_day + $days_remainder; // Do we have a Saturday or Sunday in the remainder?
if ($odd_days > 7) { // Sunday
$days_remainder--;
}
if ($odd_days > 6) { // Saturday
$days_remainder--;
}
$datediff = ($weeks_difference * 5) + $days_remainder;
break;
case "ww": // Number of full weeks
$datediff = floor($difference / 604800);
break;
case "h": // Number of full hours
$datediff = floor($difference / 3600);
break;
case "n": // Number of full minutes
$datediff = floor($difference / 60);
break;
default: // Number of full seconds (default)
$datediff = $difference;
break;
}
return $datediff;
}
?>

71 Comments
case "d": // Number of full days
$datediff = floor($difference / 86400);
Very buggy implementation, since day IS NOT a 24 hours (can be also 23 and 25 due to daylight savings).
Using this function can cause +-1 day error.
PEAR::DATE and ADODB::TIME libs have, instead, correct handling of days differences
#1, Yurik, Ukraine, 27 August 2004. Reply to this.
P.S. The same with weeks/months/quarters/years
#2, Yurik, Ukraine, 27 August 2004. Reply to this.
Your script produces a parse error!
#3, mario, Austria, 13 October 2004. Reply to this.
Hmmm, it worked fine for me. What did the error say?
#4, Dave Child, United Kingdom, 13 October 2004. Reply to this.
I'm having problems with case "w". I am gaining and losing days. Ex:
1 Feb 2004 -> 28 Feb 2004 = 21 weekdays
1 Feb 2004 -> 29 Feb 2004 = 20 weekdays.
The correct answer is actually 20 weekdays for both examples. Very buggy, but I am unsure how to fix it.
#5, Euth, United States, 1 November 2004. Reply to this.
I wrote my own script for finding weekdays in the current month. It's very straight forward. Not hard to modify to plug in your own dates.
<?
$month = date("M");
$year = date("Y");
$numdays = date("t");
$startdate = "1 ". $month." ".$year;
$enddate = $numdays." ". $month." ".$year;
$start = strtotime($startdate);
$end = strtotime($enddate);
$weekdays = "0";
while ($start <= ($end+3600)) {
if (date("D", $start) != "Sat" && date("D", $start) != "Sun") {
$weekdays++;
}
$start = ($start+86400);
}
?>
#6, Euth, United States, 2 November 2004. Reply to this.
I am having problems getting case 'n' to work. For the datefrom I use something like this (2004-11-08 13:10:04) and for dateto I use something like this (2004-11-08 13:45:37). I have tried using the timestamp set to true and set to false, but all I get returned is 0 (zero). I am just looking for the minute difference. Any suggestions, thanks!
#7, Kipp, United States, 8 November 2004. Reply to this.
if there would be a function some thing like getting "2 Years 5 Months 3 Days" kind of output, if some one get this function please mail me on this id 'vijaydchauhan@hotmail.com'
#8, ajay, India, 10 December 2004. Reply to this.
Good code but it does not display differences as negatives. If it did i could use this.
#9, ap0c, United Kingdom, 9 March 2005. Reply to this.
I am making a booking system for a hotel.Can anyone guide me how to use(if is possible) this function to fit my needs?
Or to give my any other advise...
Thanks
#10, Reginos, United Kingdom, 12 March 2005. Reply to this.
I am using this on another site to calculate ages (peoples) so I only needed the month and year calculations.
One change I made was to use only one date() call for each mktime() call, the functions previously used 6 date() calls per mktime().
eg. for quarters:
$df = explode(',', date("H,i,s,n,j,Y", $datefrom));
while (mktime($df[0], $df[1], $df[2], $df[3] + ($quarters_difference*3), $df[4], $df[5]) < $dateto) {
$months_difference++;
}
Should speed it up a little...
#11, R K Wellstead, United Kingdom, 11 April 2005. Reply to this.
GREAT! Been looking everywhere for a script that can take two dates of the mySQL format [YYYY-MM-DD HH:MM:SS] and return the difference, in whole seconds. Your script seems to work beautifully for me - although I have not tested it for bugs mentioned, such as leapyear stuff, which I don't think apply to me anyways.
Thanks for your code - and for all the other great resources on your site.
I love beer :)
#12, Simon, Australia, 27 April 2005. Reply to this.
thanks; I was starting to write this bitch for myself and I thought "man, this thing I'm carving looks suspiciously like a wheel."
#13, daniel heath, United States, 4 May 2005. Reply to this.
Thanks for posting this function. I have been annoyed by my ISP moving backwards on my MySQL date and I lost DATEDIFF() function in MySQL 4.1.1, so this fits the bill perfectly!
#14, Osiris, Brazil, 28 May 2005. Reply to this.
There is a Bug in the "Number of full quarters" calculation.
In the while clause you increment the variable $months_difference. But you should increment $quarters_difference.
Anyway, very nice script.
#15, Stefan, Switzerland, 22 September 2005. Reply to this.
Thanks so much this helped alot!
#16, atapi, United States, 1 November 2005. Reply to this.
This implementation is very wrong, especially as someone mentioned with regard to daylight savings time but especially with the difference between dates as shown in months. He used 31 days as the average days per month (='2678400', which itself is wrong since the average per year is 30.5); however, you need to calculate difference in months based on the same date of month to the same date of the next month. For dates whose variance is greater than a few years, this script will produce errors.
#17, kirk, United States, 3 November 2005. Reply to this.
terrible script, there are only 60 seconds in a minute. DO NOT USE THIS SCRIPT.
#18, Anonymous, United States, 5 January 2006. Reply to this.
I might be missing something, but how many seconds would you prefer in a minute?
On a serious note, folks, this script does need updating as there are some problems with it - notably daylight savings and leap years. An update is coming.
#19, Dave Child, United Kingdom, 5 January 2006. Reply to this.
Actually I'm going to use it for my simple web application which doesn't take into account DST and leap years :) Hope to make this work. Thanks Dave Child!
#20, Niño, Philippines, 19 January 2006. Reply to this.
How to find out the minutes difference on same date?
Ex: $datefrom = "Tue Apr 4";
$dateto = "Tue Apr 4";
#21, Phany, India, 4 April 2006. Reply to this.
Hi,
If you just want to count days between 2 unixtime stamps then why not use this:
<?php
function datediff ($start_date, $finish_date)
{
return date ("j", $finish_date) - date("j", $start_date);
}
?>
Thanks.
#22, Tapan Bhanot, India, 21 April 2006. Reply to this.
Dave: did you finished the last version of this function updated?
I would like to use it, but not sure if it still have any bugs...
Thanks.
#23, Karl, Argentina, 12 June 2006. Reply to this.
Very nice code :D thanks.
#24, Ed Rackham, United Kingdom, 21 June 2006. Reply to this.
Great code - just what i needed
Thanks!
#25, Matt Wynn, United Kingdom, 27 June 2006. Reply to this.
Nice, this is what i was looking for!
Thanks! your site is awesome, great stuff.
Nacho.
#26, Nacho, Argentina, 7 August 2006. Reply to this.
I can't believe people are still raving about this buggy script. I guess what they don't know won't hurt them. Right? .... wrong.
#27, Ray, Unknown, 20 September 2006. Reply to this.
Thanks for this function. It's very useful for my recent project. I appreciate it so much!
Cheers
#28, Dante, Indonesia, 11 November 2006. Reply to this.
If you make this change, then the daylight saving problems of your local timezone goes away.
$datefrom = strtotime($datefrom.' GMT');
$dateto = strtotime($dateto.' GMT');
#29, Bruce Leister, Australia, 14 November 2006. Reply to this.
Isnt it just a simple thing? Why sounds so complicated!!!
#30, Ted, Thailand, 10 December 2006. Reply to this.
Thank. Your function help-me.
#31, Tadeu Martins - Brazil, Unknown, 10 December 2006. Reply to this.
good stuff.. thnks! Rod
#32, Rod, United States, 14 December 2006. Reply to this.
misprint in a month case (may be in a quarter case too - not tested):
in "while" date("j", $dateto) instead date("j", $datefrom)
working code is:
case "m": // Number of full months
$months_difference = floor($difference / 2678400);
while (mktime(date("H", $datefrom), date("i", $datefrom), date("s", $datefrom), date("n", $datefrom)+($months_difference), date("j", $datefrom), date("Y", $datefrom)) < $dateto)
$months_difference++;
$months_difference--;
$datediff = $months_difference;
break;
#33, Sergey Chitalov, Russian Federation, 23 January 2007. Reply to this.
This code does NOT copy properly (IE 6). The carriage returns do not copy and must be manually reinserted upon copying into a text editor.
#34, Oxygen, Unknown, 25 January 2007. Reply to this.
I'd like to be able to use this code somehow and insert into a calendar all the days inbetween two dates.. for example, the beginning of X week and the end.. so I can fill out every day into the database.. Any clues?
#35, Paula, Unknown, 26 January 2007. Reply to this.
This code is unpasteable... probably because the background markup looks ridiculous!
#36, Matt, United States, 7 February 2007. Reply to this.
this function works great for me. i just need the seconds feature to create a unique long-id. it also works for my hidden countdown timer, too. thanks!
#37, Ruel B, Philippines, 12 April 2007. Reply to this.
Oh, great! I've been looking for this function a long time. Thanks for it. Congratulations!
#38, Alex Saueressig, Brazil, 13 April 2007. Reply to this.
Thanks for this wonderful function. It really helps to find the difference between 2 days. This is a great web site
#39, Jagar, Canada, 17 April 2007. Reply to this.
Please post the most recent version!
I don't have the knowledge or time to read through every comment / code snipet and piece my own function together.
Where can I find the latest (and correct) DateDiff function?
Ryan
#40, Ryan D. Hatch, United States, 25 April 2007. Reply to this.
Just do a sql query and capture the result. As you said, why reinvent the wheel
#41, prodigel, Romania, 24 May 2007. Reply to this.
Hi
Looks good! Very useful, good stuff. Good resources here. Thanks much!
G'night
#42, rjekolod, Hong Kong, 12 July 2007. Reply to this.
This is what exactly i needed!! Thank you very much for sharing it
#43, eval, Australia, 19 July 2007. Reply to this.
looking for this script for some time. I found another script here.
http://tinyurl.com/392hn4
but this script just calculate in days.
#44, adib, Malaysia, 23 July 2007. Reply to this.
would someone be able to apply all of the needed updates and re-release it or just post it in a comment? it would be very helpful
#45, Tom, Unknown, 27 July 2007. Reply to this.
I found the mistake in the number of weekdays case :
It's written :
$weeks_difference = floor($days_difference / 7);
Replace with :
If(abs($days_difference) >= 7) {
$weeks_difference = floor($days_difference / 7);
}
Else {
$weeks_difference = 0;
}
#46, Wreckman, France, 19 September 2007. Reply to this.
Huu, you don't find somethig more complicated ???
#47, China Landscape, China, 26 November 2007. Reply to this.
You know, I don't see why this has to be so complicated. I mean, lest we forget that the strtotime function has the ability to add or subtract any interval of time you want with its first optional parameter. So you could compare differences between dates quite easily with it.
http://us2.php.net/manual/en/function.strtotime.php
It doesn't involve parsing the dates, which consumes precious processor time, and the function runs at C-level for things you would be running at PHP-level with a function like the one used here at addedbytes.com.
#48, Super Mike, United States, 15 February 2008. Reply to this.
Check this bad boy out:
function DateComp($sDateA, $sDateB_ForInterval, $sInterval, $bUseTimeStamps = FALSE) {
$sFormat = ($bUseTimeStamps) ? 'Y-m-d H:i:s' : 'Y-m-d';
$sDateA = (($sDateA == '') || (empty($sDateA))) ? gmdate($sFormat) : $sDateA;
$dDateA = strtotime(date($sFormat, strtotime($sDateA)));
$sDateB = $sDateB_ForInterval;
$sDateB = (($sDateB == '') || (empty($sDateB))) ? gmdate($sFormat) : $sDateB;
$dDateB = strtotime(date($sFormat, strtotime($sDateB)));
$dTempDate = strtotime($sInterval, $dDateB);
return ($dTempDate > $dDateA);
}
/*
// USAGE OF DateComp:
$sDBDate = '2007-10-15 23:16:28';
$sCurrDate = gmdate('Y-m-d');
if (DateComp($sDBDate, $sCurrDate, '- 4 months')) {
echo "DB date value is older than 4 months past current date.";
} else {
echo "DB date value is newer than 4 months past current date.";
}
*/
#49, Super Mike, United States, 15 February 2008. Reply to this.
Meant the previous post to read "4 months prior to current date", not "past current date". But you get the point.
#50, Super Mike, United States, 15 February 2008. Reply to this.
So long already yet no latest update?
#51, Job, Malaysia, 1 May 2008. Reply to this.
I [desperately] need this script. Is it working? I mean, it works for me now, but I´ve read that you were going to update it because it was a bit buggy.
Is it safe now?
Thanks!!
#52, Rosamunda, Argentina, 5 July 2008. Reply to this.
Rosamunda: I'd suggest looking at the comments - several people have posted fixes and improvements to this script since it was published.
As to whether it's working ... I've not updated it since my comment above, so I would run your own tests to ensure it's ok. I don't think it's far off, but it will still be a day out for leap years and daylight savings may cause problems too.
As Super Mike pointed out above, there are almost certainly easier and more efficient ways to do this with existing PHP functionality.
#53, Dave Child, United Kingdom, 5 July 2008. Reply to this.
Great script Dave It saved my time but when you are going to provide update for existing bugs.
#54, Shariq, India, 21 August 2008. Reply to this.
This worked great and saved me a lot of time. The only change I made was to decrement the $days_remainder value when $first_day was a '0' (Sunday) and $days_remainder > 0 for the weekday calculation. Without this I was getting an extra day when $datefrom started on a Sunday. I added the following:
if ($first_day == 0 && $days_remainder > 0) {// must account for Sunday if datefrom is a Sunday
$days_remainder--;
}
just before the final value of $datediff is calculated.
#55, Don, United States, 12 September 2008. Reply to this.
wow so many comments, here goes another comment...
thanks for bearing so many comments !!!! :D
#56, khaild, Australia, 22 October 2008. Reply to this.
how to work if the dates are in the format dd/mm/yyyy.
#57, kitty, India, 16 December 2008. Reply to this.
is it better or not to floor the time to the "difference resolution" before doing this difference ? like =>
function datediff($interval, $datefrom, $dateto)
{
// IMPORTANT : $dateto and $datefrom in time format
switch($interval) {
case "d": // Number of full days
$datediff = floor($dateto/86400) - floor($datefrom/86400); // Difference in days
break;
case "h": // Number of full hours
$datediff = floor($dateto/3600) - floor($datefrom/3600); // Difference in hours
break;
case "n": // Number of full minutes
$datediff = floor($dateto/60) - floor($datefrom/60); // Difference in minutes
break;
default: // Number of full seconds (default)
$datediff = $dateto - $datefrom; // Difference in seconds
break;
}
return $datediff;
}
#58, Christian S, France, 13 January 2009. Reply to this.
This algorithm doesn't give you the exact difference.
A simple code to get the exact age of someone from it's birth date:
$date_of_birth='20-04-1978';
$t=strtotime($date_of_birth);
if(date("Y")>date("Y",$t))
{
$age=date("Y")-date("Y",$t);
if(date("m")<date("m",$t))
$age--;
else
if(date("m")==date("m",$t) and date("d")<date("d",$t))
$age--;
}
else
$age=0;
#59, Gabor Balazs, Hungary, 18 February 2009. Reply to this.
Don't trust on 'mktime'
According to http://in2.php.net/mktime
"the range of valid years was limited to 1970 through 2038. "
It wont work if the year is beyond 2038!!!
#60, Sumesh, India, 21 March 2009. Reply to this.
Just wanted to say thanks for the datediff. The normal date functions in php just didn't do it for me but yours worked great.
#61, Thomas Dilts, Sweden, 26 March 2009. Reply to this.
function Difference( $From, $To ) {
$Date1Array = explode( "-", $From );
$Date2Array = explode( "-", $To );
$Date1Greg = gregoriantojd( $Date1Array[1], $Date1Array[2], $Date1Array[0] );
$Date2Greg = gregoriantojd( $Date2Array[1], $Date2Array[2], $Date2Array[0] );
return $Date2Greg - $Date1Greg;
}
$DaysDiff = Difference( "1985-06-01", "2009-06-01" );
$Done = false;
$Years = 0;
$Days = $DaysDiff;
while ( !$Done ) {
if ( $Days > 365 ) {
$Days = $Days - 365;
$Years = $Years + 1;
}
else {
$Done = true;
}
}
$Leap = $Years % 4;
$Leap = ( $Years - $Leap ) / 4;
$Days = $Days - $Leap;
echo $Years . " " . $Days;
Solves the problem, at least the one i had. Use strtotime() to work out months from $Days if you need to.
#62, David, Cape Town, South Africa, 1 June 2009. Reply to this.
Brilliant - thanks
#63, Crispin, United Kingdom, 1 June 2009. Reply to this.
I am his(its first using direct query in its(the mysql database, isn't it mysql there is function of datediff to lessen or adds according to our desire.
But in php simply so complicated like this..
are there quicker, a few, and easy to be understood.
in mysql, example datediff(date of actually, date of comparison, number of less or in adding)
#64, Ahmad Ridwan, Indonesia, 3 June 2009. Reply to this.
Works well for me! Thanks!
#65, Sharla Hansen, United States, 5 June 2009. Reply to this.
Really a very nice function u made. it helps me a lot to find the date difference in php.
Thanks dear.
#66, Sagar, India, 14 July 2009. Reply to this.
Hey.. is there anyone out there who can help me with my problem...
I Just to get the minutes interval of two dates
ex :08-14-2009 08:00:00 and 08-14-2009 09:15:00
Pls help me with my problem im only newbie in php!
#67, Reven Sheen, Germany, 17 August 2009. Reply to this.
Has anyone conglomerated all of the "fixes" above into a nice updated function? Dave did a great job getting it going. Others have suggested fixes for DST and leap years, etc. Surely somebody has put it all together. :-)
#68, Troy Sartain, Cleveland, 8 October 2009. Reply to this.
There's functions built into PHP to easily find the difference between dates. There's no sense in creating such a long script. Just delete this tutorial, please.
#69, Erik, United States, 26 October 2009. Reply to this.
thanks ,dude, really awesome function.
I'm using it to count days.
#70, xtr3mz, PRC, 15 January 2010. Reply to this.
Several improved versions can be found in the "comments on this post". This link on your article goes to a 404
and
#69, Erik you should post an example...
#71, chillicothe, US, 14 February 2010. Reply to this.