Difference Date Calculation - php

i've problem with calculating difference between two dates (including the End Date) using Carbon. Here's the problem:
I'm using this code (source: danharper's answer in https://laracasts.com/discuss/channels/general-discussion/carbon-display-age-in-years-months-day?page=1) :
$dateFrom = new Carbon("2017-01-01");
$dateTo = new Carbon("2017-12-31");
$dateTo = $dateTo->addDay(); //including End Date
echo $dateFrom->diff($dateTo)->format('%y') . " year, <br>";
echo $dateFrom->diff($dateTo)->format('%m') . " month, <br>";
echo $dateFrom->diff($dateTo)->format('%d') . " day <br>";
echo "difference " . $dateFrom->diffInDays($dateTo) . " days <br>";
Scenario 1:
Let's say, $date1 = 2017-01-01 and $date2 = 2017-12-31, then it'll results:
1 year, 0 month, 0 day
difference 365 days
When i'm using date calculator in https://www.timeanddate.com/date/durationresult.html?d1=1&m1=1&y1=2017&d2=31&m2=12&y2=2017&ti=on, it'll results:
It is 365 days from the start date to the end date, end date included
Or 1 year including the end date
They resulting the same answer. BUT:
Scenario 2:
$date1 = 2017-10-01 and $date2 = 2017-12-31, then it'll results:
0 year, 3 month, 1 day
difference 92 days
Using date calculator in https://www.timeanddate.com/date/durationresult.html?d1=1&m1=10&y1=2017&d2=31&m2=12&y2=2017&ti=on, it'll results:
It is 92 days from the start date to the end date, end date included
Or 3 months including the end date
The result in timeanddate.com is exactly 3 months ONLY. Not with 1 day.
I want the result is 3 months (the timeanddate.com's answer).
How can i achieve that answer?
Or, if it can't be achieved, is there any other technique to achieve:
x months y days? (ex: 1 jan 2017 ~ 5 feb 2019 = 25 months, 5 days)
Please help me.

You can change you code like following,
$dateFrom = new Carbon("2017-01-01");
$dateTo = new Carbon("2017-12-31");
$dateTo = $dateTo->addDay(); //including End Date
$days = $dateFrom->diffInDays($dateTo);
$months = $dateFrom->diffInMonths($dateTo);
$years = $dateFrom->diffInYears($dateto);
In you code, you have measured difference many times instead of one time. Use diffInDays(), diffInMonths() and diffInYears() functions to get values of days, months and years between two dates.
Hope you understand.

Scenario 1
$start_date = new DateTime('1 Jan 2017');
$end_date = new DateTime('5 Feb 2019 +1 day');
$difference = $start_date->diff($end_date);
$year_diff = $difference->format('%y');
$months_diff = $difference->format('%m');
$total_months = $months_diff + ($year_diff * 12);
$output = $total_months . ' months ' . $difference->format('%d') . ' days';
// would output 25 months 5 days
Scenario 2
$start_date = new DateTime('2017-10-01');
$end_date = new DateTime('2017-12-31 +1 day');
$difference = $start_date->diff($end_date);
$year_diff = $difference->format('%y');
$months_diff = $difference->format('%m');
$total_months = $months_diff + ($year_diff * 12);
$output = $total_months . ' months ' . $difference->format('%d') . ' days';
// would output 3 months 1 days

Related

PHP | Calculate remaining days but taking leap years into account

small problem to calculate the remaining days of the month starting today just I write:
$today = date('Y/m/d');
$timestamp = strtotime($today);
$daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
echo $daysRemaining;
and I get the remaining days
to do a test I entered a static date for the month of February
$timestamp = strtotime('2020-02-01');
$daysRemaining = (int)date('t', $timestamp) - (int)date('j', $timestamp);
echo $daysRemaining;
the question is here how do I calculate the remaining days in the month taking into account leap years, for example in February 2020 it will have 29 days and in this way I get out of it that remain 28
Stop using the functions and start using the DateTime class!!!
This code should explain itself.
<?php
$x = new DateTime('2020-02-17'); // create your date
$y = clone $x; // copy the date
$y->modify('last day of this month'); // alter the copy to the last day
echo $x->format('d') . "\n"; // show the day of the first date
echo $y->format('d') . "\n"; // show the day of the second date
echo $y->format('d') - $x->format('d'); // show the difference between the two
Output:
17
29
12
Check it here https://3v4l.org/8ZhOb
Check the DateTime class docs here https://www.php.net/manual/en/class.datetime.php

DateTime::diff returns unexpected result

I have the following code that is returning an unexpected answer. Please let me know what's wrong.
$start_date = new DateTime('31-03-2019');
$end_date = new DateTime('01-05-2019');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";
It is returning the following output:
day: 0 month: 1
I expect the output to be:
day: 1 month: 1
This will give you one day and one month https://3v4l.org/q0T8r
$start_date = new DateTime('31-03-2019 00:00:00');
$end_date = new DateTime('01-05-2019 24:00:00');
$d = $start_date->diff($end_date);
echo "day: " . $d->d . " month: " . $d->m . "\n";
When you add 1 month to 2019-03-31, PHP will internally just increment the month value 03 to 04. The result is 2019-04-31.
As April has only 30 days, 2019-04-31 has the same meaning as 2019-05-01 has. And that's the reason, why you get one month and zero days as the result.
The DateInterval class has another handy property: days instead of m and d. It will contain the total number of days between the two dates, which equals to 31 (you have to add 31 days to 2019-03-31 to get to the 2019-05-01.
On this value you can implement your own logic, what "one month" is. If you define it as "one month = 30 days", this could be your whished result:
$start_date = new DateTime('31-03-2019');
$end_date = new DateTime('01-05-2019');
$diff = $start_date->diff($end_date);
$months = floor($diff->days / 30);
$days = $diff->days % 30;
echo "day: " . $days . " month: " . $months . "\n";

Add multiple of interval to date until date is in current year

suppose I have an initial date whose year was prior to that of the current year and I want to repeat the event every 7 days but only in the current year.
How would I find the first occurrence in the current year?
I realize I can do it with a loop like this:
$reOccurringEvent =new DateTime('2013-12-01');
$interval = new DateInterval('P7D');
while($reOccurringEvent->format('Y') < date('Y') ){
$reOccurringEvent->add($interval);
}
echo $reOccurringEvent->format('d m Y'); //05 01 2014
But it strikes me there should be a more efficient way to achieve this rather than repeatedly adding an interval to the date (it would happen many times if the initial date was some years ago).
I was hoping to be able to calculate the number of times the interval should be added and just do it a single time.
I was thinking something like:
$date = new DateTime();
$diff = $date->diff($reOccurringEvent)->days%7;
But obviously that doesn't work and I can't quite figure out the logic of how to do it.
More generically, the algorithm would be to find the number of intervals between the given date and the last day of last year. Then multiplying the interval by the number of intervals + 1 to get the first interval of the current year.
$date1="12/9/2013";
$ts1 = strtotime($date1);
$ts2 = strtotime("12/31/" . Date("Y")-1);
//get the number of seconds between the date and first of the year
$seconds_diff = $ts2 - $ts1;
echo "$seconds_diff <br>";
//get the number of days
$dayDiff=$seconds_diff/86400;
//how many intervals?
$intervalDays = "10";
//get the number of intervals from start date to last day of last year
$numIntervals = floor($dayDiff/$intervalDays);
echo $numIntervals."<br>";
//now the total intervals to get into the current year is one more interval, turn this into days
$totIntervals= ($numIntervals* $intervalDays)+$intervalDays;
//Date Time date in question
$theDt = new DateTime($date1);
//Add the intervals we calculated to the date in question, and we have the first date of the interval for the current year...
$theDt->add(new DateInterval('P' . $totIntervals. 'D'));
echo "The first date of the intreval is: " . $theDt->format('Y-m-d');
I think, if you are doing 7 day intervals, you can find out the Day of week of your initial date, and then get the first date of the current year with that day of week...
Find out day of week: How to find the day of week from a date using PHP?
Find out date with that day of week for this year: Getting first weekday in a month with strtotime
Putting it together:
$date=Date("2/8/2012");
//Get the day of week for the date in question
$dayOfWeek = date('l', strtotime($date));
echo "The day of week for the given date is: $dayOfWeek <br>";
//Get the current year
$thisYear = date("Y");
echo "This year: $thisYear <br>";
//Create a date with the first occurence of the day of week of the given date for the current year
$firstOccurenceThisYear = date("m/d/y", strtotime("January " .$thisYear ." " . $dayOfWeek));
echo "The first interval of the year is: $firstOccurenceThisYear";
/*
Output:
This year: 2014
The day of week for the given date is: Wednesday
The first interval of the year is: 01/01/14
*/
Here is a slightly modified version of #Dan's second answer which worked well for me.
Benchmarks shown below.
$date="1985-02-18";
$intervalDays = "5";
//original version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$interval = new DateInterval("P{$intervalDays}D");
while ($dt1->format('Y') < date('Y')) {
$dt1->add($interval);
}
echo $dt1->format('d m Y') . '<br>';
echo microtime(true)-$benchMark.'<br>';
//new version
$benchMark = microtime(true);
$dt1 = new DateTime($date);
$dt2 = new DateTime("12/31/" . ((int) Date("Y") - 1));
$dayDiff = $dt1->diff($dt2)->days;
$numIntervals = floor($dayDiff / $intervalDays);
$totIntervals = ($numIntervals * $intervalDays) + $intervalDays;
$dt1->add(new DateInterval('P' . $totIntervals . 'D'));
echo $dt1->format('d m Y').'<br>';
echo microtime(true)-$benchMark.'<br>';
exit;
output
02 01 2014
0.0145111083984
02 01 2014
0.000123977661133

date_diff returns 0 if the difference is over a year

I am using this function to get month difference between two dates.
$interval = date_diff(date_create('2015-10-08'), date_create('2014-10-10'));
$total_months = $interval->format('%m');
RESULT: 11 (That's Correct!)
But, When the difference is over a year, then,
$interval = date_diff(date_create('2015-11-08'), date_create('2014-10-10'));
$total_months = $interval->format('%m');
RESULT: 0 (That's Wrong!)
why is it returns 0? Is there any way by which I can get difference between any 2 dates? Thanks!
2015-11-08 to 2014-10-10 is 12 months become a year. So it returns 0 month. Calculate the number of years from the $interval then add (year * 12) to the number of months. Example here...
$interval = date_diff(date_create('2015-11-08'), date_create('2014-10-10'));
$year = $interval->format('%Y');
echo $total_months = $interval->format('%m') + $year * 12;
Or better:
$total_months = $interval->y * 12 + $interval->m;
You have years and months as fields, no need to use format to obtain parts as texts for later adding the parts!
It is a bit tricky and needs a work round , try the following, that could
be it.
$first = new DateTime('2015-11-08',new DateTimeZone('America/New_York'));
$second = new DateTime('2014-10-10',new DateTimeZone('America/New_York'));
$diff = $second->diff($first);
$months = (Int)($diff->days/30);
echo "The two dates have $months months between them.";
Output:The two dates have 13 months between them.

PHP get date after one week and calculate the number of days left

I have a dynamic date, now what i want is that finding the date after exact one week, i have achieved that with the code below, but now i want that now many days are left for that week after date to come. i have got some sort of time stamp, but i don't know how to convert it to DAYS LEFT.
$weekDate = date( "d/m/Y", strtotime("19-05-2014") + 86400 * 7 );
echo $weekDate;// THATS PERFECT
////////////////////////////////////////////////////////////////
$future = strtotime( $weekDate ); //Future date.
$datediff = time() - $future;
$days = floor( ( ( $datediff / 24 ) / 60 ) / 60 ); //this is not perfect, returns some
sort of timestamp
I have tried other methods which are fine, but if week completes on 26, and today is 25th it gives me 0 days left, but it should say 1 day left. please help me.
In your $date_diff now is less than the future date thats why its zero. Inside strtotime() function, you can directly put a relative date inside. In this case, for one week you can use +1 week or +7 days. Consider this example:
$next_week = date('d/m/Y', strtotime('19-05-2014 +1 week')); // 26/05/2014
$next_week = strtotime('19-05-2014 +7 days');
$difference = $next_week - time(); // next weeks date minus todays date
$difference = date('j', $difference);
echo $difference . (($difference > 1) ? ' days ' : ' day ') . ' left';
// should output: 1 day left
Alright. I did something. Here's the code
$startDate = strtotime("19-05-2014");
$endDate = $startDate + 604800;
$diff = ($endDate - time()) / 60 / 60 / 24;
if ($diff < 1 && $diff > 0) {
$days = 1;
} else {
$days = floor($diff);
}
echo $days;
The problem you have with getting "1 day" if the date is tomorrow is the floor method. strtotime() gives you the time at 0 a.m. if you don't set it by your own. Because of that the difference between now and tomorrow is less than 1 which is 0 if you floor that. I created an if-clause for that.
But that will give you "1 day" for today and "1 day" for yesterday (last 2 days before the final date). If you want that better, you have to specify time in your initial date (19-05-2014).
Use DateTime for date and time calculations.
$weekDate = new \DateTime('+ 1 week');
$future = new \DateTime('+ 3 days');
$daysLeft = $weekDate->diff($future)->days;
echo $daysLeft; //4
See it working.
Reference http://php.net/datetime

Categories