Question

I get a date from MySQL in "YYYY-MM-DD HH:MM:SS" format (for example "2013-05-28 12:58:24"). How do I convert such a date to readable string like "This file will expire in 2 hours 35 minutes"? Thanks in advance!

Was it helpful?

Solution

Try this:

<?php

$startDate=strtotime(date('Y-m-d H:i:s'));
$endDate = strtotime('2013-05-28 12:58:24');
function work_hours_diff($date1,$date2) {
    if ($date1>$date2) { 
        $tmp=$date1; 
        $date1=$date2; 
        $date2=$tmp; 
        unset($tmp); 
        $sign=-1; 
    } else $sign = 1;
    if ($date1==$date2) return 0;

    $days = 0;
    $working_days = array(1,2,3,4,5); // Monday-->Friday
    $working_hours = array(9, 17.5); // from 9:00 to 17:30 (8.5 hours)
    $current_date = $date1;

    $beg_h = floor($working_hours[0]); 
    $beg_m = ($working_hours[0]*60)%60;
    $end_h = floor($working_hours[1]); 
    $end_m = ($working_hours[1]*60)%60;

    //In case date1 is on same day of date2
    if (mktime(0,0,0,date('n', $date1), date('j', $date1), date('Y', $date1))==mktime(0,0,0,date('n', $date2), date('j', $date2), date('Y', $date2))) {
        //If its not working day, then return 0
        if (!in_array(date('w', $date1), $working_days)) return 0;

        $date0 = mktime($beg_h, $beg_m, 0, date('n', $date1), date('j', $date1), date('Y', $date1));
        $date3 = mktime($end_h, $end_m, 0, date('n', $date1), date('j', $date1), date('Y', $date1));

        if ($date1<$date0) {
            if ($date2<$date0) return 0;
            $date1 = $date0;
            if ($date2>$date3) $date2=$date3;
            return $date2-$date1;
        }
        if ($date1>$date3) return 0;
        if ($date2>$date3) $date2=$date3;
        return $date2-$date1;
    }

    //setup the very next first working time stamp
    if (!in_array(date('w',$current_date) , $working_days)) {
        // the current day is not a working day

        // the current time stamp is set at the beginning of the working day
        $current_date = mktime( $beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date) );

        // search for the next working day
        while ( !in_array(date('w',$current_date) , $working_days) ) {
            $current_date += 24*3600; // next day
        }
    } else {
        // check if the current timestamp is inside working hours
        $date0 = mktime( $beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date) );
        // it's before working hours, let's update it
        if ($current_date<$date0) $current_date = $date0;

        $date3 = mktime( $end_h, $end_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date) );

        if ($date3<$current_date) {
            // outch ! it's after working hours, let's find the next working day
            $current_date += 24*3600; // the day after
            // and set timestamp as the beginning of the working day
            $current_date = mktime( $beg_h, $beg_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date) );
            while ( !in_array(date('w',$current_date) , $working_days) ) {
                $current_date += 24*3600; // next day
            }
        }
    }

    // so, $current_date is now the first working timestamp available...

    // calculate the number of seconds from current timestamp to the end of the working day
    $date0 = mktime( $end_h, $end_m, 0, date('n',$current_date), date('j',$current_date), date('Y',$current_date) );
    $seconds = $date0-$current_date;

    // calculate the number of days from the current day to the end day

    $date3 = mktime( $beg_h, $beg_m, 0, date('n',$date2), date('j',$date2), date('Y',$date2) );
    while ( $current_date < $date3 ) {
        $current_date += 24*3600; // next day
        if (in_array(date('w',$current_date) , $working_days) ) $days++; // it's a working day
    }
    if ($days>0) $days--; //because we've already count the first day (in $seconds)

    // check if end's timestamp is inside working hours
    $date0 = mktime( $beg_h, $beg_m, 0, date('n',$date2), date('j',$date2), date('Y',$date2) );
    if ($date2<$date0) {
        // it's before, so nothing more !
    } else {
        // is it after ?
        $date3 = mktime( $end_h, $end_m, 0, date('n',$date2), date('j',$date2), date('Y',$date2) );
        if ($date2>$date3) $date2=$date3;
        // calculate the number of seconds from current timestamp to the final timestamp
        $tmp = $date2-$date0;
        $seconds += $tmp;
     }

    // calculate the working days in seconds
    $seconds += 3600*($working_hours[1]-$working_hours[0])*$days;

    return $sign * $seconds;
}

function seconds2human($ss) {
    $s = $ss%60;
    $m = floor(($ss%3600)/60);
    $h = floor(($ss)/3600);

    return "$h hours, $m minutes, $s seconds";
}
echo "This file will expire in  ".seconds2human(work_hours_diff($startDate,$endDate));


?>

And you will get the output as:

This file will expire in 11 hours, 3 minutes, 15 seconds

Demo Here>>

OTHER TIPS

This much simpler to achieve using PHP's DateTime classes:-

$expire = \DateTime::createFromFormat('Y-m-d H:i:s', '2013-05-28 12:58:24');
$now = new \DateTime();

$diff = $expire->diff(($now));

$result = '';

if($diff->y){
    $result .= $diff->y . ($diff->y > 1 ? ' years ' : ' year ');
}
if($diff->m){
    $result .= $diff->m . ($diff->m > 1 ? ' months ' : ' month ');
}
if($diff->d){
    $result .= $diff->d . ($diff->d > 1 ? ' days ' : ' day ');
}
if($diff->h){
    $result .= $diff->h . ($diff->h > 1 ? ' hours ' : ' hour ');
}
if($diff->i){
    $result .= $diff->i . ($diff->i > 1 ? ' minutes ' : ' minute ');
}
if($diff->s){
    $result .= $diff->s . ($diff->s > 1 ? ' seconds ' : ' second ');
}

echo "File expires in $result";

Output when I ran it:-

File expires in 16 hours 14 minutes 38 seconds
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top