PHP date_diff function returns wrong result - php

I was trying to find the number of months between two dates using date_diff() in PHP. As we all know the number of months between 2019-03-01 and 2020-01-31 is 11 months, but the following code return 10 months.
$date1=date_create("2019-03-01");
$date2=date_create("2020-01-31");
$diff=date_diff($date1,$date2);
echo $diff->format("%m months");
Output
10 months
Why this code return 1 month less?

If you need the difference in months from the beginning of the first day to the end of the last day at midnight, you can also set the end date to midnight (24h !) or add a day.
<?php
$dateStart = date_create("2019-03-01");
$dateEnd = date_create("2020-01-31");
//set Time to midnight or add a day
$dateEnd->setTime(24,0,0);
$diff = date_diff($dateStart,$dateEnd);
echo $diff->format("%m months");
//11 months
try self.

The difference is 10 months and 30 days, which is what date_diff() returns:
object(DateInterval)#3 (16) {
["y"]=>
int(0)
["m"]=>
int(10)
["d"]=>
int(30)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["f"]=>
float(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(336)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
ETA as #showdev commented above.

Related

Can you display the difference between two dates in months even if there's more than 12 in PHP? [duplicate]

This question already has answers here:
Elegant way to get the count of months between two dates?
(10 answers)
Closed 3 years ago.
I'm trying to find the difference between two dates and display it in months.
$currentDate = date_create(date('Y-m-d'));
$expiryDate = date_create('2022-12-10');
$dateDiff = date_diff($currentDate, $expiryDate);
$formattedDateDiff = $dateDiff->format('%m');
When I var_dump($formattedDateDiff) it just returns 0. Changing the $expiryDate reveals that it seems to be giving the leftover months after the years, i.e. if the expiry date was '2022-01-10', it would give 1, as there's 3 years and 1 month between now and then, whereas I want the full 37 months.
When I var_dump($dateDiff) to see what it is that I'm actually formatting, it returns the following:
object(DateInterval)#830 (16) {
["y"]=>
int(3)
["m"]=>
int(0)
["d"]=>
int(0)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["f"]=>
float(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(1096)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
So it's obviously expecting every relevant unit to be displayed, rather than just one. Is there a way to return the total number of months in the $dateDiff object, rather than just the leftover months? I could just divide the days by 30, but that seems like such a naff way around it, and wouldn't exactly be the most accurate what with differing lengths of months and such.
Cant' you just multiply the years in difference for 12?
return $dateDiff->m + ($datediff->y * 12);

PHP number of days miscalculation [duplicate]

This question already has answers here:
How to calculate the difference between two dates using PHP?
(34 answers)
Closed 5 years ago.
I have this php code to calculate number of days between current date and specific date.
<?php
$query = mysql_query("SELECT * FROM library_users LEFT JOIN students ON library_users.student_id = students.student_id LEFT JOIN books ON library_users.book_id = books.book_id WHERE library_users.student_id <> ''")or die(mysql_error());
while($library_users = mysql_fetch_array($query))
{
$datefrom = date('d-m-Y');
$dateto = $library_users['return_date'];
$datefrom = DateTime::createFromFormat('d-m-Y', $datefrom);
$dateto = DateTime::createFromFormat('d-m-Y', $dateto);
$date_dur = $datefrom->diff($dateto);
$days = $date_dur->format('%d');
}
For now the current date is 27-06-2017; when I input tomorrow's date which is 28-06-2017 I'm getting 1 day which is fine, but when I input 27-07-2017(next month) it is giving me 0 days. How can I solve this?
The problem is that you are using the %d format to get the days, but this will give you the difference in days of a month.
Use %a instead:
$days = $date_dur->format('%a');
http://php.net/manual/en/dateinterval.format.php
a ==> Total number of days as a result of a DateTime::diff()
It works as designed.
DateTime::diff() returns an object of type DateInterval.
A DateInterval object stores the interval in years and subdivisions (months, days, hours, minutes and seconds). You tell it to format() itself using the format "%d".
The %d format specifier means the number of days; not the absolute number of days in the interval but only the days of the last incomplete month.
The format to display the total number of days is "%a":
$days = $date_dur->format('%a');
dumping your object between 27-06-2017 and 27-07-2017 give me this:
object(DateInterval)#4 (15) { ["y"]=> int(0) ["m"]=> int(1) ["d"]=> int(1) ["h"]=> int(0) ["i"]=> int(0) ["s"]=> int(0) ["weekday"]=> int(0) ["weekday_behavior"]=> int(0) ["first_last_day_of"]=> int(0) ["invert"]=> int(0) ["days"]=> int(31) ["special_type"]=> int(0) ["special_amount"]=> int(0) ["have_weekday_relative"]=> int(0) ["have_special_relative"]=> int(0) }
so your are right : it gives you 0 days but 1 month (["m"]=> int(1))
You must use:
$date_dur->days
to get the real days number.
regards.

date_default_timezone_set is producing weird results, what gives?

I need to use date_default_timezone_set for my project and it all worked fine until I started using date_diff, as it is producing good and false results depending on the chosen timezone.
An example:
date_default_timezone_set('America/Los_Angeles');
$first = date_create("2016-10-01");
$last = date_create("2016-10-31");
$diff = date_diff($first, $last);
echo $diff->d;
The result is 30, which is correct.
Now, If I set the timezone to Europe:
date_default_timezone_set('Europe/London');
The result is 0.
What's going on?
If you var_dump($diff) you will see that the days has reset to zero and month has incremented to 1:
object(DateInterval)#3 (15) {
["y"]=>
int(0)
["m"]=>
int(1)
["d"]=>
int(0)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(30)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
This is probably due to the fact that London switches back from DST on the last Sunday in October. However the date difference is calculated that apparently makes it a "month" as opposed to 30 days.
You can overcome this by using the days property which is will report 30:
$first = date_create("2016-10-01");
$last = date_create("2016-10-31");
$diff = date_diff($first, $last);
echo $diff->days;

Strange DateTime::diff() result

Can somebody please explain me the result of DateTime::diff() in the following example:
$start = DateTime::createFromFormat('Y/m/d', '2013/05/11');
$end = DateTime::createFromFormat('Y/m/d', '2015/03/08');
$diff = $start->diff($end);
var_dump($diff);
exit;
Result:
object(DateInterval)#19 (15) {
["y"]=>
int(1)
["m"]=>
int(9)
["d"]=>
int(25)
["h"]=>
int(0)
["i"]=>
int(0)
["s"]=>
int(0)
["weekday"]=>
int(0)
["weekday_behavior"]=>
int(0)
["first_last_day_of"]=>
int(0)
["invert"]=>
int(0)
["days"]=>
int(666)
["special_type"]=>
int(0)
["special_amount"]=>
int(0)
["have_weekday_relative"]=>
int(0)
["have_special_relative"]=>
int(0)
}
This is what I think is happened here:
$diff->y is 1 because there is one full year between dates;
$diff->m is 9 because there are 9 full months between dates (without 2013/05 and 2015/03).
I'd like to know how number 25 is calculated. I can'f figure out where this number comes from.
I'd expect here the difference between 2013/05/11 and 2013/05/31 + 2015/03/01 and 2015/03/08, so 20 + 7 = 27. Instead I got 25.
This is what I think is happened here: $diff->y is 1 because there is one full year between dates; $diff->m is 9 because there are 9 full months between dates (without 2013/05 and 2015/03).
This assumption is correct.
I'd expect here the difference between 2013/05/11 and 2013/05/31 + 2015/03/01 + 2015/03/08, so 20 + 7 = 27.
This is rather confusingly written and it took me awhile to figure out exactly what you mean, but here's why you can't expect that ...
What difference would you expect there to be between 2013/05/11 (your original "from" date) and 2015/02/11? Exactly a year an 9 months, right?
Well, that's how it works - a full month difference is reached when the day of month matches. For the dates you've got, 2013/02/11 is the point where month difference count increases from 8 to 9, and the days start counting from that point on.
And the rest is easy - February (in that year) has 28 days, so you get (28 - 11) + 8 = 25 days.

How to compare a variable containing a date in PHP to current time to figure out time passed

How can I tell if a variable that contains a stampdate like this “2015-05-12 15:32:53” is less or more than an hour comparing it with current timestamp? Is there any good function in PHP that I can use to compare with this time format?
I have this code:
$date = date('Y-m-d h:i:s a', time()); //Current time e.g. "“2015-05-12 13:32:53”
$timetocomp; //Contains “2015-05-12 15:32:53”
My question is how I can compare them to know if 2 hours have passed or not.
Try DateTime
$timetocomp = "2015-06-27 09:10:53"; // its 2015-05-28 08:5x:xx now
$dateTimeToCompare = DateTime::createFromFormat('Y-m-d H:i:s', $timetocomp);
var_dump($dateTimeToCompare);
$dateTimeNoW = new DateTime();
$diff = $dateTimeToCompare->diff($dateTimeNoW);
if($diff->h >= 1 or $diff->d > 0 or $diff->m > 0 or $diff->y > 0) {
echo "difference of at least 1 hour";
} else {
echo "difference less than 1 hour";
}
Edit: My mistake was that I assumed $diff would contain the difference for each size, but its seperated as var_dump($diff) showed.
object(DateInterval)#3 (15) {
["y"]=> int(0)
["m"]=> int(0)
["d"]=> int(30)
["h"]=> int(0)
["i"]=> int(15)
["s"]=> int(13)
["weekday"]=> int(0)
["weekday_behavior"]=> int(0)
["first_last_day_of"]=> int(0)
["invert"]=> int(1)
["days"]=> int(30)
["special_type"]=> int(0)
["special_amount"]=> int(0)
["have_weekday_relative"]=> int(0)
["have_special_relative"]=> int(0)
}
So I updated the If-clause to also chck the days, months and years.
If you are trying to check weather string contains that format or not, try using regular expression and then try figure out the actual date and comparing.

Categories