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.
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”.
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
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.
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.
I’m embarrassed to say that the praise afforded my script by you and Stefan isn’t quite justified. :rolleyes:
In the additions at the top, the carries should be added in before the divs and mods.
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.
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.