Avatar ·

Как преобразовать секунды в формат Час:Минута:Секунда в PHP?

Всем привет! Я новичок в PHP и столкнулся с такой задачей: у меня есть переменная, которая хранит количество секунд, например 3665. Мне нужно вывести это время в читаемом формате ЧЧ:ММ:СС, то есть 1:01:05. Я пробовал просто делить на 3600, 60 и использовать остаток от деления, но у меня получается ерунда. Вот мой код: ```php ``` Проблема в том, что часы выводятся как 1.0180555555556, а минуты как 1.0833333333333. Я понимаю, что нужно округление, но если просто использовать intval, то теряются остатки. Подскажите, как правильно сделать? Нужно, чтобы часы, минуты и секунды были целыми числами, и при этом формат был с ведущими нулями (например, 01:01:05, а не 1:1:5). Заранее спасибо! <<>>

Решение с помощью деления и форматирования

Ваша основная ошибка в том, что при делении вы получаете дробные числа, так как оператор / в PHP возвращает float. Вам нужно использовать целочисленное деление (intdiv) или явно приводить результат к int. Также для красивого вывода с ведущими нулями удобно использовать функцию sprintf или str_pad. Вот правильное решение:

<?php
$seconds = 3665;

// Целочисленное деление на 3600 — получаем часы
$hours = intdiv($seconds, 3600);

// Остаток от деления на 3600 — это секунды, оставшиеся после вычитания часов
$remaining = $seconds % 3600;

// Из остатка получаем минуты (целочисленное деление на 60)
$minutes = intdiv($remaining, 60);

// Оставшиеся секунды — это остаток от деления на 60
$secs = $remaining % 60;

// Форматируем с ведущими нулями
echo sprintf("%02d:%02d:%02d", $hours, $minutes, $secs);
// Результат: 01:01:05
?>

Объяснение по шагам

  • intdiv — функция для целочисленного деления. В отличие от обычного /, она сразу возвращает целое число (int), отбрасывая дробную часть. Альтернатива: (int)($seconds / 3600) или floor($seconds / 3600).
  • Оператор % — остаток от деления. Он даёт нам то, что не делится нацело. Например, 3665 % 3600 = 65 (это секунды, оставшиеся после вычитания одного часа).
  • sprintf("%02d", ...) — форматирует число так, чтобы оно занимало минимум 2 символа, а если цифр меньше — добавляет спереди ноль. То есть 1 превращается в "01", 5 — в "05".

Альтернативный вариант с str_pad

Если по каким-то причинам не хотите использовать sprintf, можно сделать так:

<?php
$hours = intdiv($seconds, 3600);
$minutes = intdiv($seconds % 3600, 60);
$secs = $seconds % 60;

echo str_pad($hours, 2, '0', STR_PAD_LEFT) . ':' . 
     str_pad($minutes, 2, '0', STR_PAD_LEFT) . ':' . 
     str_pad($secs, 2, '0', STR_PAD_LEFT);
// Результат: 01:01:05
?>

Что делать, если секунд меньше часа?

Код корректно обработает и такие случаи. Например, для 65 секунд:

<?php
$seconds = 65;
$hours = intdiv($seconds, 3600);   // 0
$minutes = intdiv($seconds % 3600, 60); // 1
$secs = $seconds % 60;            // 5
echo sprintf("%02d:%02d:%02d", $hours, $minutes, $secs); // 00:01:05
?>

Готовое решение в виде функции

Для многократного использования рекомендую обернуть логику в функцию:

<?php
function secondsToHms(int $seconds): string {
    $hours = intdiv($seconds, 3600);
    $minutes = intdiv($seconds % 3600, 60);
    $secs = $seconds % 60;
    return sprintf("%02d:%02d:%02d", $hours, $minutes, $secs);
}

echo secondsToHms(3665); // 01:01:05
echo secondsToHms(75);   // 00:01:15
?>

Этот подход работает для любых неотрицательных целых чисел. Если нужно поддерживать отрицательные значения (например, для таймера обратного отсчёта), добавьте проверку на abs().

<<>>

Использование встроенной функции gmdate

Если не хотите писать собственную логику деления, PHP предоставляет удобную функцию gmdate, которая форматирует метку времени Unix. Однако есть нюанс: она работает только для интервалов меньше 24 часов (86400 секунд), так как даты начинаются с 00:00:00. Для больших значений часы будут обнуляться.

<?php
$seconds = 3665;
echo gmdate("H:i:s", $seconds); // 01:01:05
// Но для 90000 секунд (25 часов) выведет 01:00:00, а не 25:00:00
?>

Когда это удобно

Этот метод идеален, если ваше время гарантированно меньше 24 часов — например, для длительности видео, аудиозаписей или коротких таймеров. Код получается очень компактным и читаемым.

Решение для любого количества часов (включая >24)

Если нужно поддерживать произвольные значения, комбинируйте gmdate с ручным вычислением часов:

<?php
$seconds = 90000; // 25 часов
$hours = floor($seconds / 3600);
$remaining = $seconds % 3600;
echo sprintf("%02d:%s", $hours, gmdate("i:s", $remaining)); 
// Результат: 25:00:00
?>

Этот подход берёт часы через деление, а минуты и секунды — через gmdate, что избавляет от ручного вычисления остатков. Но для простых случаев (секунды < 86400) достаточно одного вызова gmdate.