Skip to content

Instantly share code, notes, and snippets.

@arshamalh
Created August 7, 2025 14:43
Show Gist options
  • Save arshamalh/27ff86d35903baf607b204b492a369b1 to your computer and use it in GitHub Desktop.
Save arshamalh/27ff86d35903baf607b204b492a369b1 to your computer and use it in GitHub Desktop.
Tick at specific times everyday
package main
import (
"errors"
"strconv"
"strings"
"time"
)
var (
ErrTimeFormat = errors.New("time format error")
)
// Runs everyday at a specified time
// at examples: "10:30", "15:22"
func NewTickAtTime(at string) (<-chan time.Time, error) {
hour, min, err := formatTime(at)
if err != nil {
return nil, err
}
tickChan := make(chan time.Time)
// save atTime start as duration from midnight
atTime := time.Duration(hour)*time.Hour + time.Duration(min)*time.Minute
now := time.Now()
firstTickAt := getDate(now).Add(atTime)
if firstTickAt.Before(now) {
firstTickAt = firstTickAt.Add(time.Hour * 24)
}
time.AfterFunc(time.Until(firstTickAt), func() {
tickChan <- time.Now()
// Use NewTicker and return it if you need to stop the ticker eventually.
for tick := range time.Tick(time.Hour * 24) {
tickChan <- tick
}
})
return tickChan, nil
}
func getDate(t time.Time) time.Time {
return time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, nil)
}
func formatTime(t string) (hour, min int, err error) {
ts := strings.Split(t, ":")
if len(ts) != 2 {
return 0, 0, ErrTimeFormat
}
if hour, err = strconv.Atoi(ts[0]); err != nil {
return 0, 0, err
}
if min, err = strconv.Atoi(ts[1]); err != nil {
return 0, 0, err
}
if hour < 0 || hour > 23 || min < 0 || min > 59 {
return 0, 0, ErrTimeFormat
}
return hour, min, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment