code: def call_later(self, delay, func, *args, **kwargs):
          
          # "quantize" the delay to the nearest bucket
          now = self._get_seconds()
          real_time = int(now + delay) * 1000
          real_time -= int(real_time % self._bucket_milliseconds)
          call = _BatchedCall(self, real_time, lambda: func(*args, **kwargs))
          try:
              self._buckets[real_time][1].append(call)
          except KeyError:
              # new bucket; need to add "actual" underlying IDelayedCall
              diff = (real_time / 1000.0) - now
              # we need to clamp this because if we quantized to the
              # nearest second, but that second is actually (slightly)
              # less than the current time 'diff' will be negative.
              delayed_call = self._create_delayed_call(
                  max(0.0, diff),
                  self._notify_bucket, real_time,
              )
              self._buckets[real_time] = (delayed_call, [call])
          return call
docs: IBatchedTimer API