撒科打诨
有很多复杂的时代。例如:如果升级日是“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 mainimport ( "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()}