Отримати інтервал секунд між двома датами в PHP?


Відповіді:


138

Ви можете використовувати strtotime () для цього:

$diff = strtotime('2009-10-05 18:11:08') - strtotime('2009-10-05 18:07:13')

Подібний підхід можливий з об'єктами DateTime, наприклад

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diff = $date2->getTimestamp() - $date->getTimestamp();

1
Примітка: Переконайтеся, що ви використовуєте велику літеру "H" протягом годин (режим 24 години), коли ваш "нижчий" час "зараз", і ви використовуєте date()для отримання дати і часу зараз ( date("Y-m-d H:i:s")).
jave.web

`` Дати у форматах m / d / y або dmy розгладжуються, дивлячись на роздільник між різними компонентами: якщо роздільник є косою рисою (/), то передбачається американський m / d / y; тоді як якщо роздільником є ​​тире (-) або крапка (.), то передбачається європейський формат dmy. Якщо, однак, рік вказано у двозначному форматі, а роздільником є ​​тире (-, рядок дати аналізується як ymd. Щоб уникнути потенційної неоднозначності, найкраще використовувати дати ISO 8601 (РРРР-ММ-ДД) або DateTime :: createFromFormat (), коли це можливо. ``
Микола Петканський,

перевірте відповідь JCM і оберіть свою справу
Леандро

158

З об'єктами DateTime ви можете зробити це так:

$date = new DateTime( '2009-10-05 18:07:13' );
$date2 = new DateTime( '2009-10-05 18:11:08' );

$diffInSeconds = $date2->getTimestamp() - $date->getTimestamp();

1
Це також враховує перехід на літній час!
Brainware

5
Це найелегантніше рішення питання. Це має бути прийнятою відповіддю.
Гіл Беркерс

1
Зауважте, що для правильного врахування переходу на літній час потрібно вказати правильний DateTimeZone. Якщо ваша система налаштована правильно, тоді php може вже знати ваш часовий пояс за замовчуванням системи. Якщо це питання, вручну інстанціюйте так: $ tz = new DateTimeZone ('Європа / Берлін'); і передайте його конструктору DateTime як другий параметр.
j4k3

відмінне рішення, але протягом довших періодів (приклад 1 година) я отримую від’ємне значення (переповнення?), будь-яка ідея, як це виправити?
Марто


4

Через обмеження епохи unix у вас можуть виникнути проблеми зі порівнянням дат до 1970 року і після 2038 року. Я вирішив втратити точність (= не дивитись ні на одну секунду), але уникати переходу через перетворення епох unix (getTimestamp). Це залежить від того, що ти робиш, щоб робити ...

У моєму випадку використання 365 замість (12 * 30) та "30" як середньої довжини місяця зменшило помилку в корисному виведенні.

function DateIntervalToSec($start,$end){ // as datetime object returns difference in seconds
    $diff = $end->diff($start);
    $diff_sec = $diff->format('%r').( // prepend the sign - if negative, change it to R if you want the +, too
                ($diff->s)+ // seconds (no errors)
                (60*($diff->i))+ // minutes (no errors)
                (60*60*($diff->h))+ // hours (no errors)
                (24*60*60*($diff->d))+ // days (no errors)
                (30*24*60*60*($diff->m))+ // months (???)
                (365*24*60*60*($diff->y)) // years (???)
                );
    return $diff_sec;
}

Зверніть увагу, що помилка може становити 0, якщо "середні" величини призначені для різниці. Документи PHP не говорять про це ... У поганому випадку помилка може бути:

  • 0 секунд, якщо різниця застосовується до проміжків часу <1 місяць
  • Від 0 до 3 днів, якщо різниця застосовується до проміжків часу> 1 місяць
  • Від 0 до 14 днів, якщо різницю застосовувати до проміжків часу> 1 рік

Я вважаю за краще припустити, що хтось вирішив вважати "m" 30 днями, а "y" 365, заряджаючи "d" з різницею, коли "diff" проходить через не 30-денні місяці ...

Якщо хтось знає щось більше про це і може надати офіційну документацію, ласкаво просимо!


Використовуйте властивість days замість властивості d, щоб отримати точні дні між двома днями. Тож ніяких неточних результатів там немає.
Nilz11,


2

Якщо вам потрібна реальна місцева різниця в часі і ви хочете працювати getTimestamp, ви повинні враховувати переходи на літній час протягом розрахункового періоду. Отже, місцеве зміщення до UTC має бути включене в рівняння.

Візьмемо, наприклад, такі дати:

$tz = new \DateTimeZone("Europe/Berlin");
$start = new \DateTime("2018-02-01 12:00:00", $tz);
$end = new \DateTime("2018-04-01 12:00:00", $tz);

$startв UTC є "2018-02-01 11:00:00", а в UTC $end- "2018-04-01 10:00:00". Зауважте, що, хоча час доби однаковий у часовому поясі Берліна, в UTC він інший. Зсув UTC становить одну годину $startі 2 години $end.

Майте на увазі, що getTimestampзавжди повертається UTC! Тому ви повинні відняти зміщення від позначки часу, коли шукаєте фактичну локальну різницю.

// WRONG! returns 5094000, one hour too much due to DST in the local TZ
echo $end->getTimestamp() - $start->getTimestamp();

// CORRECT: returns 5090400
echo ($end->getTimestamp() - $end->getOffset()) - ($start->getTimestamp() - $start->getOffset());

Ця відповідь є жахливою дезінформацією. Я просто написав свій власний тестовий кейс, щоб перевірити це, і радий, що виявляється, це просто абсолютно неправильно. 5094000% 86400 = 82800. Це повний день секунд мінус 3600 для "відсутньої години", коли годинник переходить на одну годину на межі літнього часу. Простіші тестові випадки: різниця між позначками часу між "2019-03-31 01:59:59" та "2019-03-31 03:00:01" становить 2 секунди, що є правильною сумою. Різниця між позначками часу між "2019-10-27 01:59:59" та "2019-10-27 02:00:01" становить 3602 секунди, що є правильною сумою.
j4k3

Більше інформації про це: getTimestamp і setTimestamp посилаються на часову мітку unix, яка завжди позбавлена ​​часових поясів . Ви змішуєте вільні формати часових поясів із зміщеннями часових поясів. У вашому прикладі "угода з мітками часу unix" ви шукаєте 3600 + 1 = 3720 секунд, тому що годинник набирається назад на одну годину, а не на дві.
j4k3

0

Для тих, хто турбується про обмеження використання позначок часу (тобто використання дат до 1970 року і після 2038 року), ви можете просто обчислити різницю в секундах так:

$start = new DateTime('2009-10-05 18:11:08');
$end = new DateTime('2009-10-05 18:07:13');
$diff = $end->diff($start);

$seconds = ($diff->format('%r%a') * 24 * 60 * 60)
    + $diff->h * 60 * 60
    + $diff->i * 60
    + $diff->s;

echo $seconds; // output: 235

Написав допис у блозі для тих, хто бажає читати більше.


-1

Просте і точне рішення (на прикладі коментаря Nilz11):

$hiDate = new DateTime("2310-05-22 08:33:26");
$loDate = new DateTime("1910-11-03 13:00:01");
$diff = $hiDate->diff($loDate);
$secs = ((($diff->format("%a") * 24) + $diff->format("%H")) * 60 + 
   $diff->format("%i")) * 60 + $diff->format("%s");
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.