Calcola i secondi totali in PHP DateInterval


99

Qual è il modo migliore per calcolare il numero totale di secondi tra due date? Finora ho provato qualcosa sulla falsariga di:

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

Tuttavia, la daysproprietà dell'oggetto DateInterval sembra essere danneggiata nell'attuale build PHP5.3 (almeno su Windows, restituisce sempre lo stesso 6015valore). Ho anche tentato di farlo in un modo che non sarebbe riuscito a preservare il numero di giorni in ogni mese (round a 30), anni bisestili, ecc:

$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);

Ma non sono davvero contento di usare questa soluzione a metà.


Qual è il risultato $delta->format("%r%s")?
warrenm

1
@warrenm Il problema formatè quando diciamo che il numero di secondi è 0 mentre il numero di minuti è 1, $delta->format("%r%s")risulta essere 0 :(
Vadim Samokhin

4
Peggio ancora, parlando come qualcuno che ora sta riparando un difetto catturato nella revisione del codice da un programmatore che ha incollato il tuo codice ESATTO sopra - non tutti i mesi hanno 30 giorni e non tutti gli anni hanno 365 giorni. :) [Modifica: e quel programmatore potrei essere stato io!]
taiganaut

Risposte:


205

Non potresti invece confrontare i timestamp ?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()

11
Immagino di non aver fatto RTFM ... Questo è quello che stavo cercando; molte grazie!
efritz

3
+1: bello e pulito! Nota che il getTimestamp()metodo è disponibile in PHP> = 5.3.0.
Sk8erPeter

6
Se sei bloccato con PHP 5.2 sul tuo schifoso hoster condiviso, usa format('U')invece di getTimestamp().
chiborg

4
La tua soluzione non è compatibile con il bug dell'anno 2038
Jack M.

9
@JackM. Buono a sapersi. Spero che tutto ciò che viene costruito ora non sia più in esecuzione nel 2037. Sentiti libero di fornire una soluzione alternativa sicura per i bug dell'anno 2038.
Ben

34

Questa funzione consente di ottenere la durata totale in secondi da un oggetto DateInterval

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

    return $endTime->getTimestamp() - $reference->getTimestamp();
}

2
Va notato che DateTimeImmutable è disponibile solo da PHP 5.5 o versioni successive.
hschmieder

Penso che devi sostituire le variabili di ritorno $endTimee $referencetra loro, poiché questo mi dà un risultato negativo con un valore datetime dell'intervallo futuro.
AlexioVay

Non credo nemmeno che il timestamp sia in secondi. PHP DateTime = Horrific API
Quadrivium

5

Potresti farlo in questo modo:

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

$differenceInSeconds = $currentTime - $timeInPast;

time () restituisce l'ora corrente in secondi dall'ora epoch (1970-01-01T00: 00: 00) e strtotime fa lo stesso, ma in base a una data / ora specifica che fornisci.


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;
}

0

È sempre bello quando ciò di cui hai bisogno è già presente in classe. Nel tuo caso, hai bisogno di un numero totale di secondi. Perché non ne fai una lezione? Il codice potrebbe essere così:

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

Oltre ad essere intuitivo, puoi anche beneficiare della funzionalità di completamento automatico del tuo IDE.

Per un'implementazione più utile, puoi controllare questa libreria .


-8

Potresti semplicemente inserire i numeri rigidi (invece di 60 * 60 - inserire 3600) in modo che non sia necessario calcolarli ogni volta.

Modifica: corretto il numero in base al tuo commento.


Andrebbe bene, e probabilmente funzionerebbe una frazione di secondo più veloce in PHP, ma mi lascia comunque con lo stesso errore di calcolo dell'esempio sopra.
efritz
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.