Reputation: 190
Is there any way for designing a timer that expires on a specific future time in Golang ? I mean a timer that expires on 2AM (let the current time be 12AM). I know one way is to use,
timer(target_future_time - current_time)
but doesn't seem to be an exact way of doing it (may not be accurate on considering the execution time). Can anyone help please?
Upvotes: 2
Views: 4396
Reputation: 876
The following code achieves your purpose. All you've to do is call ScheduleAlarm() in the manner shown in the main() function below.
package main
import (
"strings"
"strconv"
"fmt"
"time"
)
// A struct for representing time.
type Time struct {
Hh int // Hours.
Mm int // Minutes.
Ss int // Seconds.
}
func main() {
/*
Set the alarm as shown below.
Time must be specified in 24 hour clock format.
Also, pass the callback to be called after the alarm is triggered.
*/
alarm := ScheduleAlarm(Time{23, 28, 0}, func() {
fmt.Println("alarm received")
})
// Do your stuff.
for i := 0; i < 10; i++ {
fmt.Println(i)
time.Sleep(2 * time.Second)
}
// Don't forget to call the below line whenever you want to block.
<-alarm
}
// Call this function to schedule the alarm. The callback will be called after the alarm is triggered.
func ScheduleAlarm(alarmTime Time, callback func() ()) (endRecSignal chan string) {
endRecSignal = make(chan string)
go func() {
timeSplice := strings.Split(time.Now().Format("15:04:05"), ":")
hh, _ := strconv.Atoi(timeSplice[0])
mm, _ := strconv.Atoi(timeSplice[1])
ss, _ := strconv.Atoi(timeSplice[2])
startAlarm := GetDiffSeconds(Time{hh, mm, ss}, alarmTime)
// Setting alarm.
time.AfterFunc(time.Duration(startAlarm) * time.Second, func() {
callback()
endRecSignal <- "finished recording"
close(endRecSignal)
})
}()
return
}
func GetDiffSeconds(fromTime, toTime Time) int {
fromSec := GetSeconds(fromTime)
toSec := GetSeconds(toTime)
diff := toSec - fromSec
if diff < 0 {
return diff + 24 * 60 * 60
} else {
return diff
}
}
func GetSeconds(time Time) int {
return time.Hh * 60 * 60 + time.Mm * 60 + time.Ss
}
Hope this helps.
Upvotes: 0
Reputation: 299
In golang,maybe there are two way create ticker,just like the following:
package main
import (
"fmt"
"time"
)
func main() {
//第一种实现方式
ticker1 := time.NewTicker(1 * time.Second)
i := 1
for c := range ticker1.C {
i++
fmt.Println(c.Format("2006/01/02 15:04:05.999999999"))
if i > 5 {
ticker1.Stop()
break
}
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 1 Finished.")
//第二种实现方式
i = 1
ticker2 := time.AfterFunc(1*time.Second, func() {
i++
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"))
})
for {
select {
case <-ticker2.C:
fmt.Println("nsmei")
case <-time.After(3 * time.Second):
if i <= 5 {
ticker2.Reset(1 * time.Second)
continue
}
goto BRK
}
BRK:
ticker2.Stop()
break
}
fmt.Println(time.Now().Format("2006/01/02 15:04:05.999999999"), " 2 Finished.")
}
Output:
2016/01/26 16:46:34.261248567
2016/01/26 16:46:35.256381743
2016/01/26 16:46:36.259717152
2016/01/26 16:46:37.260320837
2016/01/26 16:46:38.259312704
2016/01/26 16:46:38.259410752 1 Finished.
2016/01/26 16:46:39.260604274
2016/01/26 16:46:42.261091322
2016/01/26 16:46:45.263136257
2016/01/26 16:46:48.264193517
2016/01/26 16:46:51.265655137
2016/01/26 16:46:53.265722632 2 Finished.
According to the execution,the first is more precise than the second.
In your case,you can use time.Time.Sub()
to calculate the duration,and execute once using the second method,the rest using the first method.
I hope these help you!
Upvotes: 2