adding time strings

I have to add two time strings in the format xx:xx:xx (that means hours:minutes:seconds). That’s quite easy in principle of course but I’m curious if there is a particularly nice and short way to do it using built in applescript date and time manipulation capabilities.

Hi.

If your computer’s set to display 24-hour times anyway, this will do it:

set timeString to time string of theDate

Otherwise (or in any case):

set {hours:h, minutes:m, seconds:s} to theDate
tell (1000000 + h * 10000 + m * 100 + s) as text to set timeString to text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7

Thanks. sorry, I think I didn’t make clear what I wanted. i have two text strings, say, date1=“01:24:36” and date2=“02:37:41”. I need to add them as time strings and get “04:02:17”.

Hi,

actually you can’t do date arithmetic directly with AppleScript date objects,
so this is a vanilla AppleScript solution, it considers also results > 24 hrs

addTimeStrings("11:26:40", "20:40:30") --> "01:08:07:10"

on addTimeStrings(timeString1, timeString2)
	return secsToTimeString(timeStringToSecs(timeString1) + timeStringToSecs(timeString2))
end addTimeStrings

on timeStringToSecs(timeString)
	set TID to text item delimiters
	set text item delimiters to ":"
	set {hrs, mins, secs} to text items of timeString
	set text item delimiters to TID
	return hrs * hours + mins * minutes + secs
end timeStringToSecs

on secsToTimeString(theSecs)
	set {dys, hrs, mins, secs} to {theSecs div days, theSecs mod days div hours, theSecs mod hours div minutes, theSecs mod minutes div 1}
	if dys > 0 then
		return pad(dys) & ":" & pad(hrs) & ":" & pad(mins) & ":" & pad(secs)
	else
		return pad(hrs) & ":" & pad(mins) & ":" & pad(secs)
	end if
	
	return theDate
end secsToTimeString

on pad(v)
	return text -2 thru -1 of ((100 + v) as text)
end pad

Thanks a lot Stefan!

Ah, I see. I thought that one could which is why I asked.
thanks for the script. I particularly like the pad() function.

Oh, sorry. I noticed you didn’t say what you were adding them to: it just never occurred to me that you meant to each other! :lol:

Here’s a fairly simple and obvious method. Like Stefan’s, it includes a days figure in the result if it’s more than “23:59:59”. It relies on “:” being a word separator on everyone’s machines, which I think is true with Unicode text, though I may be wrong. It can easily be changed to text items if not.

on addTimeStrings(ts1, ts2)
	tell (word 3 of ts1) + (word 3 of ts2) to set {m, s} to {it div 60, it mod 60}
	tell (word 2 of ts1) + (word 2 of ts2) + m to set {h, m} to {it div 60, it mod 60}
	tell (word 1 of ts1) + (word 1 of ts2) + h to set {d, h} to {it div 24, it mod 24}
	if (d is 0) then
		tell (1000000 + h * 10000 + m * 100 + s) as text to return text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7
	else
		tell (100000000 + d * 1000000 + h * 10000 + m * 100 + s) as text to return text 2 thru 3 & ":" & text 4 thru 5 & ":" & text 6 thru 7 & ":" & text 8 thru 9
	end if
end addTimeStrings

addTimeStrings("01:24:36", "02:37:41")

You can very definitely do date arithmetic with AppleScript date objects, but there’s no advantage to doing so here.

Edit: Script corrected 9th May 2012.

:smiley: I knew, you would present the ultimate solution. It’s amazing as always

My statement was too unclearly. Of course you can work with time intervals like calculating the difference of two dates, but you can’t add two date objects or date/time string representations of them

I see that you have already efficiently answered the question. For fun I thought I’d add a twist. Time strings can come in many formats so I played with making a more flexible solution. Sometimes the time strings include “days” and sometimes they’re only “minutes:seconds”. As such here’s one that works similar to StefanK’s solution but with a revised timeStringToSecs(timeString) handler to handle the various cases.

addListOfTimestrings({"02:37:41", "01:01:24:36", "24:00", 200})

on addListOfTimestrings(timestringsList)
	set theSecs to 0
	repeat with aString in timestringsList
		set theSecs to theSecs + (my timeStringToSecs(aString))
	end repeat
	return my secsToTimeString(theSecs)
end addListOfTimestrings

-- this can handle a variable format time string meaning
-- the format can be "days:hours:mins:secs" or just secs or anything in between
on timeStringToSecs(timeString)
	set l to {0, 0, 0, 0}
	set t to words of (timeString as text) -- coerce to text in case a number is passed
	repeat with i from 1 to count of t
		set item -i of l to item -i of t
	end repeat
	return (item 1 of l) * days + (item 2 of l) * hours + (item 3 of l) * minutes + (item 4 of l)
end timeStringToSecs

on secsToTimeString(theSecs)
	set timeString to ""
	if theSecs is greater than or equal to 86400 then
		set da to text 2 thru 3 of ((100 + theSecs div days) as text)
		set timeString to da & ":"
	end if
	set hr to text 2 thru 3 of ((100 + theSecs mod days div hours) as text)
	set min to text 2 thru 3 of ((100 + theSecs mod hours div minutes) as text)
	set sec to text 2 thru 3 of ((100 + theSecs mod minutes div 1) as text)
	set timeString to timeString & hr & ":" & min & ":" & sec
	return timeString
end secsToTimeString

:D, yes, I only realized that my original post was ambiguous after seeing your first response. I had a very specific task in mind and didn’t consider other possible meanings of my question.

thanks a lot. this is a really nice and efficient way of doing it. both yours and Stefan’s scripts are definitely better than what I was going to make myself.

Thanks! In my case the time format is fixed. I need to merge two subtitles .srt files into one which requires adding a fixed time to all time instances (in the format I mentioned) in the second file.

But I’m sure your script can be useful to others.

I’m embarrassed to say that the praise afforded my script by you and Stefan isn’t quite justified. :rolleyes:

  1. In the additions at the top, the carries should be added in before the divs and mods.
  2. Setting the sumStr variable was originally done with the intention of returning it at the end of the handler. In fact, one could just return the result at those stages.
  3. SInce the input times are both less than a day, the days figure resulting from their addition is never going to be more than 1, so ‘100000000 + d * 1000000’ in the last ‘tell’ line could just be ‘101000000’. On the other hand, the original gives the correct result even when one of the inputs has an hours figure greater than 23, so I think I’ll keep it.

I’ve now corrected the script in my post (#6) above.