Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Non-Rounding Seconds to Time Function

Status
Not open for further replies.

PCHomepage

Programmer
Feb 24, 2009
609
US
I'm working on a simple function that I expected would give me HH:MM:SS.xxxxxx and it is giving the correct result in general but it is rounding off the seconds rather than showing their decimal fraction where it exists. This is a video time conversion and I thought there would be a remainder to need conversion to frames but it seems to not have any remainder. It's late and my brain is fried so maybe there will always be full seconds with no "excess" but can someone confirm or tell me what I did wrong?

Thank you.

Code:
function tsdate($seconds) {
	$hours = floor($seconds/3600);
	$remainder_1 = ($seconds % 3600);
	$minutes = floor($remainder_1 / 60);
	$seconds = ($remainder_1 % 60);

		if(strlen($hours) == 1) {
			$hours = "0".$hours;
		}

		if(strlen($minutes) == 1) {
			$minutes = "0".$minutes;
		}

		if(strlen($seconds) == 1) {
			$seconds = "0".$seconds;
		}

	return $hours.":".$minutes.":".$seconds;
}
 
If we assume that your input parameter being $seconds means you are passing the number of seconds to your function, then unless you pass a decimal number of seconds, there will never bee any remainder as you are always passing solid seconds.


You would need to pass a decimal number to get a remainder of less than a full second.



----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.

Web & Tech
 
Yes, I realized after posting that I am indeed passing fractional seconds so probably I can just remove the portion to the right of the decimal and process it separately. For example, the first one being processed is: 15.949266666667 but the function is giving only 00:00:15 so nearly a second is missing that I need to convert to video frames.

Thank you.
Don
 
Use explode on the value. Or Round off, and then subtract.



----------------------------------
Phil AKA Vacunita
----------------------------------
Ignorance is not necessarily Bliss, case in point:
Unknown has caused an Unknown Error on Unknown and must be shutdown to prevent damage to Unknown.

Web & Tech
 
I may be misunderstanding the question
Code:
function getTimeParts($secs){
 $hours = floor($secs / 3600);
 $minutes = floor( ($secs - ($hours * 3600)) / 60);
 $seconds = $secs - ($hours * 3600) - ($minutes * 60) ;
 $wholeSeconds = floor($seconds);
 $decimalSeconds = $seconds - $wholeSeconds;
 $formatted = sprintf('%s:%s:%s',($hours <= 0 ? "0$hours" : $hours), ($minutes <= 9 ? "0$minutes" : $minutes), ($seconds <=9 ? "0$seconds" : $seconds));
 return compact('hours', 'minutes', 'seconds', 'wholeSeconds', 'decimalSeconds','formatted');
}

 
Thanks. Sounds like you understood perfectly and it's certainly cleaner than my raw and messy quickie version. Since your function was outputting an array when I needed the final format as 00:00:15.xxxxxx (where the "x" is the decimal remainder), I changed it to [red]return $formatted;[/red] which to be almost exactly what's needed:

Code:
function udate($secs) {
	$hours = floor($secs / 3600);
	$minutes = floor( ($secs - ($hours * 3600)) / 60);
	$seconds = $secs - ($hours * 3600) - ($minutes * 60) ;
	$wholeSeconds = floor($seconds);
	$decimalSeconds = $seconds - $wholeSeconds;
	$formatted = sprintf('%s:%s:%s',($hours <= 0 ? "0$hours" : $hours), ($minutes <= 9 ? "0$minutes" : $minutes), ($seconds <=9 ? "0$seconds" : $seconds));
	return $formatted;
}

Now, within this function, I should be easily able to convert the remaining partial second back to frames, round it off (or pad it if needed) to three digits, and replace the decimal with a comma. The conversion is, I believe, the decimal value times the frame rate (60 or, more accurately, 59.94 but 60 is close enough) but I'm not sure about that so I'll have to experiment a bit. Since the frame rate may vary in different projects, I'll also feed it as a variable into the function.

Don
 
I've got it working to the proper format with the frames replacing the decimals but I still need a bit of help as I am unsure how to round a whole number to three places! It always needs to be three digits, padded on the left with zeros if necessary. Any ideas?

Code:
function udate($secs, $framerate = 60000) {
	$hours = floor($secs / 3600);
	$minutes = floor( ($secs - ($hours * 3600)) / 60);
	$seconds = $secs - ($hours * 3600) - ($minutes * 60) ;
	$wholeSeconds = floor($seconds);
	$decimalSeconds = $seconds - $wholeSeconds;
	$decimalpart = ($decimalSeconds - floor($decimalSeconds)) * $framerate;  
	$formatted = sprintf('%s:%s:%s,%s',($hours <= 0 ? "0$hours" : $hours), ($minutes <= 9 ? "0$minutes" : $minutes), ($wholeSeconds <=9 ? "0$wholeSeconds" : $wholeSeconds), ($decimalpart <=9 ? "00$decimalpart" : $decimalpart));

	return $formatted;
}

Sorry, I just realized I had renamed the function but it is still the same one I was talking about originally.

Don
 
Wrapping several round() functions around a "faked" decimal version of the frame value, then stripping off the decimal has ALMOST given me the proper results except that it seems to be padded with a 0 on some when it should not. In other words, some look okay with something like [red]00:00:15,057[/red] while others are not, with a value like [red]00:00:19,0372[/red]. Surely there must be a cleaner way of doing it that will give more consistent results.

The inner round() is simply rounding to a whole number any decimal values that may already exist from the calculation to frames; the outer round() has an added a decimal to the result, then rounding it to three places; the str_replace() is, of course simply removing the decimal again:

Code:
function udate($secs, $framerate = 60000) {
	$hours = floor($secs / 3600);
	$minutes = floor( ($secs - ($hours * 3600)) / 60);
	$seconds = $secs - ($hours * 3600) - ($minutes * 60) ;
	$wholeSeconds = floor($seconds);
	$decimalSeconds = $seconds - $wholeSeconds;
	$decimalpart = [b][red]str_replace(".","",round(".". round((($decimalSeconds - floor($decimalSeconds)) * $framerate),0),3));[/red][/b]  
	$formatted = sprintf('%s:%s:%s,%s',($hours <= 0 ? "0$hours" : $hours), ($minutes <= 9 ? "0$minutes" : $minutes), ($wholeSeconds <=9 ? "0$wholeSeconds" : $wholeSeconds), ($decimalpart <=9 ? "$decimalpart" : $decimalpart));

	return $formatted;
}
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top