Shalin LK
Shalin LK

Reputation: 190

Alarm like timer functionality in Golang

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

Answers (2)

Gautham
Gautham

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

joy miao
joy miao

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

Related Questions