Skip to content

Commit 9803aad

Browse files
authored
fix weekly and monthly to handle midnight (#643)
1 parent 80a4f43 commit 9803aad

File tree

2 files changed

+40
-27
lines changed

2 files changed

+40
-27
lines changed

Diff for: job.go

+34-21
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ func (w weeklyJobDefinition) setup(j *internalJob, location *time.Location) erro
256256
daysOfTheWeek := w.daysOfTheWeek()
257257

258258
slices.Sort(daysOfTheWeek)
259+
ws.daysOfWeek = daysOfTheWeek
259260

260261
atTimesDate, err := convertAtTimesToDateTime(w.atTimes, location)
261262
switch {
@@ -622,31 +623,31 @@ type dailyJob struct {
622623
}
623624

624625
func (d dailyJob) next(lastRun time.Time) time.Time {
625-
return d.nextDay(lastRun)
626+
firstPass := true
627+
next := d.nextDay(lastRun, firstPass)
628+
if !next.IsZero() {
629+
return next
630+
}
631+
firstPass = false
632+
633+
startNextDay := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(d.interval), 0, 0, 0, lastRun.Nanosecond(), lastRun.Location())
634+
return d.nextDay(startNextDay, firstPass)
626635
}
627636

628-
func (d dailyJob) nextDay(lastRun time.Time) time.Time {
637+
func (d dailyJob) nextDay(lastRun time.Time, firstPass bool) time.Time {
629638
for _, at := range d.atTimes {
630639
// sub the at time hour/min/sec onto the lastRun's values
631640
// to use in checks to see if we've got our next run time
632641
atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day(), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location())
633642

634-
if atDate.After(lastRun) {
643+
if firstPass && atDate.After(lastRun) {
635644
// checking to see if it is after i.e. greater than,
636645
// and not greater or equal as our lastRun day/time
637646
// will be in the loop, and we don't want to select it again
638647
return atDate
639-
}
640-
}
641-
startNextDay := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(d.interval), 0, 0, 0, lastRun.Nanosecond(), lastRun.Location())
642-
for _, at := range d.atTimes {
643-
// sub the at time hour/min/sec onto the lastRun's values
644-
// to use in checks to see if we've got our next run time
645-
atDate := time.Date(startNextDay.Year(), startNextDay.Month(), startNextDay.Day(), at.Hour(), at.Minute(), at.Second(), startNextDay.Nanosecond(), startNextDay.Location())
646-
647-
if !atDate.Before(startNextDay) {
648+
} else if !firstPass && !atDate.Before(lastRun) {
648649
// now that we're looking at the next day, it's ok to consider
649-
// the same at time that was last run
650+
// the same at time that was last run (as lastRun has been incremented)
650651
return atDate
651652
}
652653
}
@@ -662,17 +663,19 @@ type weeklyJob struct {
662663
}
663664

664665
func (w weeklyJob) next(lastRun time.Time) time.Time {
665-
next := w.nextWeekDayAtTime(lastRun)
666+
firstPass := true
667+
next := w.nextWeekDayAtTime(lastRun, firstPass)
666668
if !next.IsZero() {
667669
return next
668670
}
671+
firstPass = false
669672

670673
startOfTheNextIntervalWeek := (lastRun.Day() - int(lastRun.Weekday())) + int(w.interval*7)
671674
from := time.Date(lastRun.Year(), lastRun.Month(), startOfTheNextIntervalWeek, 0, 0, 0, 0, lastRun.Location())
672-
return w.nextWeekDayAtTime(from)
675+
return w.nextWeekDayAtTime(from, firstPass)
673676
}
674677

675-
func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time) time.Time {
678+
func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time, firstPass bool) time.Time {
676679
for _, wd := range w.daysOfWeek {
677680
// checking if we're on the same day or later in the same week
678681
if wd >= lastRun.Weekday() {
@@ -683,11 +686,15 @@ func (w weeklyJob) nextWeekDayAtTime(lastRun time.Time) time.Time {
683686
// to use in checks to see if we've got our next run time
684687
atDate := time.Date(lastRun.Year(), lastRun.Month(), lastRun.Day()+int(weekDayDiff), at.Hour(), at.Minute(), at.Second(), lastRun.Nanosecond(), lastRun.Location())
685688

686-
if atDate.After(lastRun) {
689+
if firstPass && atDate.After(lastRun) {
687690
// checking to see if it is after i.e. greater than,
688691
// and not greater or equal as our lastRun day/time
689692
// will be in the loop, and we don't want to select it again
690693
return atDate
694+
} else if !firstPass && !atDate.Before(lastRun) {
695+
// now that we're looking at the next week, it's ok to consider
696+
// the same at time that was last run (as lastRun has been incremented)
697+
return atDate
691698
}
692699
}
693700
}
@@ -717,21 +724,23 @@ func (m monthlyJob) next(lastRun time.Time) time.Time {
717724
}
718725
slices.Sort(daysList)
719726

720-
next := m.nextMonthDayAtTime(lastRun, daysList)
727+
firstPass := true
728+
next := m.nextMonthDayAtTime(lastRun, daysList, firstPass)
721729
if !next.IsZero() {
722730
return next
723731
}
732+
firstPass = false
724733

725734
from := time.Date(lastRun.Year(), lastRun.Month()+time.Month(m.interval), 1, 0, 0, 0, 0, lastRun.Location())
726735
for next.IsZero() {
727-
next = m.nextMonthDayAtTime(from, daysList)
736+
next = m.nextMonthDayAtTime(from, daysList, firstPass)
728737
from = from.AddDate(0, int(m.interval), 0)
729738
}
730739

731740
return next
732741
}
733742

734-
func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int) time.Time {
743+
func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int, firstPass bool) time.Time {
735744
// find the next day in the month that should run and then check for an at time
736745
for _, day := range days {
737746
if day >= lastRun.Day() {
@@ -746,11 +755,15 @@ func (m monthlyJob) nextMonthDayAtTime(lastRun time.Time, days []int) time.Time
746755
continue
747756
}
748757

749-
if atDate.After(lastRun) {
758+
if firstPass && atDate.After(lastRun) {
750759
// checking to see if it is after i.e. greater than,
751760
// and not greater or equal as our lastRun day/time
752761
// will be in the loop, and we don't want to select it again
753762
return atDate
763+
} else if !firstPass && !atDate.Before(lastRun) {
764+
// now that we're looking at the next month, it's ok to consider
765+
// the same at time that was lastRun (as lastRun has been incremented)
766+
return atDate
754767
}
755768
}
756769
continue

Diff for: job_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ func TestWeeklyJob_next(t *testing.T) {
113113
1,
114114
[]time.Weekday{time.Monday, time.Thursday},
115115
[]time.Time{
116-
time.Date(0, 0, 0, 5, 30, 0, 0, time.UTC),
116+
time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC),
117117
},
118-
time.Date(2000, 1, 3, 5, 30, 0, 0, time.UTC),
119-
time.Date(2000, 1, 6, 5, 30, 0, 0, time.UTC),
118+
time.Date(2000, 1, 3, 0, 0, 0, 0, time.UTC),
119+
time.Date(2000, 1, 6, 0, 0, 0, 0, time.UTC),
120120
3 * 24 * time.Hour,
121121
},
122122
{
@@ -179,10 +179,10 @@ func TestMonthlyJob_next(t *testing.T) {
179179
[]int{1, 10},
180180
nil,
181181
[]time.Time{
182-
time.Date(0, 0, 0, 5, 30, 0, 0, time.UTC),
182+
time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC),
183183
},
184-
time.Date(2000, 1, 1, 5, 30, 0, 0, time.UTC),
185-
time.Date(2000, 1, 10, 5, 30, 0, 0, time.UTC),
184+
time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC),
185+
time.Date(2000, 1, 10, 0, 0, 0, 0, time.UTC),
186186
9 * 24 * time.Hour,
187187
},
188188
{

0 commit comments

Comments
 (0)