Calcular segundos totales en PHP DateInterval

99

¿Cuál es la mejor manera de calcular el número total de segundos entre dos fechas? Hasta ahora, he intentado algo como:

$delta   = $date->diff(new DateTime('now'));
$seconds = $delta->days * 60 * 60 * 24;

Sin embargo, la dayspropiedad del objeto DateInterval parece estar rota en la compilación actual de PHP5.3 (al menos en Windows, siempre devuelve el mismo 6015valor). También intenté hacerlo de una manera que no pudiera conservar el número de días de cada mes (se redondea a 30), años bisiestos, etc.

$seconds = ($delta->s)
         + ($delta->i * 60)
         + ($delta->h * 60 * 60)
         + ($delta->d * 60 * 60 * 24)
         + ($delta->m * 60 * 60 * 24 * 30)
         + ($delta->y * 60 * 60 * 24 * 365);

Pero realmente no estoy contento con usar esta solución a medias.

Efritz
fuente
¿Cuál es el resultado $delta->format("%r%s")?
warrenm
1
@warrenm El problema con formates cuando dicen que la cantidad de segundos es 0 mientras que la cantidad de minutos es 1, $delta->format("%r%s")resulta ser 0 :(
Vadim Samokhin
4
Peor aún, hablando como alguien que ahora está arreglando un defecto detectado en la revisión del código de un codificador que pegó su código EXACTO arriba: no todos los meses tienen 30 días, y no todos los años tienen 365 días. :) [Editar: ¡y ese codificador puede haber sido yo mismo!]
taiganaut

Respuestas:

205

¿No podría comparar las marcas de tiempo ?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
fuente
11
Supongo que no RTFM ... Esto es lo que estaba buscando; ¡muchas gracias!
Efritz
3
+1: ¡agradable y limpio! Tenga en cuenta que el getTimestamp()método está disponible en PHP> = 5.3.0.
Sk8erPeter
6
Si está atascado con PHP 5.2 en su servidor compartido de mierda, use en format('U')lugar de getTimestamp().
chiborg
4
Su solución no es compatible con el error del año 2038
Jack M.
9
@JackM. Bueno saber. Espero que lo que se está construyendo ahora ya no se esté ejecutando en 2037. Siéntase libre de proporcionar una solución alternativa a prueba de errores para el año 2038.
Ben
34

Esta función le permite obtener la duración total en segundos de un objeto DateInterval

/**
 * @param DateInterval $dateInterval
 * @return int seconds
 */
function dateIntervalToSeconds($dateInterval)
{
    $reference = new DateTimeImmutable;
    $endTime = $reference->add($dateInterval);

    return $endTime->getTimestamp() - $reference->getTimestamp();
}
dave1010
fuente
2
Cabe señalar que DateTimeImmutable solo está disponible desde PHP 5.5 o superior.
hschmieder
Creo que debe reemplazar las variables de retorno $endTimey $referenceentre sí, ya que esto me da un resultado negativo con un valor de fecha y hora de intervalo futuro.
AlexioVay
Tampoco creo que la marca de tiempo esté en segundos. PHP DateTime = API horrible
Quadrivium
5

Podrías hacerlo así:

$currentTime = time();
$timeInPast = strtotime("2009-01-01 00:00:00");

$differenceInSeconds = $currentTime - $timeInPast;

time () devuelve el tiempo actual en segundos desde el tiempo de época (1970-01-01T00: 00: 00), y strtotime hace lo mismo, pero basado en una fecha / hora específica que usted proporcione.

xil3
fuente
4
static function getIntervalUnits($interval, $unit)
{
    // Day
    $total = $interval->format('%a');
    if ($unit == TimeZoneCalc::Days)
        return $total;
    //hour
    $total = ($total * 24) + ($interval->h );
    if ($unit == TimeZoneCalc::Hours)
        return $total;
    //min
    $total = ($total * 60) + ($interval->i );
    if ($unit == TimeZoneCalc::Minutes)
        return $total;  
    //sec
    $total = ($total * 60) + ($interval->s );
    if ($unit == TimeZoneCalc::Seconds)
        return $total;  

    return false;
}
pezuña
fuente
0

Siempre se siente bien cuando lo que necesitas ya está presente como clase. En su caso, necesita un número total de segundos. ¿Por qué no hacer una clase con eso? El código podría verse así:

(new TotalFullSeconds(
    new IntervalFromRange(
        new DateTimeFromISO8601String('2017-07-03T14:27:39+00:00'),
        new DateTimeFromISO8601String('2017-07-05T14:27:39+00:00')
    )
))
    ->value()

Además de ser intuitivo, también puede beneficiarse de la función de autocompletado de su IDE.

Para una implementación más útil, puede consultar esta biblioteca .

Vadim Samokhin
fuente
-8

Podrías simplemente poner los números duros (en lugar de 60 * 60 - poner 3600) para que no sea necesario calcularlos cada vez.

Editar: se corrigió el número según su comentario.

Duniyadnd
fuente
Eso estaría bien, y probablemente funcionaría una fracción de segundo más rápido en PHP, pero todavía me deja con el mismo error de cálculo que en el ejemplo anterior.
Efritz