I was sitting at home last night with nothing to do so thought id have a go at one myself, man was that a mistake, I almost gave up twice. I thought it would be simple, just a matter of subtracting the first date from the second, and it is but theres alot of little fiddly bits that i didnt take into account, some not with the calculation itself but with $ctime and how it replies with a count of seconds between your localtime and 1970-01-01 00:00:00 GMT time, im at +12gmt so i cant even get a value on that date/time first i get is 1970-01-01 12:00:00, this was a second problem I encountered, and nearly tossed it for it. Anyway enough complaining heres what I came up with.

[code]
;Duration.From.To.Format
; * Pass it any two dates that $ctime can return values for (1970-01-01 00:00:00 +-12 hours onward to sometime)
; * and it returns back the yrs,mths,wks,days,hrs,mins,secs from one to the other. A few output format options also see below.
;
;usage $Duration.From.To.Format($1,$2,$3)
; $1 = $date $time
; $2 = $date $time
; $3 = formating (as follows)
; e=short extentions yrs,mths,wks,days,hrs,mins,secs (default)
; E=long extentions years,months,weeks,days,hours,minutes,seconds (overrides e)
; a=all fields
; A=all fields no extentions (overrides e & E & a)
; z=zeropad fields years(4) Months(2) Weeks(1) Days(1) Hours(2) Minutes(2) Seconds(2)
;
alias Duration.From.To.Format {
var %c1 = $ctime($1), %c2 = $ctime($2)
if ((%c1 == $null) || (%c2 == $null)) { RETURN }
if (%c1 < %c2) { var -s %temp = %c1, %c1 = %c2, %c2 = %temp }
var %y1 = $date(%c1,yyyy), %m1 = $date(%c1,mm), %d1 = $date(%c1,dd), %t1 = $calc($time(%c1,HH) * 3600 + $time(%c1,nn) * 60 + $time(%c1,ss))
var %y2 = $date(%c2,yyyy), %m2 = $date(%c2,mm), %d2 = $date(%c2,dd), %t2 = $calc($time(%c2,HH) * 3600 + $time(%c2,nn) * 60 + $time(%c2,ss))
if (%t1 < %t2) { inc %t1 86400 | dec %d1 }
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y1 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
if (%m1 < %m2) { inc %m1 12 | dec %y1 }
var %y0 = $calc(%y1 - %y2), %m0 = $calc(%m1 - %m2), %d0 = $calc(%d1 - %d2), %t0 = $calc(%t1 - %t2), %w0 = $int($calc(%d0 / 7))
var %d0 = $calc(%d0 % 7), %h0 = $int($calc(%t0 / 3600)), %n0 = $int($calc((%t0 % 3600) / 60)), %s0 = $calc(%t0 % 60)
;
if ((A isincs $3) && (z isin $3)) { RETURN $right($+(0000,%y0),4) $right($+(00,%m0),2) %w0 %d0 $right($+(00,%h0),2) $right($+(00,%n0),2) $right($+(00,%s0),2) }
if ((A isincs $3)) { RETURN %y0 %m0 %m0 %w0 %d0 %h0 %n0 %s0 }
if ((a isincs $3) && (E isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years)) $+($right($+(00,%m0),2),$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours)) $+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes)) $+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (E isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,year,years)) $+(%m0,$iif(%m0 == 1,month,months)) $+(%w0,$iif(%w0 == 1,week,weeks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hour,hours)) $+(%n0,$iif(%n0 == 1,minute,minutes)) $+(%s0,$iif(%s0 == 1,second,seconds)) }
if ((a isincs $3) && (z isin $3)) { RETURN $+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs)) $+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs)) $+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins)) $+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs)) }
if ((a isincs $3)) { RETURN $+(%y0,$iif(%y0 == 1,yr,yrs)) $+(%m0,$iif(%m0 == 1,mth,mths)) $+(%w0,$iif(%w0 == 1,wk,wks)) $+(%d0,$iif(%d0 == 1,day,days)) $+(%h0,$iif(%h0 == 1,hr,hrs)) $+(%n0,$iif(%n0 == 1,min,mins)) $+(%s0,$iif(%s0 == 1,sec,secs)) }
if ((E isincs $3) && (z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,year,years))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hour,hours))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,second,seconds))) }
if ((E isincs $3)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,year,years))) $iif(%m0,$+(%m0,$iif(%m0 == 1,month,months))) $iif(%w0,$+(%w0,$iif(%w0 == 1,week,weeks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hour,hours))) $iif(%n0,$+(%n0,$iif(%n0 == 1,minute,minutes))) $iif(%s0,$+(%s0,$iif(%s0 == 1,second,seconds))) }
if ((z isin $3)) { RETURN $iif(%y0,$+($right($+(0000,%y0),4),$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+($right($+(00,%m0),2),$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+($right($+(00,%h0),2),$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+($right($+(00,%n0),2),$iif(%n0 == 1,min,mins))) $iif(%s0,$+($right($+(00,%s0),2),$iif(%s0 == 1,sec,secs))) }
if (($true)) { RETURN $iif(%y0,$+(%y0,$iif(%y0 == 1,yr,yrs))) $iif(%m0,$+(%m0,$iif(%m0 == 1,mth,mths))) $iif(%w0,$+(%w0,$iif(%w0 == 1,wk,wks))) $iif(%d0,$+(%d0,$iif(%d0 == 1,day,days))) $iif(%h0,$+(%h0,$iif(%h0 == 1,hr,hrs))) $iif(%n0,$+(%n0,$iif(%n0 == 1,min,mins))) $iif(%s0,$+(%s0,$iif(%s0 == 1,sec,secs))) }
}
[code]

* wouldnt mind someone running it through the grinder, seeing if you can break it, Im not overly convinced i got the bit when you have a bigger day count to take off a smaller one, like if u have a time of 8:12 and 4:16 to take off it, you just make it 7:72 - 4:16 = 3:56, but when its a day count you cant just add 28,29,30,31 whcih one is it?!?!?! I think i got it right but then again.
This line is where i likely have a fault.
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y1 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
It might need to be
if (%d1 < %d2) { inc %d1 $gettok(31 $iif(!$calc(%y2 % 4),29,28) 31 30 31 30 31 31 30 31 30 31,%m2,32) | dec %m1 }
* its designed to add a months days onto the first day count so the second day count can be removed from it, and it then adjusts the month count down by one.