Функция cot_build_friendlynumber в Cotonti
Функция cot_build_friendlynumber предназначена для генерации удобочитаемого числа с локализованными единицами измерения.
Код функции
/**
* Generic function for generating a human-readable number with localized units.
*
* @param float $number
* Input number to convert, based on the unit with size (key) 1.
* @param array $units
* Array of units as $relativesize => $unit.
* Example: array('3600' => 'hours', '60' => 'minutes', '1' => 'seconds').
* Where 'seconds' is the base unit, since it has a value of 1. Hours has a value of
* 3600, since one hour contains 3600 seconds. Values can be given as strings or integers.
* @param int $levels
* Number of levels to return.
* "3 hours 45 minutes" = 2 levels.
* @param int $decimals
* Number of decimals to show in last level.
* "2 minutes 20.5 seconds" = 2 levels, 1 decimals.
* @param mixed $round
* Number of decimals to round the last level up to, can also be negative, see round().
* Set false to disable or null to inherit from $decimals.
* @param string $smallestunit
* Key of the smallest unit to show. Any number smaller than this will return 'Less than 1 ...'.
* Effectively its a way to cut off $units at a certain key.
* @return string
*/
function cot_build_friendlynumber($number, $units, $levels = 1, $decimals = 0, $round = null, $smallestunit = null)
{
global $L;
if (!is_array($units)) return '';
$pieces = array();
// First sort from big to small
ksort($units, SORT_NUMERIC);
$units = array_reverse($units, true);
// Trim units after $smallestunit
if (array_key_exists($smallestunit, $units))
{
$offset = array_search($smallestunit, array_keys($units));
$units = array_slice($units, 0, $offset+1, true);
}
if ($number == 0)
{
// Return smallest possible unit
$units = array_reverse(array_values($units));
return cot_declension(0, $units[0]);
}
foreach ($units as $size => $expr)
{
$size = floatval($size);
if ($number >= $size)
{
$levels--;
$num = $number / $size;
$number -= floor($num) * $size;
if ($number > 0 && $levels > 0)
{
// There's more to come, so no decimals yet.
$pieces[] = cot_declension(floor($num), $expr);
}
else
{
// Last item gets decimals and rounding.
if($decimals > 0)
{
$pieces[] = cot_build_number($num, $decimals, $round). ' ' .
cot_declension($num, $expr, true, true);
}
else
{
$pieces[] = floor($num). ' ' .
cot_declension(floor($num), $expr, true, true);
}
break;
}
if ($levels == 0)
{
break;
}
}
}
if (count($pieces) == 0)
{
// Smaller than smallest possible unit
$expr = array_reverse(array_values($units));
return $L['LessThan'] . ' ' . cot_declension(1, $expr[0]);
}
return implode(' ', $pieces);
}
Подробное описание:
Параметры функции:
$number: Число для конвертации, основанное на единице измерения с размером (ключ) 1.
$units: Массив единиц измерения, где ключ - относительный размер единицы, а значение - название единицы. Пример: array('3600' => 'hours', '60' => 'minutes', '1' => 'seconds').
$levels: Количество уровней для возврата. Например, "3 hours 45 minutes" = 2 уровня.
$decimals: Количество десятичных знаков для отображения на последнем уровне.
$round: Количество десятичных знаков для округления последнего уровня. Может быть отрицательным, как в функции round(). Можно отключить, установив значение false, или наследовать от $decimals, установив null.
$smallestunit: Ключ самой маленькой единицы, которую нужно показывать. Число, меньшее этого значения, вернёт "Меньше 1 ...".
Описание работы:
Сначала единицы измерения сортируются от большего к меньшему.
Если указан параметр $smallestunit, массив единиц обрезается до этой единицы.
Если переданное число равно нулю, возвращается самая маленькая возможная единица с количеством 0.
Перебираются единицы измерения и для каждой рассчитывается количество полных единиц в переданном числе.
Последняя единица получает десятичные знаки и округление.
Если количество уровней равно нулю, цикл прерывается.
Если число меньше самой маленькой единицы, возвращается строка "Меньше 1 ..." с указанием единицы.
Пример общего использования:
$units = array(
'3600' => 'hours',
'60' => 'minutes',
'1' => 'seconds'
);
echo cot_build_friendlynumber(3670, $units, 2, 1); // Выводит "1 hour 1 minute"
Этот пример выводит удобочитаемую строку "1 hour 1 minute" для числа 3670, что эквивалентно 1 часу и 1 минуте.
Разберём функцию cot_build_friendlynumber по условиям.
Условия в функции:
Проверка, что $units - массив:
if (!is_array($units)) return '';
Если $units не является массивом, функция возвращает пустую строку.
Сортировка единиц измерения:
ksort($units, SORT_NUMERIC);
$units = array_reverse($units, true);
Сначала массив единиц измерения сортируется по ключам (размеру) в порядке возрастания, затем переворачивается, чтобы идти от больших единиц к меньшим.
Обрезка массива единиц после $smallestunit:
if (array_key_exists($smallestunit, $units))
{
$offset = array_search($smallestunit, array_keys($units));
$units = array_slice($units, 0, $offset+1, true);
}
Если ключ $smallestunit существует в массиве $units, массив обрезается до этой единицы включительно.
Обработка нулевого значения:
if ($number == 0)
{
// Возвращается самая маленькая возможная единица с количеством 0
$units = array_reverse(array_values($units));
return cot_declension(0, $units[0]);
}
Если переданное число равно нулю, возвращается строка с самой маленькой единицей и количеством 0.
Цикл по единицам измерения:
foreach ($units as $size => $expr)
Для каждой единицы измерения проверяется, сколько раз она помещается в переданном числе.
Расчёт количества полных единиц:
$num = $number / $size;
$number -= floor($num) * $size;
Расчёт количества полных единиц, вычитание этого количества из общего числа.
Добавление уровня с десятичными знаками:
if($decimals > 0)
{
$pieces[] = cot_build_number($num, $decimals, $round) . ' ' . cot_declension($num, $expr, true, true);
}
else
{
$pieces[] = floor($num) . ' ' . cot_declension(floor($num), $expr, true, true);
}
Если указано количество десятичных знаков, оно используется при добавлении уровня, иначе используется целое число.
Обработка оставшихся уровней:
if ($levels == 0)
{
break;
}
Если достигнуто заданное количество уровней, цикл прерывается.
Меньше самой маленькой единицы:
if (count($pieces) == 0)
{
// Меньше самой маленькой возможной единицы
$expr = array_reverse(array_values($units));
return $L['LessThan'] . ' ' . cot_declension(1, $expr[0]);
}
Если число меньше самой маленькой единицы, возвращается строка "Меньше 1 ..." с этой единицей.
Генерация удобочитаемого числа с локализованными единицами:
Массив единиц измерения:
* Массив единиц измерения в формате $relativesize => $unit.
* Пример: array('3600' => 'часов', '60' => 'минут', '1' => 'секунд').
Количество уровней для возврата:
* Количество уровней для возврата. Например, "3 часа 45 минут" = 2 уровня.
Количество десятичных знаков на последнем уровне:
* Количество десятичных знаков на последнем уровне. Например, "2 минуты 20,5 секунд" = 2 уровня, 1 десятичный знак.
Округление последнего уровня:
* Округление последнего уровня до указанного количества десятичных знаков. Можно использовать отрицательные значения, как в функции round().
Ключ самой маленькой единицы для отображения:
* Ключ самой маленькой единицы для отображения. Любое число меньше этого значения вернёт "Меньше 1 ...".
Этот подробный разбор и перевод комментариев помогут лучше понять логику работы функции в контексте Cotonti.
Комментарии (0)
Автор контента
Оффлайн
Administrator
Последняя авторизация: 05.07.2026 18:32
- Страница размещена: 21.01.2025 22:57
- Последнее обновление: 21.01.2025 22:57