为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
扬帆大鱼 2022-06-27 16:07:15
我正在尝试找到一种方法来检查当前时间是否在时间窗口内。输入是: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 中解决这个问题吗?
查看完整描述

2 回答

?
阿波罗的战车

TA贡献1862条经验 获得超6个赞

这是解决问题的一种方法:


package main

import "time"

type window struct { time.Time }


func (w window) isDay(s string) bool {

   return w.Weekday().String() == s

}


func (w window) isHourRange(begin, end int) bool {

   return w.Hour() >= begin && w.Hour() <= end

}


func main() {

   w := window{

      time.Now(),

   }

   {

      b := w.isDay("Friday")

      println(b)

   }

   {

      b := w.isHourRange(20, 23)

      println(b)

   }

}

这假设只有一天有效,因此您需要修改它以处理多天。不过,这应该可以帮助您入门。


查看完整回答
反对 回复 2022-06-27
?
撒科打诨

TA贡献1934条经验 获得超2个赞

有很多复杂的时代。例如:

  • 如果升级日是“Søndag”(丹麦语)而不是“星期日”怎么办?

  • 我们应该在当地时间还是 UTC 工作?如果是本地的,谁的位置很重要?如果服务器在伦敦而我在旧金山,我们使用服务器的时间还是我的时间?

  • 如果升级间隔包括凌晨 2 点,那么这是否包括太平洋夏令时间凌晨 2 点和太平洋标准时间凌晨 2 点?这些时间在我住的地方相隔一小时。如果时间间隔从凌晨 2 点开始,到 2:59:59 结束,那么在许多 DST 轮班时间为一小时的地区,一年中的某一天不存在该时间。

如果您忽略所有这些复杂性——国际化 (i18n)、本地化 (l10n)、夏令时等——仍然存在一些问题,即有人可以设置日期和时间,或者升级本身可能需要一段时间,但通常我们也会忽略这些。

请注意,Gotime.Now()返回本地时间——但是,谁的位置?由于我们还没有回答使用哪个时区的问题,我们可能希望避免担心这个问题。给定其余的输入约束,让我们编写一个函数来确定提供的时间是否满足输入约束,而不是如果满足time.Now()。然后,调用者可以在用户的位置提供 UTC 时间挂钟时间:

someNow = time.Time()
localNow = someNow.In(location) // from time.LoadLocation() or similar

我们还有一些似乎与您的类型不一致的东西:

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

以小时为单位的值介于 0 和 12(含)之间很容易适合 plain int。这是否已经是一个time.Duration以纳秒表示的值?如果是这样,为什么是int64而不是time.Duration?或者它是以秒为单位的值,因此可以在 0 到 43200 之间?如果是这样,它仍然适合int

package main


import (

    "fmt"

    "strconv"

    "strings"

    "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.  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 {

    // Find OK-to-start time, and end-time.  If end exceeds

    // 24*60, we ignore the extra end time, rather than

    // allowing some minutes into the next day.

    start := h*60 + m

    end := start + d*60


    // Convert when to hour-and-minute and see if we are

    // in the allowed range.

    wh, wm, _ := when.Clock()

    now := wh*60 + wm

    if now < start || now >= end {

        // Not in hh:mm through hh+d:mm; say no.

        return false

    }


    // The time-of-day is OK; check the day-of-week.

    // We could do this earlier but by positioning it

    // here, we leave room to check to see if it's

    // the *next* day, if needed.

    if !func(wd time.Weekday) bool {

        for _, allowed := range days {

            if wd == allowed {

                return true

            }

        }

        return false

    }(when.Weekday()) {

        return false // when.Weekday() not in days[]

    }


    // time is OK, day is OK

    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.  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) {

    parts := strings.Split(hhmm, ":")

    // optional: be strict about two-digit values

    if len(parts) != 2 {

        return false, fmt.Errorf("invalid time string %q", hhmm)

    }

    h, err := strconv.Atoi(parts[0])

    if err != nil {

        return false, err

    }

    if h < 0 || h >= 60 {

        return false, fmt.Errorf("invalid hour value %s", parts[0])

    }

    m, err := strconv.Atoi(parts[1])

    if err != nil {

        return false, err

    }

    if m < 0 || m >= 60 {

        return false, fmt.Errorf("invalid minute value %s", parts[1])

    }

    var wd []time.Weekday

    for _, s := range days {

        w, err := parseWeekday(s)

        if err != nil {

            return false, err

        }

        wd = append(wd, w)

    }

    ok := startOK(when, wd, h, m, d)

    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) {

    strToWeekday := map[string]time.Weekday{

        "Sunday":    time.Sunday,

        "Monday":    time.Monday,

        "Tuesday":   time.Tuesday,

        "Wednesday": time.Wednesday,

        "Thursday":  time.Thursday,

        "Friday":    time.Friday,

        "Saturday":  time.Saturday,

    }

    if v, ok := strToWeekday[s]; ok {

        return v, nil

    }

    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() {

    okDays := []string{"Sunday", "Wednesday"}

    okStart := "04:00"

    okDuration := 2 // hours


    tfmt := "Mon Jan 2 15:04:05 2006"

    t1 := "Sat Sep 5 04:30:00 2020" // time OK, day not

    t2 := "Sun Sep 6 04:30:00 2020" // time OK, day OK

    check := func(s string, expect bool) {

        when, err := time.Parse(tfmt, s)

        if err != nil {

            panic(err)

        }

        result, err := startOKStr(when, okDays, okStart, okDuration)

        if err != nil {

            panic(err)

        }

        if result != expect {

            fmt.Printf("fail: expected %v for %q\n", expect, s)

        }

    }

    check(t1, false)

    check(t2, true)

    fmt.Println("2 tests run")

}


func main() {

    tests()

}


查看完整回答
反对 回复 2022-06-27
  • 2 回答
  • 0 关注
  • 176 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号