猿问

如何编写一个函数来检查当前时间是否在时间窗口内

我正在尝试找到一种方法来检查当前时间是否在时间窗口内。

输入是:

upgradeDay []string- 几天(例如["Sunday", "Tuesday"])

upgradetime string- 小时:分钟(例如"22:04")

upgradeDuration int64- 时间量,从upgradetime时间窗口有效的时间开始。最长可达 12 小时。

完整示例:

upgradeDay= ["Sunday", Tuesday"] , upgradetime= "10:00", upgradeDuration= 2 -> 时间窗口是每个星期日和星期二,从 10:00 到 12:00 点。我试着写以下功能,但它在天/月/年之间的过渡中不起作用:


func isInsideTimeWindow(upgradeDay []string, upgradeTime string, upgradeDuration int64) bool {

    now := time.Now()


    ut := strings.Split(upgradeTime, ":")

    hour, _ := strconv.Atoi(ut[0])

    min, _ := strconv.Atoi(ut[1])


    // !! not working when now it's Monday 00:01 and got: upgradeDay = ["Sunday"], upgradeTime = 23:59, upgradeDuration = 2

    twStart := time.Date(now.Year(), now.Month(), now.Day(), hour, min, 0, 0, now.Location())

    twEnd := twStart.Add(time.Hour * time.Duration(upgradeDuration))



    if !(now.After(twStart) && now.Before(twEnd)) {

        return false

    }

    

    wd := now.Weekday().String()

    

    for i := range upgradeDay {

      if upgradeDay[i] == wd  {

         return true

      }

    }

    

    return false

}

有人知道如何在 Go 中解决这个问题吗?


扬帆大鱼
浏览 177回答 2
2回答

阿波罗的战车

这是解决问题的一种方法:package mainimport "time"type window struct { time.Time }func (w window) isDay(s string) bool {&nbsp; &nbsp;return w.Weekday().String() == s}func (w window) isHourRange(begin, end int) bool {&nbsp; &nbsp;return w.Hour() >= begin && w.Hour() <= end}func main() {&nbsp; &nbsp;w := window{&nbsp; &nbsp; &nbsp; time.Now(),&nbsp; &nbsp;}&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; b := w.isDay("Friday")&nbsp; &nbsp; &nbsp; println(b)&nbsp; &nbsp;}&nbsp; &nbsp;{&nbsp; &nbsp; &nbsp; b := w.isHourRange(20, 23)&nbsp; &nbsp; &nbsp; println(b)&nbsp; &nbsp;}}这假设只有一天有效,因此您需要修改它以处理多天。不过,这应该可以帮助您入门。

撒科打诨

