一尘不染

我必须发出数以千计的提醒,有什么办法避免每分钟发出响声吗?

go

我有一个像这样的结构:

type Notifications struct {
  Id int
  Start *time.Time
}

notifications := db.GetNotifications()

因此,现在我需要在时间与当前时间匹配时发出这些通知。

1  2018-11-07 09:05:00
2  2018-11-07 09:05:00
3  2018-11-07 09:15:00
..

对我来说,最简单的方法是使用代码:

ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()

for {
    <-ticker.C
    alerts := []Notification
    for _, n := range notifications {
      if n.Start == // same year, month, day, hour and minute {
        alerts = append(alerts, n) 
      }
    }

    sendNotifications(alerts)
    // TODO mutate the notifications to avoid duplicatation sending
}

有没有更有效的方法可以做到这一点?

匹配时间的最佳方法是什么,我必须在if语句中分别比较time.Now()的属性,例如年,月,日,小时和分钟吗?即,如果到达年,月,日,小时和分钟,则触发通知(忽略秒及以后的时间)


阅读 179

收藏
2020-07-02

共1个答案

一尘不染

第一件事首先,比较时间值,使用Time.EqualTime.Beforetime.After方法。比较各个组件根本不可靠:

newYork, _ := time.LoadLocation("America/New_York")

t1 := time.Date(2018, 11, 8, 4, 0, 0, 0, time.UTC)
t2 := t1.In(newYork)

fmt.Printf("%v == %v?\n", t1, t2) // 2018-11-08 04:00:00 +0000 UTC == 2018-11-07 23:00:00 -0500 EST?

fmt.Println(t1.Day() == t2.Day()) // false
fmt.Println(t2.Equal(t1))         // true

https://play.golang.org/p/06RcvuI_1Ha


对于计划问题,我将使用time.Timer

  1. 找出接下来要发出的通知
  2. 相应地设置或重置计时器
    1. 计时器触发后,转到1
    2. 如果添加了通知,请转到1
    3. 如果删除通知,则转到1

这是一个草图:

package main

import "time"

func main() {
    t := time.NewTimer(0)

    go func() {
        for range t.C {
            nextTwo := db.GetNextNotifications(2)

            // Sanity check
            if time.Until(nextTwo[0].Start) > 1*time.Second {
                // The timer went off early. Perhaps the notification has been
                // deleted?
                t.Reset(time.Until(nextTwo[0].Start))
                continue
            }

            go send(nextTwo[0])
            t.Reset(time.Until(nextTwo[1].Start))
        }
    }()

    resetTimer(t) // call as required whenever a notification is added or removed
}

func resetTimer(t *time.Timer) {
    next := db.GetNextNotification()
    t.Reset(time.Until(next.Start))
}
2020-07-02