Time Counter (seconds to 0:00:00)

Here’s a snippet of code that should help anyone dealing in seconds. So far I’ve only been able to convert times that are less than a day long, but I hope to get it up to weeks, months, and years. It shouldn’t be that difficult, but checking the math might be a pain. The reason I made this is because when you return MP3 track information using the mdls command, it will give you only seconds. Enjoy.


to timeConvert(inputSeconds)
	if inputSeconds is less than 10 then
		return ("00:0" & inputSeconds) as string
	else if inputSeconds is less than 60 then --less than 60 seconds
		return ("00:" & inputSeconds) as string
	else if inputSeconds is less than 600 then --less than 10 minutes
		set theMinutes to inputSeconds div 60
		set theSeconds to inputSeconds mod 60
		if theSeconds is less than 10 then
			set theSeconds to ("0" & theSeconds) as string
		end if
		return ("0" & theMinutes & ":" & theSeconds) as string --minutes will also be < 10
	else if inputSeconds is less than 3600 then --less than one hour
		set theMinutes to (inputSeconds div 60)
		set theSeconds to inputSeconds mod 60
		if theSeconds is less than 10 then
			set theSeconds to ("0" & theSeconds) as string
		end if
		return (theMinutes & ":" & theSeconds) as string --no formatting needed for minutes
	else if inputSeconds is less than 86400 then --1 day
		set theMinutes to (inputSeconds div 60) --total minutes
		set theSeconds to (inputSeconds mod 60)
		set theHours to (theMinutes div 60)
		set theMinutes to (theMinutes mod 60)
		if theSeconds is less than 10 then
			set theSeconds to ("0" & theSeconds) as string
		end if
		if theMinutes is less than 10 then
			set theMinutes to ("0" & theMinutes) as string
		end if
		return (theHours & ":" & theMinutes & ":" & theSeconds) as string
	else
		return 0
	end if
end timeConvert

set timeCounter to timeConvert(1500)

Running this snippet should return “25:00” – 25 minutes.

Hi, psolin.

Welcome to MacScripter and thanks for posting your solution. (You haven’t changed the original variable name in the “less than 10 minutes” section!)

If you’re interested, AppleScript has some constants you may find handy: ‘weeks’, ‘days’, ‘hours’, and ‘minutes’. Their values are the number of seconds in those time periods. So for instance:

2 * minutes --> 120

Months and years don’t have fixed lengths, so there are no constants for them and you won’t be able to realise your ambition to include them without reference to specific dates.

With a couple of lists and a couple of repeats, you could get rid of all the 'else if’s:


on timeConvert(inputSeconds)
	set theWeeks to inputSeconds div weeks
	set theDays to inputSeconds mod weeks div days
	set theHours to inputSeconds mod days div hours
	set theMinutes to inputSeconds mod hours div minutes
	set theSeconds to inputSeconds mod minutes
	
	set theFigures to {theWeeks, theDays, theHours, theMinutes, theSeconds}
	set figureCount to (count theFigures)
	set theOutput to {}
	repeat with i from 1 to figureCount - 2 -- Find the first non-zero figure before the minutes, if any.
		set thisFigure to item i of theFigures
		if (thisFigure > 0) then -- If found, insert this figure into the output list as is and stop the search.
			set end of theOutput to thisFigure
			exit repeat
		end if
	end repeat
	repeat with i from (i + 1) to figureCount -- Pad the remaining figures to 2 digits each and append them to the output.
		set end of theOutput to text 2 thru 3 of ((100 + (item i of theFigures)) as text)
	end repeat
	
	set astid to AppleScript's text item delimiters -- Coerce the output list to colon-delimited text.
	set AppleScript's text item delimiters to ":"
	set theOutput to theOutput as text
	set AppleScript's text item delimiters to astid
	
	return theOutput
end timeConvert

set timeCounter to timeConvert(weeks + days + 1500) --> "1:01:00:25:00"

This will do the same and have a fixed notation, Now you don’t even need a repeat and only 1 if statement


timeConvert(7200)

on timeConvert(tis) --tis: time in seconds
	set theSeconds to tis mod 60
	set theMinutes to tis div 60
	set theHours to theMinutes div 60 as string
	set theMinutes to theMinutes mod 60
	if length of theHours is 1 then --only the hours is infinte so it can be more than two decimals.
		set theHours to "0" & theHours
	end if
	theHours & ":" & characters -2 thru -1 of ("00" & theMinutes as string) & ":" & characters -2 thru -1 of ("00" & theSeconds as string) as string
end timeConvert
theHours & ":" & text -2 thru -1 of ("0" & theMinutes) & ":" & text -2 thru -1 of ("0" & theSeconds)

:wink:

Much better Nigel, I had a little too much coercions in it. The double zero is something personal. I like the idea when notating number like this (with a fixed width) to use exact the same numbers as the fixed width. So when the variable is “” it still doesn’t throw an error. I know it’s not possible in this case but sometimes things are getting routine work instead of thinking about it, like in this case.

Maybe it should throw an error if the variable’s “”. :slight_smile:

My preferred leading zero method (for widths up to eight digits) is the one I used in post #2 above, which substitutes a simple mathematical operation for a text concatenation ” more efficient:

theHours & ":" & text 2 thru 3 of ((100 + theMinutes) as text) & ":" & text 2 thru 3 of ((100 + theSeconds) as text)

In fact, with yet another mathematical operator, the two coercions to text can be done in one:

tell ((10000 + theMinutes * 100 + theSeconds) as text) to return theHours & ":" & text 2 thru 3 & ":" & text 4 thru 5

I can only agree with you but, there is always a but ;), I use this function from my library I’ve written for the following reasons:

  1. The fixed with can be ridiculous wide (I hate limits :lol:)
  2. Argument int can be an integer, string or number
on createLeadingZero(int, width)
	set maxPrefix to ""
	if (int as string)'s length > width then
		return int as string
	end if
	repeat width times
		set maxPrefix to maxPrefix & "0"
	end repeat
	return characters (width - (width * 2)) thru -1 of (maxPrefix & int as text) as text
end createLeadingZero

I agree that there is much more code and for small width’s I would recommend your methodT

Hmm. You still need to change that ‘characters . thru . of . as text’ construction to ‘text . thru . of .’, otherwise you’re vulnerable to stray text item delimiter values.

Good point!

Ah, fixed :slight_smile:

Great solutions, everyone!