Convierta los segundos en días, horas, minutos y segundos

92

Me gustaría convertir una variable $uptimeque es segundos, en días, horas, minutos y segundos.

Ejemplo:

$uptime = 1640467;

El resultado debe ser:

18 days 23 hours 41 minutes
Florian
fuente

Respuestas:

214

Esto se puede lograr con DateTimeclase.

Utilizar:

echo secondsToTime(1640467);
# 18 days, 23 hours, 41 minutes and 7 seconds

Función:

function secondsToTime($seconds) {
    $dtF = new \DateTime('@0');
    $dtT = new \DateTime("@$seconds");
    return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds');
}

demo

Glavić
fuente
@ Glavić ¿Cómo agregaría soporte por semana y mes a esto?
socca1157
2
Asegúrese de agregar validación a la función. if (vacío ($ segundos)) {return false;}
un codificador
4
@acoder: Creo que esta función no debería encargarse de la validación; la validación debe configurarse antes de la llamada a la función. Sin embargo, su validación sigue siendo incorrecta porque, por ejemplo, también pasará alfabeto.
Glavić
2
¿Qué @significa cuando se pasa como argumento al DateTimeconstructor?
Ivanka Todorova
4
@IvankaTodorova: el valor después @es la marca de tiempo de Unix.
Glavić
44

Esta es la función reescrita para incluir días. También cambié los nombres de las variables para que el código sea más fácil de entender ...

/** 
 * Convert number of seconds into hours, minutes and seconds 
 * and return an array containing those values 
 * 
 * @param integer $inputSeconds Number of seconds to parse 
 * @return array 
 */ 

function secondsToTime($inputSeconds) {

    $secondsInAMinute = 60;
    $secondsInAnHour  = 60 * $secondsInAMinute;
    $secondsInADay    = 24 * $secondsInAnHour;

    // extract days
    $days = floor($inputSeconds / $secondsInADay);

    // extract hours
    $hourSeconds = $inputSeconds % $secondsInADay;
    $hours = floor($hourSeconds / $secondsInAnHour);

    // extract minutes
    $minuteSeconds = $hourSeconds % $secondsInAnHour;
    $minutes = floor($minuteSeconds / $secondsInAMinute);

    // extract the remaining seconds
    $remainingSeconds = $minuteSeconds % $secondsInAMinute;
    $seconds = ceil($remainingSeconds);

    // return the final array
    $obj = array(
        'd' => (int) $days,
        'h' => (int) $hours,
        'm' => (int) $minutes,
        's' => (int) $seconds,
    );
    return $obj;
}

Fuente: CodeAid () - http://codeaid.net/php/convert-seconds-to-hours-minutes-and-seconds-(php)

Julián Moreno
fuente
Sería bueno incluir la fuente
Martin.
¿Sería tan amable de agregar días a esta función?
Knittledan
@knittledan, no parece tan :)
AO_
1
@ hsmoore.com Seguí adelante y descubrí esto $ días = piso ($ segundos / (60 * 60 * 24)); // extraer horas $ divisor_for_horas = $ segundos% (60 * 60 * 24); $ horas = piso ($ divisor_for_horas / (60 * 60));
Knittledan
1
Esto no funciona como se esperaba durante días. Debe restar ($ días * 24) de $ horas, de lo contrario, las horas de los días se contarán dos veces en $ días y $ horas. por ejemplo, ingrese 100000 => 1 día y 27 horas. Esto debería ser de 1 día y 3 horas.
finiteloop
30

Basado en la respuesta de Julián Moreno, pero cambiado para dar la respuesta como una cadena (no un arreglo), solo incluya los intervalos de tiempo requeridos y no asuma el plural.

La diferencia entre esta y la respuesta más votada es:

Por 259264segundos, este código daría

3 días, 1 minuto, 4 segundos

Por 259264segundos, la respuesta más votada (por Glavić) daría

3 días, 0 horas , 1 minuto y 4 segundos

