Codewars: Human Readable Time
Glossary overview

Codewars: Human Readable Time

Write a function, which takes a non-negative integer (seconds) as input and returns the time in a human-readable format (HH:MM:SS)

  • HH = hours, padded to 2 digits, range: 00 – 99
  • MM = minutes, padded to 2 digits, range: 00 – 59
  • SS = seconds, padded to 2 digits, range: 00 – 59

The maximum time never exceeds 359999 (99:59:59)

You can find some examples in the test fixtures.

Я сначала хотел решить через рекурсию.

<?php

function human_readable($seconds) {

  // базовый случай
  if ($seconds < 60) {
  	$time = [];
  	$time['seconds'] = $seconds;

    return $time;
  };
  
  // в рекурсию передаем остаток секунд, сначала определяем целое к-во часов
  if ($seconds / 3600 > 1) {
    $hours = floor($seconds / 3600);
	// получаем резульат снизу, в нашем случае минуты
    $result =  human_readable($seconds - $hours * 3600);
    // добавляем наши данные в массив который пришел снизу
    $result['hours'] = $hours;

    return $result;
  }
  
  if ($seconds / 60 > 1) {
    $minutes = floor($seconds / 60);
    $result = human_readable($seconds - $minutes * 60);
    $result['minutes'] = $minutes;
    
    return $result;
  }
  
}

var_dump(human_readable(86399));
var_dump(human_readable(5));

// Output
array(3) {
  ["seconds"]=>
  float(59)
  ["minutes"]=>
  float(59)
  ["hours"]=>
  float(23)
}
array(1) {
  ["seconds"]=>
  int(5)
}

Получается на каждом шагу дописываем массив:

array(1) {
  ["seconds"]=>
  float(59)
}
array(2) {
  ["seconds"]=>
  float(59)
  ["minutes"]=>
  float(59)
}
array(3) {
  ["seconds"]=>
  float(59)
  ["minutes"]=>
  float(59)
  ["hours"]=>
  float(23)
}

Но рекурсия в этом примере все усложняет.

Более элегантное решение

function human_readable($seconds) {
    $hours = intdiv($seconds, 3600);
    $seconds %= 3600;

    $minutes = intdiv($seconds, 60);
    $seconds %= 60;

    return sprintf('%02d:%02d:%02d', $hours, $minutes, $seconds);
}
  • intdiv()— это встроенная функция в PHP (начиная с версии 7.0), предназначенная для выполнения целочисленного деления двух чисел [3]. Она делит делимое на делитель и возвращает только целую часть результата, отбрасывая остаток (дробную часть) [1, 2]. В отличие от обычного оператора/, intdiv гарантированно возвращает целое число (int`)
  • Оператор % в PHP — это арифметический оператор деления по модулю (остаток от деления). Он возвращает остаток от деления первого операнда на второй. %d — просто выводит число
    %02d — выводит число минимум из 2 цифр, добавляя нули слева
echo 10 % 3; // Выведет 1 (так как 10 = 3*3 + 1)
  • sprintf в PHP — это функция для создания отформатированных строк, которая возвращает результат (строку), а не выводит его сразу. Она позволяет вставлять переменные в шаблон, управлять их типом, точностью и форматированием, используя спецификаторы, такие как %s (строка), %d (целое число), %f (дробное число).
sprintf("У меня %d %s", 5, "яблок"); вернет строку "У меня 5 яблок".

Более короткое решение

function human_readable(int $seconds): string
{
  return sprintf('%02d:%02d:%02d', $seconds / 3600, ($seconds % 3600) / 60, $seconds % 60);
}