Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to calculate the difference between two days as a formatted string?

Here's what I've got so far:

/**
 * Parse a duration between 2 date/times in seconds
 * and to convert that duration into a formatted string
 *
 * @param integer $time_start start time in seconds
 * @param integer $time_end   end time in seconds
 * @param string  $format     like the php strftime formatting uses %y %m %w %d %h or %i.
 * @param boolean $chop       chop off sections that have 0 values
 */
public static function FormatDateDiff($time_start = 0, $time_end = 0, $format = "%s", $chop = false) {

        if($time_start > $time_end) list($time_start, $time_end) = array($time_end, $time_start);

        list($year_start,$month_start,$day_start) = explode('-',date('Y-m-d',$time_start));
        list($year_end,$month_end,$day_end) = explode('-',date('Y-m-d',$time_end));

        $years = $year_end - $year_start;
        $months = $month_end - $month_start;
        $days = $day_start - $day_end;
        $weeks = 0;
        $hours = 0;
        $mins = 0;
        $secs = 0;

        if(mktime(0,0,0,$month_end,$day_end) < mktime(0,0,0,$month_start,$day_start)) {
            $years -= 1;
        }
        if($days < 0) {
            $months -= 1;
            $days += 30; // this is an approximation...not sure how to figure this out
        }
        if($months < 0) $months += 12;
        if(strpos($format, '%y')===false) {
            $months += $years * 12;
        }
        if(strpos($format, '%w')!==false) {
            $weeks = floor($days/7);
            $days %= 7;
        }
        echo date('Y-m-d',$time_start).' to '.date('Y-m-d',$time_end).": {$years}y {$months}m {$weeks}w {$days}d<br/>";
}

(It's incomplete and inaccurate)

I can't seem to get the math right. Naively dividing it out won't work because of leap years and differing lengths of months.

The logic also needs to change depending on the format string. For example, passing 04-Feb-2010 to 28-Jun-2011 (as unix timestamps) with format string %y year %m month %d day should output 1 year 4 month 24 day but if %y year is omitted then it needs to add 12 months to the month, i.e., output should be 16 month 24 day.

Should handle times too...but I haven't got to that yet.


None of these date_diff solutions handle weeks. And I don't know how I could hack it into date_diff, so that's not really a solution for me.

Furthermore, $diff->format doesn't do what I asked...to give the total months and days if "bigger units" are omitted. Example:

>>> $start = new DateTime('04-Feb-2010')
>>> $end = new DateTime('28-Jun-2011')
>>> $diff = $start->diff($end)
>>> $diff->format('%m months, %d days')
'4 months, 24 days'

Should be 16 months, 24 days, as I stated earlier. Please stop being so quick to close my question as a dupe before you understand it fully. If the solutions to other questions can be tweaked to solve this, fine, but please explain how, because I don't get it.

To be clear,

  • if %y is omitted, years should be rolled in the months
  • if %m is omitted, months should be rolled into the days
  • if %w is omitted, weeks should be rolled into the days
  • if %h is omitted, hours should be rolled into minutes
  • if %m is omitted, minutes should be rolled into seconds

If "smaller units" are omitted, the next biggest unit can be rounded or floored where it makes sense.

like image 270
mpen Avatar asked Jan 24 '12 19:01

mpen


People also ask

Can string format compare two dates?

We can use compareTo() function from Date class to compare the two dates. compareTo() function returns: 0 if both dates are equal. 1 if date1 comes after date2.

How do I find the difference between two string dates in Python?

Use the strptime(date_str, format) function to convert a date string into a datetime object as per the corresponding format . To get the difference between two dates, subtract date2 from date1.

How do I get the difference between two days in SQL?

To find the difference between dates, use the DATEDIFF(datepart, startdate, enddate) function. The datepart argument defines the part of the date/datetime in which you'd like to express the difference. Its value can be year , quarter , month , day , minute , etc.


1 Answers

I don't expect an accepted answer, but here is how to get date_diff to do weeks.

<?php

$january = new DateTime('2010-01-01');
$february = new DateTime('2011-02-20 3:35:28');
$interval = $february->diff($january);

$parts = $interval->format('%y %m %d %h %i %s %a');

$weeks = 0;
list($years, $months, $days, $hours, $minutes, $seconds, $total_days) = explode(' ', $parts);

if ($days >= 7) {
    $weeks = (int)($days / 7);
    $days  %= 7;
}

echo "$years years, $months months, $weeks weeks, $days days, $hours hours, $minutes minutes $seconds seconds";
// 1 years, 1 months, 2 weeks, 5 days, 3 hours, 35 minutes 28 seconds

Maybe with that you can integrate it into your function to do the rolling over and handling the user given format.

If the bigger units aren't given, you can start from the largest unit and apply them back to the next smaller unit. (i.e. 1 year 1 month with no years should add 12 back to months). If "month" isn't included in the format, then you can use the total days to handle the fact that months have different numbers of days.

like image 129
drew010 Avatar answered Sep 23 '22 17:09

drew010