function secondsToTime($inputSeconds) {
    $secondsInAMinute = 60;
    $secondsInAnHour = 60 * $secondsInAMinute;
    $secondsInADay = 24 * $secondsInAnHour;

    // Extract days
    $days = floor($inputSeconds / $secondsInADay);

    // Extract hours
    $hourSeconds = $inputSeconds % $secondsInADay;
    $hours = floor($hourSeconds / $secondsInAnHour);

    // Extract minutes
    $minuteSeconds = $hourSeconds % $secondsInAnHour;
    $minutes = floor($minuteSeconds / $secondsInAMinute);

    // Extract the remaining seconds
    $remainingSeconds = $minuteSeconds % $secondsInAMinute;
    $seconds = ceil($remainingSeconds);

    // Format and return
    $timeParts = [];
    $sections = [
        'day' => (int)$days,
        'hour' => (int)$hours,
        'minute' => (int)$minutes,
        'second' => (int)$seconds,
    ];

    foreach ($sections as $name => $value){
        if ($value > 0){
            $timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's');
        }
    }

    return implode(', ', $timeParts);
}

Espero que esto ayude a alguien.

Luke Cousins
fuente
1
Prefiero este porque quita la "s", de "1 hora", y, en mi caso, quería quitar los días y tener un recuento de horas grande, y este método fue muy fácil de adaptar a ese <3.
Ryan S
1
Muy agradable Luke, ¡manteniéndolo compacto y limpio!
VoidZA
19

Aquí hay una función PHP simple de 8 líneas que convierte una cantidad de segundos en una cadena legible por humanos, incluida la cantidad de meses para grandes cantidades de segundos:

Función PHP seconds2human ()

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

return "$M months, $d days, $h hours, $m minutes, $s seconds";
}
snippetsofcode
fuente
2
Simple pero eficiente. Aunque no me gustó la parte de los 'meses'.
Francisco Presencia
1
Debe incluir código en su respuesta, no un enlace a otra página. No hay forma de asegurarse de que el sitio web al que está vinculando seguirá estando allí mañana
Zachary Weixelbaum
11
gmdate("d H:i:s",1640467);

El resultado será 19 23:41:07. Cuando es solo un segundo más que el día normal, aumenta el valor del día durante 1 día. Es por eso que muestra 19. Puede explotar el resultado para sus necesidades y solucionar este problema.

Caner Saygin
fuente
También puede mejorar este código de esta manera: $uptime = gmdate("y m d H:i:s", 1640467); $uptimeDetail = explode(" ",$uptime); echo (string)($uptimeDetail[0]-70).' year(s) '.(string)($uptimeDetail[1]-1).' month(s) '.(string)($uptimeDetail[2]-1).' day(s) '.(string)$uptimeDetail[3];Esto también le dará información sobre el año y el mes.
Caner SAYGIN
Para evitar el error de +1 día, simplemente reste (24 * 60 * 60) de la marca de tiempo de origen en segundos.
andreszs
9

Aquí hay algunas respuestas muy buenas, pero ninguna de ellas cubrió mis necesidades. Me basé en la respuesta de Glavic para agregar algunas características adicionales que necesitaba;

  • No imprima ceros. Entonces, "5 minutos" en lugar de "0 horas, 5 minutos"
  • Maneje el plural correctamente en lugar de usar la forma plural de forma predeterminada.
  • Limite la salida a un número determinado de unidades; Entonces, "2 meses, 2 días" en lugar de "2 meses, 2 días, 1 hora, 45 minutos"

Puede ver una versión en ejecución del código here.

function secondsToHumanReadable(int $seconds, int $requiredParts = null)
{
    $from     = new \DateTime('@0');
    $to       = new \DateTime("@$seconds");
    $interval = $from->diff($to);
    $str      = '';

    $parts = [
        'y' => 'year',
        'm' => 'month',
        'd' => 'day',
        'h' => 'hour',
        'i' => 'minute',
        's' => 'second',
    ];

    $includedParts = 0;

    foreach ($parts as $key => $text) {
        if ($requiredParts && $includedParts >= $requiredParts) {
            break;
        }

        $currentPart = $interval->{$key};

        if (empty($currentPart)) {
            continue;
        }

        if (!empty($str)) {
            $str .= ', ';
        }

        $str .= sprintf('%d %s', $currentPart, $text);

        if ($currentPart > 1) {
            // handle plural
            $str .= 's';
        }

        $includedParts++;
    }

    return $str;
}
Ramy Nasr
fuente
1
me ayudó mucho
Manojkiran.A
Crearé la función basada en tu forma de
laravel
8

