Вычислить общее количество секунд в PHP DateInterval


101

Как лучше всего рассчитать общее количество секунд между двумя датами? До сих пор я пробовал что-то вроде:

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

Однако daysв текущей сборке PHP5.3 свойство объекта DateInterval кажется нарушенным (по крайней мере, в Windows оно всегда возвращает одно и то же 6015значение). Я также попытался сделать это таким образом, чтобы не сохранять количество дней в каждом месяце (округление до 30), високосные годы и т. Д .:

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

Но я действительно не доволен использованием этого неполноценного решения.


Что в результате $delta->format("%r%s")?
warrenm 05

1
@warrenm Проблема в formatтом, что когда говорят, что количество секунд равно 0, а количество минут равно 1, $delta->format("%r%s")оказывается 0 :(
Вадим Самохин

4
Что еще хуже, если говорить, что кто-то сейчас исправляет дефект, обнаруженный при проверке кода кодировщиком, который вставил ваш ТОЧНЫЙ код выше - не в каждом месяце 30 дней, и не в каждом году 365 дней. :) [Edit: а этим кодером мог быть я!]
тайганавт 02

Ответы:


213

Не могли бы вы вместо этого сравнить отметки времени ?

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

11
Думаю, я не RTFM ... Это то, что я искал; большое спасибо!
efritz 05

3
+1: красиво и чисто! Обратите внимание, что getTimestamp()метод доступен в PHP> = 5.3.0.
Sk8erPeter

6
Если вы застряли с PHP 5.2 на своем дерьмовом хостере с общим доступом, используйте format('U')вместо getTimestamp().
chiborg

4
Ваше решение несовместимо с ошибкой 2038 года
Джек М.

9
@JackM. Хорошо знать. Я очень надеюсь, что все, что создается сейчас, больше не будет работать в 2037 году. Не стесняйтесь предоставить альтернативное решение, безопасное для ошибок 2038 года.
Бен

34

Эта функция позволяет получить общую продолжительность в секундах из объекта DateInterval.

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

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

2
Следует отметить, что DateTimeImmutable доступен только в PHP 5.5 или выше.
hschmieder

Я думаю, вам нужно заменить возвращаемые переменные $endTimeи $referenceдруг на друга, поскольку это дает мне отрицательный результат с будущим значением интервала datetime.
AlexioVay 01

Я тоже не думаю, что метка времени в секундах. PHP DateTime = Horrific API
Quadrivium

5

Сделать это можно так:

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

$differenceInSeconds = $currentTime - $timeInPast;

time () возвращает текущее время в секундах с момента времени эпохи (1970-01-01T00: 00: 00), а strtotime делает то же самое, но в зависимости от указанной вами даты / времени.


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

-1

Всегда приятно, когда то, что тебе нужно, уже присутствует в виде класса. В вашем случае вам нужно общее количество секунд. Почему бы не сделать из этого класс? Код мог выглядеть так:

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

Помимо интуитивности, вы также можете воспользоваться функцией автозаполнения в своей среде IDE.

Для более полезной реализации вы можете проверить эту библиотеку .


-8

Вы можете просто ввести точные числа (вместо 60 * 60 - введите 3600), чтобы не приходилось вычислять их каждый раз.

Изменить - исправлено число на основе вашего комментария.


Это было бы хорошо, и он, вероятно, работал бы на долю секунды быстрее в PHP, но это все равно оставляет меня с тем же неправильным расчетом, что и в примере выше.
efritz 05
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.