From ce65012a1460563bb6fe0a27fe37a805d3f12f51 Mon Sep 17 00:00:00 2001 From: John Roesler Date: Fri, 21 Nov 2025 14:15:29 -0600 Subject: [PATCH] fix: WithStartDateTimePast now correctly calculates from past time --- job.go | 6 ++---- scheduler.go | 11 +++++++++++ scheduler_test.go | 31 +++++++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/job.go b/job.go index 8bdb3c6..4a5295c 100644 --- a/job.go +++ b/job.go @@ -1022,16 +1022,14 @@ type weeklyJob struct { } func (w weeklyJob) next(lastRun time.Time) time.Time { - firstPass := true - next := w.nextWeekDayAtTime(lastRun, firstPass) + next := w.nextWeekDayAtTime(lastRun, true) if !next.IsZero() { return next } - firstPass = false startOfTheNextIntervalWeek := (lastRun.Day() - int(lastRun.Weekday())) + int(w.interval*7) from := time.Date(lastRun.Year(), lastRun.Month(), startOfTheNextIntervalWeek, 0, 0, 0, 0, lastRun.Location()) - return w.nextWeekDayAtTime(from, firstPass) + return w.nextWeekDayAtTime(from, false) } func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time, firstPass bool) time.Time { diff --git a/scheduler.go b/scheduler.go index 274f1e2..382c55f 100644 --- a/scheduler.go +++ b/scheduler.go @@ -508,6 +508,12 @@ func (s *scheduler) selectNewJob(in newJobIn) { next = j.next(s.now()) } + if next.Before(s.now()) { + for next.Before(s.now()) { + next = j.next(next) + } + } + id := j.id j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() { select { @@ -559,6 +565,11 @@ func (s *scheduler) selectStart() { if next.IsZero() { next = j.next(s.now()) } + if next.Before(s.now()) { + for next.Before(s.now()) { + next = j.next(next) + } + } jobID := id j.timer = s.exec.clock.AfterFunc(next.Sub(s.now()), func() { diff --git a/scheduler_test.go b/scheduler_test.go index 1ae7431..e040576 100644 --- a/scheduler_test.go +++ b/scheduler_test.go @@ -2876,3 +2876,34 @@ func TestScheduler_WithMonitor(t *testing.T) { }) } } + +func TestScheduler_WithStartAtDateTimePast(t *testing.T) { + defer verifyNoGoroutineLeaks(t) + + // Monday + testTime := time.Date(2024, time.January, 1, 9, 0, 0, 0, time.UTC) + + fakeClock := clockwork.NewFakeClockAt(testTime) + + s := newTestScheduler(t, WithClock(fakeClock)) + j, err := s.NewJob( + WeeklyJob(2, NewWeekdays(time.Sunday), NewAtTimes(NewAtTime(10, 0, 0))), + NewTask(func() {}), + WithStartAt( + // The start time is in the past (Dec 30, 2023 9am) which is a Saturday + WithStartDateTimePast(testTime.Add(-time.Hour*24*2)), + ), + ) + require.NoError(t, err) + + s.Start() + + nextRun, err := j.NextRun() + require.NoError(t, err) + + require.NoError(t, s.Shutdown()) + + // Because the start time was in the past - we expect it to schedule 2 intervals ahead, pasing the first available Sunday + // which was in the past Dec 31, 2023, so the next is Jan 7, 2024 + assert.Equal(t, time.Date(2024, time.January, 7, 10, 0, 0, 0, time.UTC), nextRun) +}