У меня есть сценарий, который принимает значение в секундах (до 2 десятичных знаков дробных секунд):
$seconds_input = 23.75
Затем я конвертирую его в миллисекунды:
$milliseconds = $seconds_input * 1000; // --> 23750
И тогда я хочу отформатировать его так:
H:M:Sx // --> 0:0:23.75
Где «х» – это доля второго (сколько бы ни было после десятичного числа мест).
Любая помощь? Кажется, я не могу обдумать это. Я попытался использовать gmdate (), но он продолжал отрываться от дробных секунд.
Благодарю.
Мой прием
function formatSeconds( $seconds ) { $hours = 0; $milliseconds = str_replace( "0.", '', $seconds - floor( $seconds ) ); if ( $seconds > 3600 ) { $hours = floor( $seconds / 3600 ); } $seconds = $seconds % 3600; return str_pad( $hours, 2, '0', STR_PAD_LEFT ) . gmdate( ':i:s', $seconds ) . ($milliseconds ? ".$milliseconds" : '') ; }
И затем тест
$testData = array( 23 // Seconds, w/o millis , 23.75 // Seconds, w/millis , 23.75123456789 // Lots of millis , 123456789.75 // Lots of seconds ); foreach ( $testData as $seconds ) { echo formatSeconds( $seconds ), PHP_EOL; }
который дает
00:00:23 00:00:23.75 00:00:23.75123456789 34293:33:09.75
Edit: Ну, я был немного поспешным. Вот один из способов сделать то, что вы просите:
function formatMilliseconds($milliseconds) { $seconds = floor($milliseconds / 1000); $minutes = floor($seconds / 60); $hours = floor($minutes / 60); $milliseconds = $milliseconds % 1000; $seconds = $seconds % 60; $minutes = $minutes % 60; $format = '%u:%02u:%02u.%03u'; $time = sprintf($format, $hours, $minutes, $seconds, $milliseconds); return rtrim($time, '0'); }
Шахта гораздо менее читаема, поэтому она должна быть лучше. :п
В основном та же идея, что и версия ircmaxell. Он обрезает конечные «0» и даже пропустит последний ». разделитель, если миллисекунды равны 0.
<? function format_period($seconds_input) { $hours = (int)($minutes = (int)($seconds = (int)($milliseconds = (int)($seconds_input * 1000)) / 1000) / 60) / 60; return $hours.':'.($minutes%60).':'.($seconds%60).(($milliseconds===0)?'':'.'.rtrim($milliseconds%1000, '0')); } echo format_period(23.75);
если вы действительно хотите это сделать, используя функцию даты, вы правы, вам приходится иметь дело с миллисекундами извне, она основана только на секундах.
вы можете сделать что-то вроде этого:
<? $input = "23.75"; $seconds = floor($input); $date = DateTime::createFromFormat('s', floor($seconds)); $ms = ($input-$seconds); if($ms == 0) { $ms = ""; } else { $ms = ltrim($ms,"0,"); } echo $date->format('H:i:s').$ms;
но помните о переполнении часа, если ваши часы превысят 24, вы, вероятно, закончите отбрасывать дни.
в вашем случае я бы сказал, что ваш подход с полом, чтобы получить секунды, правилен, и тогда вы, вероятно, должны просто использовать модульную арифметику следующим образом:
<? $totalsecs = 86400*10; $secs = $totalsecs%60; echo "secs: $secs \n"; $minutes = ($totalsecs - $secs) % (60*60);
?> и так далее ..