Corto, simple, confiable:

function secondsToDHMS($seconds) {
    $s = (int)$seconds;
    return sprintf('%d:%02d:%02d:%02d', $s/86400, $s/3600%24, $s/60%60, $s%60);
}
Jérémie Germain
fuente
3
Una explicación adicional sería de gran ayuda en esta respuesta, como lo que representan las constantes enteras y cómo funciona el formato de cadena con sprintf.
1
Yo haría sprintf ('% dd:% 02dh:% 02dm:% 02ds', $ s / 86400, $ s / 3600% 24, $ s / 60% 60, $ s% 60); solo para ser aún más humano (ej .: 0d: 00h: 05m: 00s). Pero probablemente la mejor solución aquí.
Ricardo Martins
6

El enfoque más simple sería crear un método que devuelva un DateInterval de DateTime :: diff del tiempo relativo en $ segundos desde el tiempo actual $ ahora que luego puede encadenar y formatear. Por ejemplo:-

public function toDateInterval($seconds) {
    return date_create('@' . (($now = time()) + $seconds))->diff(date_create('@' . $now));
}

Ahora encadena tu llamada de método a DateInterval :: formato

echo $this->toDateInterval(1640467)->format('%a days %h hours %i minutes'));

Resultado:

18 days 23 hours 41 minutes
Trent Renshaw
fuente
3

Aunque es una pregunta bastante antigua, uno puede encontrar estos útiles (no escritos para ser rápidos):

function d_h_m_s__string1($seconds)
{
    $ret = '';
    $divs = array(86400, 3600, 60, 1);

    for ($d = 0; $d < 4; $d++)
    {
        $q = (int)($seconds / $divs[$d]);
        $r = $seconds % $divs[$d];
        $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
        $seconds = $r;
    }

    return $ret;
}

function d_h_m_s__string2($seconds)
{
    if ($seconds == 0) return '0s';

    $can_print = false; // to skip 0d, 0d0m ....
    $ret = '';
    $divs = array(86400, 3600, 60, 1);

    for ($d = 0; $d < 4; $d++)
    {
        $q = (int)($seconds / $divs[$d]);
        $r = $seconds % $divs[$d];
        if ($q != 0) $can_print = true;
        if ($can_print) $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1));
        $seconds = $r;
    }

    return $ret;
}

function d_h_m_s__array($seconds)
{
    $ret = array();

    $divs = array(86400, 3600, 60, 1);

    for ($d = 0; $d < 4; $d++)
    {
        $q = $seconds / $divs[$d];
        $r = $seconds % $divs[$d];
        $ret[substr('dhms', $d, 1)] = $q;

        $seconds = $r;
    }

    return $ret;
}

echo d_h_m_s__string1(0*86400+21*3600+57*60+13) . "\n";
echo d_h_m_s__string2(0*86400+21*3600+57*60+13) . "\n";

$ret = d_h_m_s__array(9*86400+21*3600+57*60+13);
printf("%dd%dh%dm%ds\n", $ret['d'], $ret['h'], $ret['m'], $ret['s']);

resultado:

0d21h57m13s
21h57m13s
9d21h57m13s
Artur
fuente
3
function seconds_to_time($seconds){
     // extract hours
    $hours = floor($seconds / (60 * 60));

    // extract minutes
    $divisor_for_minutes = $seconds % (60 * 60);
    $minutes = floor($divisor_for_minutes / 60);

    // extract the remaining seconds
    $divisor_for_seconds = $divisor_for_minutes % 60;
    $seconds = ceil($divisor_for_seconds);

    //create string HH:MM:SS
    $ret = $hours.":".$minutes.":".$seconds;
    return($ret);
}
James Doherty
fuente
1
Te faltan días
Sam Tuke
3
function convert($seconds){
$string = "";

$days = intval(intval($seconds) / (3600*24));
$hours = (intval($seconds) / 3600) % 24;
$minutes = (intval($seconds) / 60) % 60;
$seconds = (intval($seconds)) % 60;

if($days> 0){
    $string .= "$days days ";
}
if($hours > 0){
    $string .= "$hours hours ";
}
if($minutes > 0){
    $string .= "$minutes minutes ";
}
if ($seconds > 0){
    $string .= "$seconds seconds";
}

return $string;
}

