Ok, I'd like opinions/thoughts on this script I just wrote in the last hour or so. The script should accurately output a $duration with months/years as long as the $duration is from the current date to some other past date (like when calculating uptime). I could probably make it also go forwards, but that is beyond what I'm trying to do with it right now.

Note that no matter what the $duration is (whether it's from today's date and counting backwards, or some other way), it will still be very accurate (within a few days at most). It just can't be guaranteed to be perfectly accurate except when using the current date and going backwards.

After I have your comments and ideas (and any bugs) about the script and its usefulness, I'll see about submitting it to mircscripts.org. Also, feel free to suggest fixes to the code to make it better.

Code:
; *******************************************************************
; DateXpander Script
; by Riamus 2005
;
; This script will take a standard $duration and make it include months and years
; based on the current date.
;
; For this script to be accurate, it is only meant to be used when the $duration is
; using today's date and counting backwards (such as an uptime $duration).  It
; will still be really accurate (within 3 days) even if you use a $duration that isn't
; from the current date, but it won't be exact that way.
;
; Use: $DateXpander(value)
; "value" must be in the format of $duration
;
; For questions about this script, contact Riamus on IRC -- #oldgames on irc.undernet.org
; *******************************************************************

alias DateXpander {
  unset %dateoutput

  set %weeks $iif($gettok($1-,1,119) isnum,$gettok($1-,1,119),0)
  set %days $iif($gettok($gettok($1-,1,100),-1,32) isnum,$gettok($gettok($1-,1,100),-1,32),0)
  set %hours $iif($gettok($gettok($1-,1,104),-1,32) isnum,$gettok($gettok($1-,1,104),-1,32),0)
  set %minutes $iif($gettok($gettok($1-,1,109),-1,32) isnum,$gettok($gettok($1-,1,109),-1,32),0)
  set %seconds $iif(sec isin $gettok($1-,$gettok($1-,0,32),32),$gettok($gettok($1-,$gettok($1-,0,32),32),1,115),0)
  set %totaldays $calc(%weeks * 7 + %days)
  if (%weeks < 4) {
    goto yearstart
  }

  set %currentmonth $date(m)

  :monthstart
  if (%currentmonth == 12) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 11) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 10) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 9) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 8) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 7) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 6) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 5) {
    if (%totaldays > 29) {
      inc %months
      dec %totaldays 30
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 4) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 3) {
    if (%totaldays > 27 && $int($calc($year / 4) != $calc($year / 4))) {
      inc %months
      dec %totaldays 28
      dec %currentmonth
    }
    elseif (%totaldays > 28 && $int($calc($year / 4) == $calc($year / 4))) {
      inc %months
      dec %totaldays 29
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 2) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      dec %currentmonth
    }
    else { goto yearstart }
  }
  if (%currentmonth == 1) {
    if (%totaldays > 30) {
      inc %months
      dec %totaldays 31
      set %currentmonth 12
    }
    else { goto yearstart }
  }
  goto monthstart

  :yearstart
  set %years $int($calc(%months / 12))
  dec %months $calc(%years * 12)
  set %weeks $int($calc(%totaldays / 7))
  set %totaldays $calc(%totaldays - (%weeks * 7))

  if (%years > 1) { set %dateoutput %dateoutput %years $+ _years }
  elseif (%years == 1) { set %dateoutput %dateoutput %years $+ _year }
  if (%months > 1) { set %dateoutput %dateoutput %months $+ _months }
  elseif (%months == 1) { set %dateoutput %dateoutput %months $+ _month }
  if (%weeks > 1) { set %dateoutput %dateoutput %weeks $+ _weeks }
  elseif (%weeks == 1) { set %dateoutput %dateoutput %weeks $+ _week }
  if (%totaldays > 1) { set %dateoutput %dateoutput %totaldays $+ _days }
  elseif (%totaldays == 1) { set %dateoutput %dateoutput %totaldays $+ _day }
  if (%hours > 1) { set %dateoutput %dateoutput %hours $+ _hours }
  elseif (%hours == 1) { set %dateoutput %dateoutput %hours $+ _hour }
  if (%minutes > 1) { set %dateoutput %dateoutput %minutes $+ _minutes }
  elseif (%minutes == 1) { set %dateoutput %dateoutput %minutes $+ _minute }
  if (%seconds > 1) { set %dateoutput %dateoutput %seconds $+ _seconds }
  elseif (%seconds == 1) { set %dateoutput %dateoutput %seconds $+ _second }

  unset %years
  unset %months
  unset %weeks
  unset %days
  unset %hours
  unset %minutes
  unset %seconds
  unset %totaldays
  unset %currentmonth

  return $replace(%dateoutput,$chr(32),$chr(44) $+ $chr(32),_,$chr(32))
}


Just as one explanation to how this works so you don't start saying it's messing up for it...

The current month is July. If you go back to the same date last month, you are going back 30 days (June has 30 days). That's one month ago.

So, some examples:

$datexpander(3wks 6days)
3 weeks, 6 days

$datexpander(4wks)
4 weeks

$datexpander(4wks 1day)
4 weeks, 1 day

$datexpander(4wks 2days)
1 month

$datexpander(4wks 3days)
1 month, 1 day