Calculer le nombre total de secondes en PHP DateInterval

99

Quelle est la meilleure façon de calculer le nombre total de secondes entre deux dates? Jusqu'à présent, j'ai essayé quelque chose du genre:

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

Cependant, la dayspropriété de l'objet DateInterval semble être cassée dans la version actuelle de PHP5.3 (au moins sous Windows, elle renvoie toujours la même 6015valeur). J'ai également essayé de le faire d'une manière qui ne permettrait pas de conserver le nombre de jours dans chaque mois (tours à 30), les années bissextiles, 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);

Mais je ne suis vraiment pas content d'utiliser cette solution à moitié folle.

efritz
la source
Quel est le résultat $delta->format("%r%s")?
warrenm
1
@warrenm Le problème avec formatc'est quand disons que le nombre de secondes est 0 alors que le nombre de minutes est 1, $delta->format("%r%s")se révèle être 0 :(
Vadim Samokhin
4
Pire encore, parler comme quelqu'un qui corrige maintenant un défaut détecté dans la révision du code par un codeur qui a collé votre code EXACT ci-dessus - tous les mois n'ont pas 30 jours, et pas chaque année a 365 jours. :) [Edit: et ce codeur est peut-être moi-même!]
taiganaut

Réponses:

205

Ne pourriez-vous pas comparer les horodatages à la place?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
la source
11
Je suppose que je n'ai pas RTFM ... C'est ce que je cherchais; Merci beaucoup!
efritz
3
+1: agréable et propre! Notez que la getTimestamp()méthode est disponible en PHP> = 5.3.0.
Sk8erPeter
6
Si vous êtes bloqué avec PHP 5.2 sur votre hébergeur partagé merdique, utilisez à la format('U')place de getTimestamp().
chiborg
4
Votre solution n'est pas compatible avec le bug de l'année 2038
Jack M.
9
@JackM. Bon à savoir. J'espère que tout ce qui est en cours de construction ne fonctionnera plus en 2037. N'hésitez pas à fournir une solution alternative sécurisée contre les bogues de l'année 2038.
Ben
34

Cette fonction vous permet d'obtenir la durée totale en secondes d'un objet DateInterval

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

    return $endTime->getTimestamp() - $reference->getTimestamp();
}
dave1010
la source
2
Il convient de noter que DateTimeImmutable n'est disponible qu'à partir de PHP 5.5 ou supérieur.
hschmieder
Je pense que vous devez remplacer les variables de retour $endTimeet les $referenceunes avec les autres, car cela me donne un résultat négatif avec une valeur de date / heure d'intervalle futur.
AlexioVay
Je ne pense pas non plus que l’horodatage soit en secondes. PHP DateTime = Horrific API
Quadrivium
5

Vous pouvez le faire comme ceci:

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

$differenceInSeconds = $currentTime - $timeInPast;

time () renvoie l'heure actuelle en secondes depuis l'heure de l'époque (1970-01-01T00: 00: 00), et strtotime fait de même, mais en fonction d'une date / heure spécifique que vous donnez.

xil3
la source
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;
}
Hoofuz
la source
0

C'est toujours agréable lorsque ce dont vous avez besoin est déjà présent en classe. Dans votre cas, vous avez besoin d'un nombre total de secondes. Pourquoi ne pas en faire une classe? Le code pourrait ressembler à ça:

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

En plus d'être intuitif, vous pouvez également bénéficier de la fonction de saisie semi-automatique de votre IDE.

Pour une implémentation plus utile, vous pouvez consulter cette bibliothèque .

Vadim Samokhin
la source
-8

Vous pouvez simplement entrer les nombres précis (au lieu de 60 * 60 - mettez 3600) pour qu'il n'ait pas besoin de les calculer à chaque fois.

Modifier - a fixé le nombre en fonction de votre commentaire.

Duniyadnd
la source
Ce serait bien, et cela fonctionnerait probablement une fraction de seconde plus vite en PHP, mais cela me laisse toujours avec le même mauvais calcul que l'exemple ci-dessus.
efritz