echo convert(3744000);
Madushanka Sampath
fuente
2

Solución que debe excluir valores 0 y establecer valores singulares / plurales correctos

use DateInterval;
use DateTime;

class TimeIntervalFormatter
{

    public static function fromSeconds($seconds)
    {
        $seconds = (int)$seconds;
        $dateTime = new DateTime();
        $dateTime->sub(new DateInterval("PT{$seconds}S"));
        $interval = (new DateTime())->diff($dateTime);
        $pieces = explode(' ', $interval->format('%y %m %d %h %i %s'));
        $intervals = ['year', 'month', 'day', 'hour', 'minute', 'second'];
        $result = [];
        foreach ($pieces as $i => $value) {
            if (!$value) {
                continue;
            }
            $periodName = $intervals[$i];
            if ($value > 1) {
                $periodName .= 's';
            }
            $result[] = "{$value} {$periodName}";
        }
        return implode(', ', $result);
    }
}
radzserg
fuente
1

una versión extendida de la excelente solución de Glavić , que tiene validación de enteros, soluciona el problema de 1 sy soporte adicional durante años y meses, a expensas de ser menos amigable con el análisis de computadoras en favor de ser más amigable para los humanos:

<?php
function secondsToHumanReadable(/*int*/ $seconds)/*: string*/ {
    //if you dont need php5 support, just remove the is_int check and make the input argument type int.
    if(!\is_int($seconds)){
        throw new \InvalidArgumentException('Argument 1 passed to secondsToHumanReadable() must be of the type int, '.\gettype($seconds).' given');
    }
    $dtF = new \DateTime ( '@0' );
    $dtT = new \DateTime ( "@$seconds" );
    $ret = '';
    if ($seconds === 0) {
        // special case
        return '0 seconds';
    }
    $diff = $dtF->diff ( $dtT );
    foreach ( array (
            'y' => 'year',
            'm' => 'month',
            'd' => 'day',
            'h' => 'hour',
            'i' => 'minute',
            's' => 'second' 
    ) as $time => $timename ) {
        if ($diff->$time !== 0) {
            $ret .= $diff->$time . ' ' . $timename;
            if ($diff->$time !== 1 && $diff->$time !== -1 ) {
                $ret .= 's';
            }
            $ret .= ' ';
        }
    }
    return substr ( $ret, 0, - 1 );
}

var_dump(secondsToHumanReadable(1*60*60*2+1)); -> string(16) "2 hours 1 second"

Hanshenrik
fuente
1

Se puede utilizar la clase de intervalo que he escrito. También se puede utilizar de forma opuesta.

composer require lubos/cakephp-interval

$Interval = new \Interval\Interval\Interval();

// output 2w 6h
echo $Interval->toHuman((2 * 5 * 8 + 6) * 3600);

// output 36000
echo $Interval->toSeconds('1d 2h');

Más información aquí https://github.com/LubosRemplik/CakePHP-Interval

Luboš Remplík
fuente
1

Con DateInterval :

$d1 = new DateTime();
$d2 = new DateTime();
$d2->add(new DateInterval('PT'.$timespan.'S'));

$interval = $d2->diff($d1);
echo $interval->format('%a days, %h hours, %i minutes and %s seconds');

// Or
echo sprintf('%d days, %d hours, %d minutes and %d seconds',
    $interval->days,
    $interval->h,
    $interval->i,
    $interval->s
);

// $interval->y => years
// $interval->m => months
// $interval->d => days
// $interval->h => hours
// $interval->i => minutes
// $interval->s => seconds
// $interval->days => total number of days
Zayon
fuente
0

Aquí hay un código que me gusta usar con el propósito de obtener la duración entre dos fechas. Acepta dos fechas y le da una buena respuesta estructurada en una oración.

Esta es una versión ligeramente modificada del código que se encuentra aquí .

<?php

