【问题标题】:How to compare clock portion of time.Time如何比较时间的时钟部分。时间
【发布时间】:2020-11-21 00:09:40
【问题描述】:

我有一个 time.Time start "2019-07-02 01:00:00" 我想写一个函数来告诉我 time.Now() 是否在开始时间前 x 分钟的范围内(忽略日期,只是时钟部分01:00:00

例如:

案例一

x = 30 minutes
time.Now() = "2020-11-20 00:45:00" //return True because 00:45:00 is 15 minutes before 01:00:00
time.Now() = "2020-11-20 00:20:00" //return False because 00:20:00 is 40 minutes before 01:00:00

案例二

x = 120 minutes
time.Now() = "2020-11-20 23:00:00" //return True because 23:00:00 is 120 minutes/2 hours before 01:00:00 (like 11pm is 2 hours before 1am of next day)
time.Now() = "2020-11-20 00:00:00" //return True
time.Now() = "2020-11-20 00:20:00" //return True
time.Now() = "2020-11-20 22:30:00" //returns False

案例三

x=1440 // 24 hours
always return true

我现在只解决了案例一而不是案例二。我查看了 go 的时间包,但没有找到任何有效解决此问题的方法。有什么想法吗?

now := time.Now()
trigger : = start.Sub(time.Minute * x))
triggerClock :=  trigger.Sub(trigger.Truncate(24 * time.Hour)) //extract clock portion
nowClock := now.Sub(now.Truncate(24*time.Hour)) //extract clock portion
diff := nowClock.Seconds() - triggerClock.Seconds()
if diff >= 0 && diff < x {
    return true
}

【问题讨论】:

    标签: datetime go time


    【解决方案1】:

    有多种方法可以解决此问题,选择正确的方法取决于“开始时间前 x 分钟”的含义:

    • “仅时钟部分”我假设您的意思是当天,或者,如果当前时间在“时钟部分”之后,则表示明天。
    • 夏令时的开始/结束可能会导致明显的答案可能不正确(但您需要指定在这些时间应该发生什么)。
    • 是否需要考虑时区? (我暂时不会假设,但值得考虑!)。

    我会通过计算目标时间和检查时间之间的分钟数来解决这个问题,如下所示:

    func MinutesBefore(target time.Time, check time.Time) int {
        t := time.Date(check.Year(), check.Month(), check.Day(), target.Hour(), target.Minute(), target.Second(), target.Nanosecond(), target.Location())
        if t.Before(check) {
            t = time.Date(check.Year(), check.Month(), check.Day()+1, target.Hour(), target.Minute(), target.Second(), target.Nanosecond(), target.Location())
        }
        return int(t.Sub(check).Minutes())
    }
    

    the playground 中尝试一些测试用例。

    【讨论】:

      【解决方案2】:

      截断差异可能比截断时间更容易,例如:

      package main
      
      import (
          "log"
          "time"
      )
      
      const (
          day = time.Hour * 24
      )
      
      func within(t1, t2 time.Time, epsilon time.Duration) bool {
          delta := t1.Sub(t2)
          delta = (delta - delta.Truncate(day))
      
          // Take absolute value of delta.
          if delta < 0 {
              delta = -delta
          }
      
          // Reduce if the times are closer across midnight.
          if adjusted := day - delta; adjusted < delta {
              delta = adjusted
          }
      
          return delta <= epsilon
      }
      
      func main() {
          start := time.Date(2019, 7, 2, 01, 0, 0, 0, time.UTC)
      
          for _, tc := range []struct {
              t    time.Time
              e    time.Duration
              want bool
          }{
              {
                  t:    time.Date(2020, 11, 20, 0, 45, 0, 0, time.UTC),
                  e:    time.Minute * 30,
                  want: true,
              },
              {
                  t:    time.Date(2020, 11, 20, 0, 20, 0, 0, time.UTC),
                  e:    time.Minute * 30,
                  want: false,
              },
              {
                  t:    time.Date(2020, 11, 20, 23, 0, 0, 0, time.UTC),
                  e:    time.Minute * 120,
                  want: true,
              },
              {
                  t:    time.Date(2020, 11, 20, 0, 0, 0, 0, time.UTC),
                  e:    time.Minute * 120,
                  want: true,
              },
              {
                  t:    time.Date(2020, 11, 20, 0, 20, 0, 0, time.UTC),
                  e:    time.Minute * 120,
                  want: true,
              },
              {
                  t:    time.Date(2020, 11, 20, 22, 30, 0, 0, time.UTC),
                  e:    time.Minute * 120,
                  want: false,
              },
              {
                  t:    time.Date(2020, 11, 20, 13, 0, 0, 0, time.UTC),
                  e:    time.Hour * 24,
                  want: true,
              },
          } {
              if within(start, tc.t, tc.e) != tc.want {
                  log.Fatalf("test failed for %v, %v, %v", start, tc.t, tc.e)
              }
          }
      }
      

      您说您想要为 24 小时或更长时间的任何 x 返回 true,但请注意,由于您想要案例 2 的第一个示例中给出的行为,结果证明 true 将对于任何 12 小时或更长时间的 x 都会返回,因为如果您接受 24 小时内或跨过 24 小时的最近距离,这是两次之间的最大距离。

      【讨论】:

        【解决方案3】:

        您可以使用模板15:04:05 解析日期的时间分数(时钟部分)

        var start time.Time
        start, _ = time.Parse("15:04:05", "01:00:00")
        

        我们想用now 减去start 并检查结果是否不大于x

        if start.Sub(now).Minutes() <= x.Minutes() {
            return true
        }
        

        这适用于我们的第一个案例,但是当我们中间有一个午夜时它会失败。解决我们可以从now中减去一天的问题

        if start.Before(now) {
            now = now.Add(-time.Hour * 24)
        }
        

        那么你就有了

        func rangeOf(x time.Duration, start time.Time, now time.Time) bool {
            if start.Before(now) {
                now = now.Add(-time.Hour * 24)
            }
            if start.Sub(now).Minutes() <= x.Minutes() {
                return true
            }
        
            return false
        }
        

        这里是案例二测试

        func main() {
            x := 120 * time.Minute
            var now time.Time
        
            now, _ = time.Parse("15:04:05", "23:00:00")
            fmt.Printf("%t\n", rangeOf(x, start, now))
        
            now, _ = time.Parse("15:04:05", "00:00:00")
            fmt.Printf("%t\n", rangeOf(x, start, now))
        
            now, _ = time.Parse("15:04:05", "00:20:00")
            fmt.Printf("%t\n", rangeOf(x, start, now))
        
            now, _ = time.Parse("15:04:05", "22:30:00")
            fmt.Printf("%t\n", rangeOf(x, start, now))
        }
        

        所有测试用例都在这里https://play.golang.com/p/Ijs-rlPCIIJ

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-22
          • 2013-07-25
          • 2017-04-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多