Skip to content

Commit b157316

Browse files
committed
Merge branch 'master' of https://github.com/robfig/cron
; Conflicts: ; cron_test.go
2 parents 7f3990a + df38d32 commit b157316

File tree

5 files changed

+415
-106
lines changed

5 files changed

+415
-106
lines changed

cron.go

+26-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// This library implements a cron spec parser and runner. See the README for
2-
// more details.
31
package cron
42

53
import (
@@ -19,6 +17,7 @@ type Cron struct {
1917
snapshot chan []*Entry
2018
running bool
2119
ErrorLog *log.Logger
20+
location *time.Location
2221
}
2322

2423
// Job is an interface for submitted cron jobs.
@@ -74,15 +73,21 @@ func (s byTime) Less(i, j int) bool {
7473
return s[i].Next.Before(s[j].Next)
7574
}
7675

77-
// New returns a new Cron job runner.
76+
// New returns a new Cron job runner, in the Local time zone.
7877
func New() *Cron {
78+
return NewWithLocation(time.Now().Location())
79+
}
80+
81+
// NewWithLocation returns a new Cron job runner.
82+
func NewWithLocation(location *time.Location) *Cron {
7983
return &Cron{
8084
entries: nil,
8185
add: make(chan *Entry),
8286
stop: make(chan struct{}),
8387
snapshot: make(chan []*Entry),
8488
running: false,
8589
ErrorLog: nil,
90+
location: location,
8691
}
8792
}
8893

@@ -131,6 +136,11 @@ func (c *Cron) Entries() []*Entry {
131136
return c.entrySnapshot()
132137
}
133138

139+
// Location gets the time zone location
140+
func (c *Cron) Location() *time.Location {
141+
return c.location
142+
}
143+
134144
// Start the cron scheduler in its own go-routine, or no-op if already started.
135145
func (c *Cron) Start() {
136146
if c.running {
@@ -140,6 +150,15 @@ func (c *Cron) Start() {
140150
go c.run()
141151
}
142152

153+
// Run the cron scheduler, or no-op if already running.
154+
func (c *Cron) Run() {
155+
if c.running {
156+
return
157+
}
158+
c.running = true
159+
c.run()
160+
}
161+
143162
func (c *Cron) runWithRecovery(j Job) {
144163
defer func() {
145164
if r := recover(); r != nil {
@@ -156,7 +175,7 @@ func (c *Cron) runWithRecovery(j Job) {
156175
// access to the 'running' state variable.
157176
func (c *Cron) run() {
158177
// Figure out the next activation times for each entry.
159-
now := time.Now().Local()
178+
now := time.Now().In(c.location)
160179
for _, entry := range c.entries {
161180
entry.Next = entry.Schedule.Next(now)
162181
}
@@ -177,6 +196,7 @@ func (c *Cron) run() {
177196
timer := time.NewTimer(effective.Sub(now))
178197
select {
179198
case now = <-timer.C:
199+
now = now.In(c.location)
180200
// Run every entry whose next time was this effective time.
181201
for _, e := range c.entries {
182202
if e.Next != effective {
@@ -191,7 +211,7 @@ func (c *Cron) run() {
191211

192212
case newEntry := <-c.add:
193213
c.entries = append(c.entries, newEntry)
194-
newEntry.Next = newEntry.Schedule.Next(time.Now().Local())
214+
newEntry.Next = newEntry.Schedule.Next(time.Now().In(c.location))
195215

196216
case <-c.snapshot:
197217
c.snapshot <- c.entrySnapshot()
@@ -202,7 +222,7 @@ func (c *Cron) run() {
202222
}
203223

204224
// 'now' should be updated after newEntry and snapshot cases.
205-
now = time.Now().Local()
225+
now = time.Now().In(c.location)
206226
timer.Stop()
207227
}
208228
}

cron_test.go

+31-4
Original file line numberDiff line numberDiff line change
@@ -219,19 +219,46 @@ func TestRunningMultipleSchedules(t *testing.T) {
219219
// Test that the cron is run in the local time zone (as opposed to UTC).
220220
func TestLocalTimezone(t *testing.T) {
221221
wg := &sync.WaitGroup{}
222-
wg.Add(1)
222+
wg.Add(2)
223223

224224
now := time.Now().Local()
225-
spec := fmt.Sprintf("%d %d %d %d %d ?",
226-
now.Second()+1, now.Minute(), now.Hour(), now.Day(), now.Month())
225+
spec := fmt.Sprintf("%d,%d %d %d %d %d ?",
226+
now.Second()+1, now.Second()+2, now.Minute(), now.Hour(), now.Day(), now.Month())
227227

228228
cron := New()
229229
cron.AddFunc("", spec, func() { wg.Done() })
230230
cron.Start()
231231
defer cron.Stop()
232232

233233
select {
234-
case <-time.After(ONE_SECOND):
234+
case <-time.After(ONE_SECOND * 2):
235+
t.FailNow()
236+
case <-wait(wg):
237+
}
238+
}
239+
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(2)
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 %d ?",
253+
now.Second()+1, now.Second()+2, 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 * 2):
235262
t.FailNow()
236263
case <-wait(wg):
237264
}

0 commit comments

Comments
 (0)