cron
cron copied to clipboard
schedule timezone local.
if the schedules timezone not specify, it's local timezone. but the code doesn't convert the t to the schedule timezone. and compare time below with schedule and t.
// Convert the given time into the schedule's timezone, if one is specified.
// Save the original timezone so we can convert back after we find a time.
// Note that schedules without a time zone specified (time.Local) are treated
// as local to the time provided.
origLocation := t.Location()
loc := s.Location
if loc == time.Local {
loc = t.Location()
}
if s.Location != time.Local {
t = t.In(s.Location)
}
Thank you for the report. Can you provide a test case that demonstrates the issue?
Hello, I met the same issue, I think. Here is the test reproducing the issue:
func TestCronTimezone(t *testing.T) {
loc, _ := time.LoadLocation("Europe/Paris")
cronProcess := cron.New(cron.WithLocation(loc))
entryID, _ := cronProcess.AddFunc("0 6 * * *", func() {
log.Printf("Cron job : %s", time.Now())
})
cronProcess.Start()
now := time.Date(2020, 4, 23, 5, 30, 0, 0, time.UTC)
// In "Europe/Paris" timezone, equals to 2020-04-23T07:30:00
nowInLoc := now.In(loc)
if !now.Equal(nowInLoc) {
t.Errorf("Should not happen, because dates are the same")
}
entry := cronProcess.Entry(entryID)
next := entry.Schedule.Next(now)
nextInLoc := entry.Schedule.Next(nowInLoc)
if !next.Equal(nextInLoc) {
t.Errorf("Should not happen: next %s, next in location %s", next, nextInLoc)
}
}
And the result:
Should not happen: next 2020-04-23 06:00:00 +0000 UTC, next in location 2020-04-24 06:00:00 +0200 CEST
We can see the "next" time is on two different days, whereas the "now" and "nowInLoc" dates are equals.
Found a similar issue:
func Test(t *testing.T) {
schedule, err := cron.ParseStandard("TZ=America/Los_Angeles 0 2 * * 0")
require.NoError(t, err)
zone, err := time.LoadLocation("America/Los_Angeles")
require.NoError(t, err)
now := time.Date(2022, 3, 1, 0, 0, 0, 0, zone)
expectedNext := time.Date(2022, 3, 6, 2, 0, 0, 0, zone)
nextSchedule := schedule.Next(now)
assert.Equal(t, expectedNext.String(), nextSchedule.String())
expectedNextNext := time.Date(2022, 3, 13, 2, 0, 0, 0, zone)
nextNextSchedule := schedule.Next(nextSchedule)
assert.Equal(t, expectedNextNext.String(), nextNextSchedule.String()) // Will fail, time will be 2022/3/20 02:00:00
}
On closer inspection the issue I'm referring to may be because of daylight savings time. I chose the times above for an unrelated test completely by accident apparently but in 2022, Daylight savings begins on 03/13 02:00 (moving the clock to 03:00), so 02:00 is actually not a reachable time. Sadly I can't specify a PST vs PDT, only "America/Los_Angels"... A cautionary tale I suppose.