Skip to content

Commit ab4c16f

Browse files
authored
Merge pull request robfig#61 from wannes-ds/master
Add location support
2 parents 3625689 + 17583de commit ab4c16f

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

cron.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type Cron struct {
1919
snapshot chan []*Entry
2020
running bool
2121
ErrorLog *log.Logger
22+
location *time.Location
2223
}
2324

2425
// Job is an interface for submitted cron jobs.
@@ -69,15 +70,21 @@ func (s byTime) Less(i, j int) bool {
6970
return s[i].Next.Before(s[j].Next)
7071
}
7172

72-
// New returns a new Cron job runner.
73+
// New returns a new Cron job runner, in the Local time zone.
7374
func New() *Cron {
75+
return NewWithLocation(time.Now().Location())
76+
}
77+
78+
// NewWithLocation returns a new Cron job runner.
79+
func NewWithLocation(location *time.Location) *Cron {
7480
return &Cron{
7581
entries: nil,
7682
add: make(chan *Entry),
7783
stop: make(chan struct{}),
7884
snapshot: make(chan []*Entry),
7985
running: false,
8086
ErrorLog: nil,
87+
location: location,
8188
}
8289
}
8390

@@ -125,6 +132,11 @@ func (c *Cron) Entries() []*Entry {
125132
return c.entrySnapshot()
126133
}
127134

135+
// Location gets the time zone location
136+
func (c *Cron) Location() *time.Location {
137+
return c.location
138+
}
139+
128140
// Start the cron scheduler in its own go-routine, or no-op if already started.
129141
func (c *Cron) Start() {
130142
if c.running {
@@ -150,7 +162,7 @@ func (c *Cron) runWithRecovery(j Job) {
150162
// access to the 'running' state variable.
151163
func (c *Cron) run() {
152164
// Figure out the next activation times for each entry.
153-
now := time.Now().Local()
165+
now := time.Now().In(c.location)
154166
for _, entry := range c.entries {
155167
entry.Next = entry.Schedule.Next(now)
156168
}
@@ -184,7 +196,7 @@ func (c *Cron) run() {
184196

185197
case newEntry := <-c.add:
186198
c.entries = append(c.entries, newEntry)
187-
newEntry.Next = newEntry.Schedule.Next(time.Now().Local())
199+
newEntry.Next = newEntry.Schedule.Next(time.Now().In(c.location))
188200

189201
case <-c.snapshot:
190202
c.snapshot <- c.entrySnapshot()
@@ -195,7 +207,7 @@ func (c *Cron) run() {
195207
}
196208

197209
// 'now' should be updated after newEntry and snapshot cases.
198-
now = time.Now().Local()
210+
now = time.Now().In(c.location)
199211
timer.Stop()
200212
}
201213
}

cron_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,9 @@ func TestAddWhileRunningWithDelay(t *testing.T) {
116116
defer cron.Stop()
117117
time.Sleep(5 * time.Second)
118118
var calls = 0
119-
cron.AddFunc("* * * * * *", func() { calls += 1 });
119+
cron.AddFunc("* * * * * *", func() { calls += 1 })
120120

121-
<- time.After(ONE_SECOND)
121+
<-time.After(ONE_SECOND)
122122
if calls != 1 {
123123
fmt.Printf("called %d times, expected 1\n", calls)
124124
t.Fail()
@@ -237,6 +237,33 @@ func TestLocalTimezone(t *testing.T) {
237237
}
238238
}
239239

240+
// Test that the cron is run in the given time zone (as opposed to local).
241+
func TestNonLocalTimezone(t *testing.T) {
242+
wg := &sync.WaitGroup{}
243+
wg.Add(1)
244+
245+
loc, err := time.LoadLocation("Atlantic/Cape_Verde")
246+
if err != nil {
247+
fmt.Printf("Failed to load time zone Atlantic/Cape_Verde: %+v", err)
248+
t.Fail()
249+
}
250+
251+
now := time.Now().In(loc)
252+
spec := fmt.Sprintf("%d %d %d %d %d ?",
253+
now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
254+
255+
cron := NewWithLocation(loc)
256+
cron.AddFunc(spec, func() { wg.Done() })
257+
cron.Start()
258+
defer cron.Stop()
259+
260+
select {
261+
case <-time.After(ONE_SECOND):
262+
t.FailNow()
263+
case <-wait(wg):
264+
}
265+
}
266+
240267
// Test that calling stop before start silently returns without
241268
// blocking the stop channel.
242269
func TestStopWithoutStart(t *testing.T) {

0 commit comments

Comments
 (0)