فهرست منبع

spec.go: adjust times when rolling the clock forward to handle non-existent midnight

Fixes #157
Rob Figueiredo 6 سال پیش
والد
کامیت
dbf3220455
2فایلهای تغییر یافته به همراه23 افزوده شده و 1 حذف شده
  1. 15 1
      spec.go
  2. 8 0
      spec_test.go

+ 15 - 1
spec.go

@@ -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.
@@ -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

+ 8 - 0
spec_test.go

@@ -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 {