function dateDiff($time1, $time2, $precision = 6, $offset = false) {

    // If not numeric then convert texts to unix timestamps

    if (!is_int($time1)) {
            $time1 = strtotime($time1);
    }

    if (!is_int($time2)) {
            if (!$offset) {
                    $time2 = strtotime($time2);
            }
            else {
                    $time2 = strtotime($time2) - $offset;
            }
    }

    // If time1 is bigger than time2
    // Then swap time1 and time2

    if ($time1 > $time2) {
            $ttime = $time1;
            $time1 = $time2;
            $time2 = $ttime;
    }

    // Set up intervals and diffs arrays

    $intervals = array(
            'year',
            'month',
            'day',
            'hour',
            'minute',
            'second'
    );
    $diffs = array();

    // Loop thru all intervals

    foreach($intervals as $interval) {

            // Create temp time from time1 and interval

            $ttime = strtotime('+1 ' . $interval, $time1);

            // Set initial values

            $add = 1;
            $looped = 0;

            // Loop until temp time is smaller than time2

            while ($time2 >= $ttime) {

                    // Create new temp time from time1 and interval

                    $add++;
                    $ttime = strtotime("+" . $add . " " . $interval, $time1);
                    $looped++;
            }

            $time1 = strtotime("+" . $looped . " " . $interval, $time1);
            $diffs[$interval] = $looped;
    }

    $count = 0;
    $times = array();

    // Loop thru all diffs

    foreach($diffs as $interval => $value) {

            // Break if we have needed precission

            if ($count >= $precision) {
                    break;
            }

            // Add value and interval
            // if value is bigger than 0

            if ($value > 0) {

                    // Add s if value is not 1

                    if ($value != 1) {
                            $interval.= "s";
                    }

                    // Add value and interval to times array

                    $times[] = $value . " " . $interval;
                    $count++;
            }
    }

    if (!empty($times)) {

            // Return string with times

            return implode(", ", $times);
    }
    else {

            // Return 0 Seconds

    }

    return '0 Seconds';
}

Fuente: https://gist.github.com/ozh/8169202

Mike Johanning
fuente
0

Todo en una solución. No da unidades con ceros. Solo producirá el número de unidades que especifique (3 por defecto). Bastante largo, quizás no muy elegante. Las definiciones son opcionales, pero pueden resultar útiles en un gran proyecto.

define('OneMonth', 2592000);
define('OneWeek', 604800);  
define('OneDay', 86400);
define('OneHour', 3600);    
define('OneMinute', 60);

function SecondsToTime($seconds, $num_units=3) {        
    $time_descr = array(
                "months" => floor($seconds / OneMonth),
                "weeks" => floor(($seconds%OneMonth) / OneWeek),
                "days" => floor(($seconds%OneWeek) / OneDay),
                "hours" => floor(($seconds%OneDay) / OneHour),
                "mins" => floor(($seconds%OneHour) / OneMinute),
                "secs" => floor($seconds%OneMinute),
                );  

    $res = "";
    $counter = 0;

    foreach ($time_descr as $k => $v) {
        if ($v) {
            $res.=$v." ".$k;
            $counter++;
            if($counter>=$num_units)
                break;
            elseif($counter)
                $res.=", ";             
        }
    }   
    return $res;
}

Siéntase libre de votar en contra, pero asegúrese de probarlo en su código. Puede que sea lo que necesitas.

AnDenix
fuente
0

La solución para esta que usé (volviendo a los días mientras aprendía PHP) sin ninguna función integrada:

$days = (int)($uptime/86400); //1day = 86400seconds
$rdays = (uptime-($days*86400)); 
//seconds remaining after uptime was converted into days
$hours = (int)($rdays/3600);//1hour = 3600seconds,converting remaining seconds into hours
$rhours = ($rdays-($hours*3600));
//seconds remaining after $rdays was converted into hours
$minutes = (int)($rhours/60); // 1minute = 60seconds, converting remaining seconds into minutes
echo "$days:$hours:$minutes";

Aunque esta era una pregunta antigua, los nuevos estudiantes que se encuentren con esto, pueden encontrar esta respuesta útil.

VulnerableBoy
fuente
0
a=int(input("Enter your number by seconds "))
d=a//(24*3600)   #Days
h=a//(60*60)%24  #hours
m=a//60%60       #minutes
s=a%60           #seconds
print("Days ",d,"hours ",h,"minutes ",m,"seconds ",s)
Malk Ghassan
fuente
0

