First off, $uptime doesn't report how long a person has been in a channel.
Code:
on me:*:join:#:{
  var %a = 1, %b = $nick($chan,0)
  while %a <= %b {
    .hadd -m Time $+($network,.,$chan,.,$nick($chan,%a)) $ctime
    inc %a
  }
}
on !*:join:#:{
  .hadd -m Time $+($network.,.$chan,.,$nick) $ctime
}
on *:text:!uptime:#:{
  .notice $nick You have been in $chan for $duration($calc($ctime - $hget(Time,$+($network,.,$chan,.,$nick))))
}
on *:start:{
  .scon -at1 init_time $!cid
}
alias -l init_time {
  .scid $1
  var %a = 1, %b = $chan(0)
  while %a <= %b {
    var %c = 1, %d = $nick($chan(%a),0)
    while %c <= %d {
      .hadd -m Time $+($network,.,$chan(%a),.,$nick($chan(%a),%c)) $ctime
      inc %c
    }
    inc %a
  }
}

This is a bit more complex than what you actually asked for, but it does track the time for the person in the channel, and is multi-network ready. It also will set the initial start times when the code is started, no need to disconnect from any network or part any channels for it to start, but note that the time reported will only be from the most recent of a) the script being started, b) you joining the channel, c) the time the nick joined the channel.
There is no way for the script to know how long a person had been in the channel before the script was started or before you joined with the script running.