Обчисліть загальну секунду в PHP DateInterval


99

Який найкращий спосіб розрахувати загальну кількість секунд між двома датами? Поки що я пробував щось на зразок:

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

Однак daysвластивість об'єкта DateInterval здається порушеною в поточній збірці PHP5.3 (принаймні в 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

1
@warrenm Проблема formatполягає в тому, що, скажімо, кількість секунд дорівнює 0, а кількість хвилин - 1, $delta->format("%r%s")виявляється 0 :(
Вадим Самохін

4
Що ще гірше, якщо виправляєте дефект, який потрапив у перегляд коду, від кодера, який вставив ваш EXACT-код вище - не кожен місяць має 30 днів, і не кожен рік має 365 днів. :) [Редагувати: і цим кодером, можливо, був я сам!]
тайганаут

Відповіді:


205

Не могли б ви порівняти часові позначки ?

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

11
Я думаю, я не RTFM ... Це те, що я шукав; дуже дякую!
efritz

3
+1: приємно і чисто! Зверніть увагу, що getTimestamp()метод доступний у PHP> = 5.3.0.
Sk8erPeter

6
Якщо ви застрягли в PHP 5.2 на своєму безглуздому хостері, використовуйте format('U')замість getTimestamp().
чиборг

4
Ваше рішення несумісне з помилкою 2038 року
Jack M.

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між собою, оскільки це дає мені мінусовий результат із майбутнім значенням інтервалу дати і часу.
AlexioVay

Я також не думаю, що позначка часу також в секундах. PHP DateTime = Жахливий 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;
}

0

Завжди приємно почуватися, коли те, що тобі потрібно, вже присутній як клас. У вашому випадку вам потрібна загальна кількість секунд. Чому б не зробити з цього клас? Код може виглядати так:

(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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.