I think your problem comes from the fact that you unset the variable when you type !uptime. Also, is there any particular reason why you also need a downtime variable? Since uptimeon is active only when you're live, I don't think you really need a downtime variable.

Code:
on *:text:!startuptime:#: {
  set %uptimeon On 
  if ((%floodstartuptime) || ($($+(%,floodstartuptime.,$nick),2))) { return }
  set -u600 %floodstartuptime On
  set -u600 %floodstartuptime. $+ $nick On
  msg # Stopping Downtime. Starting uptime.
  set -e %uptime. [ $+ [ # ] ] $ctime
  unset %downtime. [ $+ [ # ] ] $+
}
on *:text:!uptime:#: { 
  if (!%uptime) {
    msg # I am currently offline
  }
  else {
    if ((%flooduptime) || ($($+(%,flooduptime.,$nick),2))) { return }
    set -u300 %flooduptime On
    set -u300 %flooduptime. $+ $nick On
    msg # /me Uptime: $duration($calc($ctime - %uptime. [ $+ [ # ] ] )) $+
  }
    }
}
on *:text:!stopuptime:#: { 
  unset %uptimeon
  if ((%floodstopuptime) || ($($+(%,floodstopuptime.,$nick),2))) { return }
  set -u600 %floodstopuptime On
  set -u600 %floodstopuptime. $+ $nick On
  msg # Stopping uptime. Starting downtime.
  unset %uptime. [ $+ [ # ] ] $+
  set -e %downtime. [ $+ [ # ] ] $ctime 
}
on *:text:!downtime:#: { 
  if (!%uptimeon) {
    if ((%flooddowntime) || ($($+(%,flooddowntime.,$nick),2))) { return }
    set -u300 %flooddowntime On
    set -u300 %flooddowntime. $+ $nick On

    msg # /me Downtime: $duration($calc($ctime - %downtime. [ $+ [ # ] ] )) $+
  }
  else {
    msg # I am currently live. Duh  }
}


I might have accidently added a bracket or two but this in theory should work. Sorry, I'm not on my computer right now so I can't physically test it.