Я хотел бы конвертировать переменную $uptime
которая составляет секунды, в дни, часы, минуты и секунды.
Пример:
$uptime = 1640467;
Результат должен быть:
18 days 23 hours 41 minutes
Этого можно достичь с помощью класса DateTime
Использование:
echo secondsToTime(1640467); # 18 days, 23 hours, 41 minutes and 7 seconds
Функция:
function secondsToTime($seconds) { $dtF = new \DateTime('@0'); $dtT = new \DateTime("@$seconds"); return $dtF->diff($dtT)->format('%a days, %h hours, %i minutes and %s seconds'); }
демонстрация
Это функция, переписанная для включения дней. Я также изменил имена переменных, чтобы сделать код более понятным …
/** * Convert number of seconds into hours, minutes and seconds * and return an array containing those values * * @param integer $inputSeconds Number of seconds to parse * @return array */ function secondsToTime($inputSeconds) { $secondsInAMinute = 60; $secondsInAnHour = 60 * $secondsInAMinute; $secondsInADay = 24 * $secondsInAnHour; // extract days $days = floor($inputSeconds / $secondsInADay); // extract hours $hourSeconds = $inputSeconds % $secondsInADay; $hours = floor($hourSeconds / $secondsInAnHour); // extract minutes $minuteSeconds = $hourSeconds % $secondsInAnHour; $minutes = floor($minuteSeconds / $secondsInAMinute); // extract the remaining seconds $remainingSeconds = $minuteSeconds % $secondsInAMinute; $seconds = ceil($remainingSeconds); // return the final array $obj = array( 'd' => (int) $days, 'h' => (int) $hours, 'm' => (int) $minutes, 's' => (int) $seconds, ); return $obj; }
Источник: CodeAid () – http://codeaid.net/php/convert-seconds-to-hours-minutes-and-seconds-(php)
Здесь это простая 8-строчная PHP-функция, которая преобразует несколько секунд в удобочитаемую строку, включая количество месяцев в течение большого количества секунд:
Функция PHP seconds2human ()
Основываясь на ответе Джулиана Морено, но изменился, чтобы дать ответ в виде строки (а не массива), включить только промежутки времени и не принимать множественное число.
Разница между этим и самым высоким проголосовавшим ответом:
За 259264
секунд этот код даст
3 дня, 1 минута, 4 секунды
В течение 259264
секунд самый высокий 259264
ответ (по Главичу) дал бы
3 дня, 0 часов , 1 минута с и 4 секунды
function secondsToTime($inputSeconds) { $secondsInAMinute = 60; $secondsInAnHour = 60 * $secondsInAMinute; $secondsInADay = 24 * $secondsInAnHour; // Extract days $days = floor($inputSeconds / $secondsInADay); // Extract hours $hourSeconds = $inputSeconds % $secondsInADay; $hours = floor($hourSeconds / $secondsInAnHour); // Extract minutes $minuteSeconds = $hourSeconds % $secondsInAnHour; $minutes = floor($minuteSeconds / $secondsInAMinute); // Extract the remaining seconds $remainingSeconds = $minuteSeconds % $secondsInAMinute; $seconds = ceil($remainingSeconds); // Format and return $timeParts = []; $sections = [ 'day' => (int)$days, 'hour' => (int)$hours, 'minute' => (int)$minutes, 'second' => (int)$seconds, ]; foreach ($sections as $name => $value){ if ($value > 0){ $timeParts[] = $value. ' '.$name.($value == 1 ? '' : 's'); } } return implode(', ', $timeParts); }
Я надеюсь, что это помогает кому-то.
gmdate("d H:i:s",1640467);
Результат будет 19 23:41:07. Когда это на одну секунду больше, чем обычный день, увеличивается значение дня на 1 день. Вот почему он показывает 19. Вы можете взорвать результат для своих нужд и исправить это.
Хотя это довольно старый вопрос – можно найти эти полезные (не написанные быстро):
function d_h_m_s__string1($seconds) { $ret = ''; $divs = array(86400, 3600, 60, 1); for ($d = 0; $d < 4; $d++) { $q = (int)($seconds / $divs[$d]); $r = $seconds % $divs[$d]; $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1)); $seconds = $r; } return $ret; } function d_h_m_s__string2($seconds) { if ($seconds == 0) return '0s'; $can_print = false; // to skip 0d, 0d0m .... $ret = ''; $divs = array(86400, 3600, 60, 1); for ($d = 0; $d < 4; $d++) { $q = (int)($seconds / $divs[$d]); $r = $seconds % $divs[$d]; if ($q != 0) $can_print = true; if ($can_print) $ret .= sprintf("%d%s", $q, substr('dhms', $d, 1)); $seconds = $r; } return $ret; } function d_h_m_s__array($seconds) { $ret = array(); $divs = array(86400, 3600, 60, 1); for ($d = 0; $d < 4; $d++) { $q = $seconds / $divs[$d]; $r = $seconds % $divs[$d]; $ret[substr('dhms', $d, 1)] = $q; $seconds = $r; } return $ret; } echo d_h_m_s__string1(0*86400+21*3600+57*60+13) . "\n"; echo d_h_m_s__string2(0*86400+21*3600+57*60+13) . "\n"; $ret = d_h_m_s__array(9*86400+21*3600+57*60+13); printf("%dd%dh%dm%ds\n", $ret['d'], $ret['h'], $ret['m'], $ret['s']);
результат:
0d21h57m13s 21h57m13s 9d21h57m13s
function seconds_to_time($seconds){ // extract hours $hours = floor($seconds / (60 * 60)); // extract minutes $divisor_for_minutes = $seconds % (60 * 60); $minutes = floor($divisor_for_minutes / 60); // extract the remaining seconds $divisor_for_seconds = $divisor_for_minutes % 60; $seconds = ceil($divisor_for_seconds); //create string HH:MM:SS $ret = $hours.":".$minutes.":".$seconds; return($ret); }
Самый простой подход – создать метод, который возвращает DateInterval из DateTime :: diff относительного времени в $ секундах от текущего времени $ now, которое вы затем можете связать и форматировать. Например:-
public function toDateInterval($seconds) { return date_create('@' . (($now = time()) + $seconds))->diff(date_create('@' . $now)); }
Теперь создайте цепочку вызовов метода DateInterval :: format
echo $this->toDateInterval(1640467)->format('%a days %h hours %i minutes'));
Результат:
18 days 23 hours 41 minutes
расширенная версия превосходного решения Glavić , имеющая целую валидацию, решение 1-й проблемы и дополнительную поддержку в течение многих лет и месяцев, за счет того, что компьютерный синтаксический анализ менее дружелюбен в пользу более дружелюбного человека:
<?php function secondsToHumanReadable(/*int*/ $seconds)/*: string*/ { //if you dont need php5 support, just remove the is_int check and make the input argument type int. if(!\is_int($seconds)){ throw new \InvalidArgumentException('Argument 1 passed to secondsToHumanReadable() must be of the type int, '.\gettype($seconds).' given'); } $dtF = new \DateTime ( '@0' ); $dtT = new \DateTime ( "@$seconds" ); $ret = ''; if ($seconds === 0) { // special case return '0 seconds'; } $diff = $dtF->diff ( $dtT ); foreach ( array ( 'y' => 'year', 'm' => 'month', 'd' => 'day', 'h' => 'hour', 'i' => 'minute', 's' => 'second' ) as $time => $timename ) { if ($diff->$time !== 0) { $ret .= $diff->$time . ' ' . $timename; if ($diff->$time !== 1 && $diff->$time !== -1 ) { $ret .= 's'; } $ret .= ' '; } } return substr ( $ret, 0, - 1 ); }
var_dump(secondsToHumanReadable(1*60*60*2+1));
-> string(16) "2 hours 1 second"
Короткие, простые, надежные:
function secondsToDHMS($seconds) { $s = (int)$seconds; return sprintf('%d:%02d:%02d:%02d', $s/86400, $s/3600%24, $s/60%60, $s%60); }
Решение, которое должно исключать 0 значений и устанавливать правильные значения единственного числа / множественного числа
use DateInterval; use DateTime; class TimeIntervalFormatter { public static function fromSeconds($seconds) { $seconds = (int)$seconds; $dateTime = new DateTime(); $dateTime->sub(new DateInterval("PT{$seconds}S")); $interval = (new DateTime())->diff($dateTime); $pieces = explode(' ', $interval->format('%y %m %d %h %i %s')); $intervals = ['year', 'month', 'day', 'hour', 'minute', 'second']; $result = []; foreach ($pieces as $i => $value) { if (!$value) { continue; } $periodName = $intervals[$i]; if ($value > 1) { $periodName .= 's'; } $result[] = "{$value} {$periodName}"; } return implode(', ', $result); } }
Вот код, который мне нравится использовать для получения продолжительности между двумя датами. Он принимает две даты и дает вам хороший структурированный ответ.
Это немного измененная версия кода, найденного здесь .
<?php function dateDiff($time1, $time2, $precision = 6, $offset = false) { // If not numeric then convert texts to unix timestamps if (!is_int($time1)) { $time1 = strtotime($time1); } if (!is_int($time2)) { if (!$offset) { $time2 = strtotime($time2); } else { $time2 = strtotime($time2) - $offset; } } // If time1 is bigger than time2 // Then swap time1 and time2 if ($time1 > $time2) { $ttime = $time1; $time1 = $time2; $time2 = $ttime; } // Set up intervals and diffs arrays $intervals = array( 'year', 'month', 'day', 'hour', 'minute', 'second' ); $diffs = array(); // Loop thru all intervals foreach($intervals as $interval) { // Create temp time from time1 and interval $ttime = strtotime('+1 ' . $interval, $time1); // Set initial values $add = 1; $looped = 0; // Loop until temp time is smaller than time2 while ($time2 >= $ttime) { // Create new temp time from time1 and interval $add++; $ttime = strtotime("+" . $add . " " . $interval, $time1); $looped++; } $time1 = strtotime("+" . $looped . " " . $interval, $time1); $diffs[$interval] = $looped; } $count = 0; $times = array(); // Loop thru all diffs foreach($diffs as $interval => $value) { // Break if we have needed precission if ($count >= $precision) { break; } // Add value and interval // if value is bigger than 0 if ($value > 0) { // Add s if value is not 1 if ($value != 1) { $interval.= "s"; } // Add value and interval to times array $times[] = $value . " " . $interval; $count++; } } if (!empty($times)) { // Return string with times return implode(", ", $times); } else { // Return 0 Seconds } return '0 Seconds'; }
Источник: https://gist.github.com/ozh/8169202
Все в одном решении. Не дает единиц с нулями. Будет производиться только количество единиц, которые вы укажете (по умолчанию – 3). Довольно долго, возможно, не очень элегантно. Определения являются необязательными, но могут пригодиться в большом проекте.
define('OneMonth', 2592000); define('OneWeek', 604800); define('OneDay', 86400); define('OneHour', 3600); define('OneMinute', 60); function SecondsToTime($seconds, $num_units=3) { $time_descr = array( "months" => floor($seconds / OneMonth), "weeks" => floor(($seconds%OneMonth) / OneWeek), "days" => floor(($seconds%OneWeek) / OneDay), "hours" => floor(($seconds%OneDay) / OneHour), "mins" => floor(($seconds%OneHour) / OneMinute), "secs" => floor($seconds%OneMinute), ); $res = ""; $counter = 0; foreach ($time_descr as $k => $v) { if ($v) { $res.=$v." ".$k; $counter++; if($counter>=$num_units) break; elseif($counter) $res.=", "; } } return $res; }
Не стесняйтесь проголосовать, но обязательно попробуйте его в своем коде. Это может быть просто то, что вам нужно.
Можно использовать класс интервала, который я написал. Его можно использовать и наоборот.
composer require lubos/cakephp-interval $Interval = new \Interval\Interval\Interval(); // output 2w 6h echo $Interval->toHuman((2 * 5 * 8 + 6) * 3600); // output 36000 echo $Interval->toSeconds('1d 2h');
Дополнительная информация здесь https://github.com/LubosRemplik/CakePHP-Interval
Это функция, которую я использовал в прошлом для вычитания даты из другой, связанной с вашим вопросом, мой принцип состоял в том, чтобы узнать, сколько дней, часов и секунд осталось до истечения срока действия продукта:
$expirationDate = strtotime("2015-01-12 20:08:23"); $toDay = strtotime(date('Ymd H:i:s')); $difference = abs($toDay - $expirationDate); $days = floor($difference / 86400); $hours = floor(($difference - $days * 86400) / 3600); $minutes = floor(($difference - $days * 86400 - $hours * 3600) / 60); $seconds = floor($difference - $days * 86400 - $hours * 3600 - $minutes * 60); echo "{$days} days {$hours} hours {$minutes} minutes {$seconds} seconds";