有很多复杂的时代。例如:如果升级日是“Søndag”(丹麦语)而不是“星期日”怎么办?我们应该在当地时间还是 UTC 工作?如果是本地的,谁的位置很重要?如果服务器在伦敦而我在旧金山,我们使用服务器的时间还是我的时间?如果升级间隔包括凌晨 2 点,那么这是否包括太平洋夏令时间凌晨 2 点和太平洋标准时间凌晨 2 点?这些时间在我住的地方相隔一小时。如果时间间隔从凌晨 2 点开始,到 2:59:59 结束,那么在许多 DST 轮班时间为一小时的地区,一年中的某一天不存在该时间。如果您忽略所有这些复杂性——国际化 (i18n)、本地化 (l10n)、夏令时等——仍然存在一些问题,即有人可以设置日期和时间,或者升级本身可能需要一段时间,但通常我们也会忽略这些。请注意,Gotime.Now()返回本地时间——但是,谁的位置?由于我们还没有回答使用哪个时区的问题,我们可能希望避免担心这个问题。给定其余的输入约束,让我们编写一个函数来确定提供的时间是否满足输入约束,而不是如果满足time.Now()。然后,调用者可以在用户的位置提供 UTC 时间或挂钟时间:someNow&nbsp;=&nbsp;time.Time() localNow&nbsp;=&nbsp;someNow.In(location)&nbsp;//&nbsp;from&nbsp;time.LoadLocation()&nbsp;or&nbsp;similar我们还有一些似乎与您的类型不一致的东西:upgradeDuration int64- 时间量,从时间窗口有效的升级时间开始。最长可达 12 小时以小时为单位的值介于 0 和 12(含)之间很容易适合 plain&nbsp;int。这是否已经是一个time.Duration以纳秒表示的值?如果是这样,为什么是int64而不是time.Duration?或者它是以秒为单位的值,因此可以在 0 到 43200 之间?如果是这样,它仍然适合int。package mainimport (&nbsp; &nbsp; "fmt"&nbsp; &nbsp; "strconv"&nbsp; &nbsp; "strings"&nbsp; &nbsp; "time")// startOK determines whether the given starting-time is within a// time window.//// The window starts at a time given as two integers,// h and m, representing hours and minutes, and extends for// the given duration d in hours, which in general should not// extend into another day.&nbsp; If it does extend past the end of// the day into the next day, we ignore the extension.//// The days on which the time *is* in that window are further// limited by the days[] slice of Weekday values.//// Note: it would probably be sensible to return a time.Duration// value that is how long it will be until the next OK time, but// we leave that as an exercise.//// It would also be sensible to allow the duration d to extend// into the next day, which is also left as an exercise.func startOK(when time.Time, days []time.Weekday, h, m, d int) bool {&nbsp; &nbsp; // Find OK-to-start time, and end-time.&nbsp; If end exceeds&nbsp; &nbsp; // 24*60, we ignore the extra end time, rather than&nbsp; &nbsp; // allowing some minutes into the next day.&nbsp; &nbsp; start := h*60 + m&nbsp; &nbsp; end := start + d*60&nbsp; &nbsp; // Convert when to hour-and-minute and see if we are&nbsp; &nbsp; // in the allowed range.&nbsp; &nbsp; wh, wm, _ := when.Clock()&nbsp; &nbsp; now := wh*60 + wm&nbsp; &nbsp; if now < start || now >= end {&nbsp; &nbsp; &nbsp; &nbsp; // Not in hh:mm through hh+d:mm; say no.&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }&nbsp; &nbsp; // The time-of-day is OK; check the day-of-week.&nbsp; &nbsp; // We could do this earlier but by positioning it&nbsp; &nbsp; // here, we leave room to check to see if it's&nbsp; &nbsp; // the *next* day, if needed.&nbsp; &nbsp; if !func(wd time.Weekday) bool {&nbsp; &nbsp; &nbsp; &nbsp; for _, allowed := range days {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if wd == allowed {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return false&nbsp; &nbsp; }(when.Weekday()) {&nbsp; &nbsp; &nbsp; &nbsp; return false // when.Weekday() not in days[]&nbsp; &nbsp; }&nbsp; &nbsp; // time is OK, day is OK&nbsp; &nbsp; return true}// startOKstr is like startOK but the window starts at a time// given as a string encoded as hh:mm, with the days being a// slice of strings instead of Weekday.&nbsp; Because of these strings,// parsing can produce an error, so this function has an error// return.func startOKStr(when time.Time, days []string, hhmm string, d int) (bool, error) {&nbsp; &nbsp; parts := strings.Split(hhmm, ":")&nbsp; &nbsp; // optional: be strict about two-digit values&nbsp; &nbsp; if len(parts) != 2 {&nbsp; &nbsp; &nbsp; &nbsp; return false, fmt.Errorf("invalid time string %q", hhmm)&nbsp; &nbsp; }&nbsp; &nbsp; h, err := strconv.Atoi(parts[0])&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return false, err&nbsp; &nbsp; }&nbsp; &nbsp; if h < 0 || h >= 60 {&nbsp; &nbsp; &nbsp; &nbsp; return false, fmt.Errorf("invalid hour value %s", parts[0])&nbsp; &nbsp; }&nbsp; &nbsp; m, err := strconv.Atoi(parts[1])&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; return false, err&nbsp; &nbsp; }&nbsp; &nbsp; if m < 0 || m >= 60 {&nbsp; &nbsp; &nbsp; &nbsp; return false, fmt.Errorf("invalid minute value %s", parts[1])&nbsp; &nbsp; }&nbsp; &nbsp; var wd []time.Weekday&nbsp; &nbsp; for _, s := range days {&nbsp; &nbsp; &nbsp; &nbsp; w, err := parseWeekday(s)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false, err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; wd = append(wd, w)&nbsp; &nbsp; }&nbsp; &nbsp; ok := startOK(when, wd, h, m, d)&nbsp; &nbsp; return ok, nil}// parseWeekday handles weekday strings.//// Ideally we'd use time.Parse for this, as it already has// these in it, but they are not exported in usable form.func parseWeekday(s string) (time.Weekday, error) {&nbsp; &nbsp; strToWeekday := map[string]time.Weekday{&nbsp; &nbsp; &nbsp; &nbsp; "Sunday":&nbsp; &nbsp; time.Sunday,&nbsp; &nbsp; &nbsp; &nbsp; "Monday":&nbsp; &nbsp; time.Monday,&nbsp; &nbsp; &nbsp; &nbsp; "Tuesday":&nbsp; &nbsp;time.Tuesday,&nbsp; &nbsp; &nbsp; &nbsp; "Wednesday": time.Wednesday,&nbsp; &nbsp; &nbsp; &nbsp; "Thursday":&nbsp; time.Thursday,&nbsp; &nbsp; &nbsp; &nbsp; "Friday":&nbsp; &nbsp; time.Friday,&nbsp; &nbsp; &nbsp; &nbsp; "Saturday":&nbsp; time.Saturday,&nbsp; &nbsp; }&nbsp; &nbsp; if v, ok := strToWeekday[s]; ok {&nbsp; &nbsp; &nbsp; &nbsp; return v, nil&nbsp; &nbsp; }&nbsp; &nbsp; return time.Sunday, fmt.Errorf("invalid day-of-week %q", s)}// tests should be converted to real tests and put in// a separate file.func tests() {&nbsp; &nbsp; okDays := []string{"Sunday", "Wednesday"}&nbsp; &nbsp; okStart := "04:00"&nbsp; &nbsp; okDuration := 2 // hours&nbsp; &nbsp; tfmt := "Mon Jan 2 15:04:05 2006"&nbsp; &nbsp; t1 := "Sat Sep 5 04:30:00 2020" // time OK, day not&nbsp; &nbsp; t2 := "Sun Sep 6 04:30:00 2020" // time OK, day OK&nbsp; &nbsp; check := func(s string, expect bool) {&nbsp; &nbsp; &nbsp; &nbsp; when, err := time.Parse(tfmt, s)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; result, err := startOKStr(when, okDays, okStart, okDuration)&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic(err)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if result != expect {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("fail: expected %v for %q\n", expect, s)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; check(t1, false)&nbsp; &nbsp; check(t2, true)&nbsp; &nbsp; fmt.Println("2 tests run")}func main() {&nbsp; &nbsp; tests()}
随时随地看视频慕课网APP

相关分类

Go
我要回答