Skip to content

Commit

Permalink
spec.go: adjust times when rolling the clock forward to handle non-ex…
Browse files Browse the repository at this point in the history
…istent midnight

Fixes #157
  • Loading branch information
Rob Figueiredo committed Feb 13, 2019
1 parent 4813ba2 commit dbf3220
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 1 deletion.
16 changes: 15 additions & 1 deletion spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ const (
// Next returns the next time this schedule is activated, greater than the given
// time. If no time can be found to satisfy the schedule, return the zero time.
func (s *SpecSchedule) Next(t time.Time) time.Time {
// General approach:
// General approach
//
// For Month, Day, Hour, Minute, Second:
// Check if the time value matches. If yes, continue to the next field.
// If the field doesn't match the schedule, then increment the field until it matches.
Expand Down Expand Up @@ -109,12 +110,25 @@ WRAP:
}

// Now get a day in that month.
//
// NOTE: This causes issues for daylight savings regimes where midnight does
// not exist. For example: Sao Paulo has DST that transforms midnight on
// 11/3 into 1am. Handle that by noticing when the Hour ends up != 0.
for !dayMatches(s, t) {
if !added {
added = true
t = time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc)
}
t = t.AddDate(0, 0, 1)
// Notice if the hour is no longer midnight due to DST.
// Add an hour if it's 23, subtract an hour if it's 1.
if t.Hour() != 0 {
if t.Hour() > 12 {
t = t.Add(time.Duration(24-t.Hour()) * time.Hour)
} else {
t = t.Add(time.Duration(-t.Hour()) * time.Hour)
}
}

if t.Day() == 1 {
goto WRAP
Expand Down
8 changes: 8 additions & 0 deletions spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ func TestNext(t *testing.T) {
// Unsatisfiable
{"Mon Jul 9 23:35 2012", "0 0 0 30 Feb ?", ""},
{"Mon Jul 9 23:35 2012", "0 0 0 31 Apr ?", ""},

// Monthly job
{"2012-11-04T00:00:00-0400", "0 0 3 3 * ?", "2012-12-03T03:00:00-0500"},

// Test the scenario of DST resulting in midnight not being a valid time.
// https://github.com/robfig/cron/issues/157
{"2018-10-17T05:00:00-0400", "TZ=America/Sao_Paulo 0 0 9 10 * ?", "2018-11-10T06:00:00-0500"},
{"2018-02-14T05:00:00-0500", "TZ=America/Sao_Paulo 0 0 9 22 * ?", "2018-02-22T07:00:00-0500"},
}

for _, c := range runs {
Expand Down

0 comments on commit dbf3220

Please sign in to comment.