Documentation
¶
Overview ¶
Package timeutil provides utilities for working with time.
Clock ¶
Inject Clock into any struct that needs the current time:
type Cache struct {
clock timeutil.Clock
}
func NewCache(clock timeutil.Clock) *Cache {
return &Cache{clock: clock}
}
func (c *Cache) IsExpired(expiresAt time.Time) bool {
return c.clock.Now().After(expiresAt)
}
In production, pass RealClock:
cache := NewCache(timeutil.RealClock{})
In tests, pass FixedClock to control time precisely:
fixed := time.Date(2025, 1, 1, 12, 0, 0, 0, time.UTC) cache := NewCache(timeutil.NewFixedClock(fixed)) assert.True(t, cache.IsExpired(fixed.Add(-time.Second))) assert.False(t, cache.IsExpired(fixed.Add(time.Second)))
Sleeper ¶
Inject Sleeper into any struct that pauses execution — retry/backoff, polling, throttling — so tests run instantly instead of waiting on real time:
type Retrier struct {
sleeper timeutil.Sleeper
}
func (r *Retrier) Do(fn func() error) error {
backoff := 100 * time.Millisecond
for i := 0; i < 5; i++ {
if err := fn(); err == nil {
return nil
}
r.sleeper.Sleep(backoff)
backoff *= 2
}
return errors.New("max retries exceeded")
}
In production, pass RealSleeper:
r := &Retrier{sleeper: timeutil.RealSleeper{}}
In tests, pass FakeSleeper to assert on the schedule without waiting:
fake := timeutil.NewFakeSleeper()
r := &Retrier{sleeper: fake}
_ = r.Do(failingFn)
assert.Equal(t, []time.Duration{100 * time.Millisecond, 200 * time.Millisecond}, fake.Calls())
Ticker ¶
Inject Ticker into any struct that runs periodic work — pollers, schedulers, heartbeats — so tests can drive ticks manually instead of waiting on real intervals:
type Poller struct {
ticker timeutil.Ticker
}
func (p *Poller) Run(ctx context.Context, fn func()) {
defer p.ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-p.ticker.C():
fn()
}
}
}
In production, pass RealTicker:
p := &Poller{ticker: timeutil.NewRealTicker(time.Minute)}
In tests, pass FakeTicker to trigger ticks on demand:
fake := timeutil.NewFakeTicker()
p := &Poller{ticker: fake}
go p.Run(ctx, fn)
fake.Tick(time.Now())
fake.Tick(time.Now())
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Clock ¶
Clock provides the current time. Inject it into structs that need time so tests can control it.
type FakeSleeper ¶
FakeSleeper records every requested duration instead of sleeping. Use it in tests to assert on retry/backoff schedules without waiting for real time to pass. Safe for concurrent use.
func NewFakeSleeper ¶
func NewFakeSleeper() *FakeSleeper
NewFakeSleeper creates an empty FakeSleeper.
func (*FakeSleeper) Calls ¶
func (s *FakeSleeper) Calls() []time.Duration
Calls returns a copy of every duration recorded so far, in call order.
func (*FakeSleeper) Sleep ¶
func (s *FakeSleeper) Sleep(d time.Duration)
Sleep records d instead of sleeping.
func (*FakeSleeper) Total ¶
func (s *FakeSleeper) Total() time.Duration
Total returns the sum of every duration recorded so far.
type FakeTicker ¶
type FakeTicker struct {
// contains filtered or unexported fields
}
FakeTicker delivers ticks only when told to via Tick. Use it in tests to drive periodic code deterministically without waiting on real time. Safe for concurrent use.
func NewFakeTicker ¶
func NewFakeTicker() *FakeTicker
NewFakeTicker creates a FakeTicker with an unbuffered channel.
func (*FakeTicker) C ¶
func (t *FakeTicker) C() <-chan time.Time
func (*FakeTicker) Stop ¶
func (t *FakeTicker) Stop()
Stop marks the ticker as stopped. Safe to call multiple times.
func (*FakeTicker) Stopped ¶
func (t *FakeTicker) Stopped() bool
Stopped reports whether Stop has been called.
func (*FakeTicker) Tick ¶
func (t *FakeTicker) Tick(tm time.Time)
Tick sends tm on the ticker's channel, simulating an elapsed interval. It blocks until a receiver reads it.
type FixedClock ¶
FixedClock always returns the same time. Use in tests.
func NewFixedClock ¶
func NewFixedClock(t time.Time) FixedClock
NewFixedClock creates a FixedClock at the given time.
func (FixedClock) Now ¶
func (c FixedClock) Now() time.Time
type RealSleeper ¶
type RealSleeper struct{}
RealSleeper sleeps for real, delegating to time.Sleep.
func (RealSleeper) Sleep ¶
func (RealSleeper) Sleep(d time.Duration)
type RealTicker ¶
type RealTicker struct {
// contains filtered or unexported fields
}
RealTicker ticks for real, delegating to time.Ticker.
func NewRealTicker ¶
func NewRealTicker(d time.Duration) *RealTicker
NewRealTicker creates a RealTicker that ticks every d.
func (*RealTicker) C ¶
func (t *RealTicker) C() <-chan time.Time
func (*RealTicker) Stop ¶
func (t *RealTicker) Stop()
type Sleeper ¶
Sleeper pauses execution for a duration. Inject it into structs that sleep (retry/backoff, polling, throttling) so tests can run instantly instead of waiting on real time.
type Ticker ¶
type Ticker interface {
// C returns the channel on which ticks are delivered.
C() <-chan time.Time
// Stop turns off the ticker. No more ticks are sent after Stop returns.
Stop()
}
Ticker delivers the current time on a channel at regular intervals. Inject it into structs that run periodic work — pollers, schedulers, heartbeats — so tests can drive ticks manually instead of waiting on real intervals.