Estoy editando uno de los códigos para que funcione bien cuando llegue un valor negativo. floor()La función no proporciona el recuento correcto cuando el valor es negativo. Entonces, necesitamos usar la abs()función antes de usarla en la floor()función. $inputSecondsLa variable puede ser la diferencia entre la marca de tiempo actual y la fecha requerida.

/** 
 * Convert number of seconds into hours, minutes and seconds 
 * and return an array containing those values 
 * 
 * @param integer $inputSeconds Number of seconds to parse 
 * @return array 
 */ 

function secondsToTime($inputSeconds) {

    $secondsInAMinute = 60;
    $secondsInAnHour  = 60 * $secondsInAMinute;
    $secondsInADay    = 24 * $secondsInAnHour;

    // extract days
    $days = abs($inputSeconds / $secondsInADay);
    $days = floor($days);

    // extract hours
    $hourSeconds = $inputSeconds % $secondsInADay;
    $hours = abs($hourSeconds / $secondsInAnHour);
    $hours = floor($hours);

    // extract minutes
    $minuteSeconds = $hourSeconds % $secondsInAnHour;
    $minutes = abs($minuteSeconds / $secondsInAMinute);
    $minutes = floor($minutes);

    // extract the remaining seconds
    $remainingSeconds = $minuteSeconds % $secondsInAMinute;
    $seconds = abs($remainingSeconds);
    $seconds = ceil($remainingSeconds);

    // return the final array
    $obj = array(
        'd' => (int) $days,
        'h' => (int) $hours,
        'm' => (int) $minutes,
        's' => (int) $seconds,
    );
    return $obj;
}
Thomas Mathew
fuente
0

Una variación de la respuesta de @ Glavić: esta oculta los ceros iniciales para obtener resultados más cortos y usa plurales en los lugares correctos. También elimina la precisión innecesaria (por ejemplo, si la diferencia de tiempo es superior a 2 horas, probablemente no le importe cuántos minutos o segundos).

function secondsToTime($seconds)
{
    $dtF = new \DateTime('@0');
    $dtT = new \DateTime("@$seconds");
    $dateInterval = $dtF->diff($dtT);
    $days_t = 'day';
    $hours_t = 'hour';
    $minutes_t = 'minute';
    $seconds_t = 'second';
    if ((int)$dateInterval->d > 1) {
        $days_t = 'days';
    }
    if ((int)$dateInterval->h > 1) {
        $hours_t = 'hours';
    }
    if ((int)$dateInterval->i > 1) {
        $minutes_t = 'minutes';
    }
    if ((int)$dateInterval->s > 1) {
        $seconds_t = 'seconds';
    }


    if ((int)$dateInterval->d > 0) {
        if ((int)$dateInterval->d > 1 || (int)$dateInterval->h === 0) {
            return $dateInterval->format("%a $days_t");
        } else {
            return $dateInterval->format("%a $days_t, %h $hours_t");
        }
    } else if ((int)$dateInterval->h > 0) {
        if ((int)$dateInterval->h > 1 || (int)$dateInterval->i === 0) {
            return $dateInterval->format("%h $hours_t");
        } else {
            return $dateInterval->format("%h $hours_t, %i $minutes_t");
        }
    } else if ((int)$dateInterval->i > 0) {
        if ((int)$dateInterval->i > 1 || (int)$dateInterval->s === 0) {
            return $dateInterval->format("%i $minutes_t");
        } else {
            return $dateInterval->format("%i $minutes_t, %s $seconds_t");
        }
    } else {
        return $dateInterval->format("%s $seconds_t");
    }

}
php > echo secondsToTime(60);
1 minute
php > echo secondsToTime(61);
1 minute, 1 second
php > echo secondsToTime(120);
2 minutes
php > echo secondsToTime(121);
2 minutes
php > echo secondsToTime(2000);
33 minutes
php > echo secondsToTime(4000);
1 hour, 6 minutes
php > echo secondsToTime(4001);
1 hour, 6 minutes
php > echo secondsToTime(40001);
11 hours
php > echo secondsToTime(400000);
4 days
Mike Furlender
fuente
0

