Calcule o total de segundos em PHP DateInterval

99

Qual é a melhor maneira de calcular o número total de segundos entre duas datas? Até agora, tentei algo como:

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

No entanto, a dayspropriedade do objeto DateInterval parece estar quebrada na compilação PHP5.3 atual (pelo menos no Windows, ele sempre retorna o mesmo 6015valor). Também tentei fazer isso de uma forma que não preservasse o número de dias em cada mês (arredondados para 30), anos bissextos, 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);

Mas eu realmente não estou feliz em usar essa solução meia-boca.

Efritz
fonte
Qual é o resultado de $delta->format("%r%s")?
Warrenm
1
@warrenm O problema com formaté quando dizer que o número de segundos é 0 enquanto o número de minutos é 1, $delta->format("%r%s")acaba sendo 0 :(
Vadim Samokhin
4
Pior ainda, falando como alguém corrigindo um defeito detectado na revisão de código de um codificador que colou seu código EXATO acima - nem todo mês tem 30 dias, e nem todo ano tem 365 dias. :) [Editar: e aquele codificador pode ter sido eu mesmo!]
taiganaut

Respostas:

205

Você não poderia comparar os carimbos de hora em vez disso?

$now = new DateTime('now');
$diff = $date->getTimestamp() - $now->getTimestamp()
Ben
fonte
11
Acho que não RTFM ... Isso é o que eu estava procurando; Muito obrigado!
efritz
3
1: bonito e limpo! Observe que o getTimestamp()método está disponível em PHP> = 5.3.0.
Sk8erPeter
6
Se você estiver preso com o PHP 5.2 em seu hoster compartilhado de baixa qualidade, use em format('U')vez de getTimestamp().
chiborg
4
Sua solução não é compatível com bug de 2038
Jack M.
9
@JackM. Bom saber. Espero que tudo o que está sendo construído agora não funcione mais em 2037. Sinta-se à vontade para fornecer uma solução alternativa segura para erros do ano 2038.
Ben
34

Esta função permite que você obtenha a duração total em segundos de um objeto DateInterval

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

    return $endTime->getTimestamp() - $reference->getTimestamp();
}
dave1010
fonte
2
Deve-se notar que DateTimeImmutable está disponível apenas no PHP 5.5 ou superior.
hschmieder
Eu acho que você tem que substituir as variáveis ​​de retorno $endTimee $referenceentre si, já que isso me dá um resultado negativo com um valor de data e hora de intervalo futuro.
AlexioVay 01 de
Também não acho que o Timestamp esteja em segundos. PHP DateTime = Horrific API
Quadrivium
5

Você poderia fazer assim:

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

$differenceInSeconds = $currentTime - $timeInPast;

time () retorna a hora atual em segundos desde a época (1970-01-01T00: 00: 00), e strtotime faz o mesmo, mas com base em uma data / hora específica fornecida.

xil3
fonte
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
fonte
0

É sempre bom quando o que você precisa já está presente como uma classe. No seu caso, você precisa de um número total de segundos. Por que não fazer disso uma aula? O código pode ser assim:

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

Além de ser intuitivo, você também pode se beneficiar do recurso de preenchimento automático de seu IDE.

Para uma implementação mais útil, você pode verificar esta biblioteca .

Vadim Samokhin
fonte
-8

Você poderia simplesmente inserir os números fixos (em vez de 60 * 60 - colocar 3600) para que não seja necessário calculá-los a cada vez.

Editar - corrigiu o número com base em seu comentário.

Duniyadnd
fonte
Estaria tudo bem e provavelmente seria executado uma fração de segundo mais rápido em PHP, mas ainda me deixa com o mesmo erro de cálculo do exemplo acima.
efritz