You could use this code:

Code:
  
on *:join:#: {
  if ($nick == $me) {
    var %systime = $ctime
    .timercalltime $+ $chan 1 $calc(3600 - %systime + $floor($calc(%systime / 3600)) * 3600 + 5) calltime $chan
  }
}

on *:part:#: {
  if ($nick == $me) {
    .timercalltime $+ $chan off
  }
}

on *:quit: {
  if ($nick == $me) {
    .timercalltime* off
  }
}

on *:disconnect: {
  .timercalltime* off
}

alias calltime {
  var %systime = $ctime
  var %syshour = $left($time(%systime), 2)
  msg $1 It is $iif(%syshour == 0, midnight, $iif(%syshour >= 13, $calc(%syshour - 12), $iif(%syshour >= 10, %syshour, $right(%syshour, 1))) o'clock)
  .timercalltime $+ $1 1 $calc(3600 - %systime + $floor($calc(%systime / 3600)) * 3600 + 5) calltime $1
}


On join of a channel it starts a timer for that channel that will call the alias "calltime" 5 seconds after the next hour. In "calltime" the same timer is started again to call the same alias after exactly 3600 secs. I count for 5 seconds extra to prevent the timer to be called twice just before the hour due to some variance in calculating the delay time. You can test that by skipping the +5. The on part, on quit and on disconnect events will stop running timers.