No sé por qué algunas de estas respuestas son ridículamente largas o complejas. Aquí hay uno que usa la clase DateTime . Algo similar a la respuesta de radzserg. Esto solo mostrará las unidades necesarias, y los tiempos negativos tendrán el sufijo 'ago' ...

function calctime($seconds = 0) {

    $datetime1 = date_create("@0");
    $datetime2 = date_create("@$seconds");
    $interval = date_diff($datetime1, $datetime2);

    if ( $interval->y >= 1 ) $thetime[] = pluralize( $interval->y, 'year' );
    if ( $interval->m >= 1 ) $thetime[] = pluralize( $interval->m, 'month' );
    if ( $interval->d >= 1 ) $thetime[] = pluralize( $interval->d, 'day' );
    if ( $interval->h >= 1 ) $thetime[] = pluralize( $interval->h, 'hour' );
    if ( $interval->i >= 1 ) $thetime[] = pluralize( $interval->i, 'minute' );
    if ( $interval->s >= 1 ) $thetime[] = pluralize( $interval->s, 'second' );

    return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}

function pluralize($count, $text) {
    return $count . ($count == 1 ? " $text" : " ${text}s");
}

// Examples:
//    -86400 = 1 day ago
//     12345 = 3 hours 25 minutes 45 seconds
// 987654321 = 31 years 3 months 18 days 4 hours 25 minutes 21 seconds

EDITAR: Si desea condensar el ejemplo anterior para usar menos variables / espacio (a expensas de la legibilidad), aquí hay una versión alternativa que hace lo mismo:

function calctime($seconds = 0) {
    $interval = date_diff(date_create("@0"),date_create("@$seconds"));

    foreach (array('y'=>'year','m'=>'month','d'=>'day','h'=>'hour','i'=>'minute','s'=>'second') as $format=>$desc) {
        if ($interval->$format >= 1) $thetime[] = $interval->$format . ($interval->$format == 1 ? " $desc" : " {$desc}s");
    }

    return isset($thetime) ? implode(' ', $thetime) . ($interval->invert ? ' ago' : '') : NULL;
}
Jason
fuente
Es posible que desee agregar seguridad a la función calctime para proteger contra 0 segundos. El código actual arroja un error. Envuelva $thetimeen el regreso, por ejemplo,isset($thetime)
Gusano de observación de estrellas
Gracias por la sugerencia, tienes razón sobre el error (no puedo creer que me haya perdido). ¡He actualizado el código en consecuencia!
Jason
-1
foreach ($email as $temp => $value) {
    $dat = strtotime($value['subscription_expiration']); //$value come from mysql database
//$email is an array from mysqli_query()
    $date = strtotime(date('Y-m-d'));

    $_SESSION['expiry'] = (((($dat - $date)/60)/60)/24)." Days Left";
//you will get the difference from current date in days.
}

El valor de $ proviene de la base de datos. Este código está en Codeigniter. $ SESSION se utiliza para almacenar suscripciones de usuarios. es obligatorio. Lo usé en mi caso, puedes usar lo que quieras.

Tayyab Hayat
fuente
1
¿Puede agregar alguna explicación más a su código? De donde $valueviene ¿Por qué queréis introducir una sesión? ¿Cómo devuelve esto la cadena adecuada durante segundos, minutos y horas?
Nico Haase
Respuesta de @NicoHaase actualizada.
Tayyab Hayat
-2

Esta es una función que utilicé en el pasado para restar una fecha de otra relacionada con su pregunta, mi principio era obtener cuántos días, horas, minutos y segundos quedan para que un producto caduque:

$expirationDate = strtotime("2015-01-12 20:08:23");
$toDay = strtotime(date('Y-m-d H:i:s'));
$difference = abs($toDay - $expirationDate);
$days = floor($difference / 86400);
$hours = floor(($difference - $days * 86400) / 3600);
$minutes = floor(($difference - $days * 86400 - $hours * 3600) / 60);
$seconds = floor($difference - $days * 86400 - $hours * 3600 - $minutes * 60);

echo "{$days} days {$hours} hours {$minutes} minutes {$seconds} seconds";
Krazii KiiD
fuente
¿cómo obtener también el número de semanas? ejemplo: 5 segundos, 1 hora, 3 días, 2 semanas, 1 mes
Stackoverflow