Datetime 如何进行日期/时间比较

Datetime 如何进行日期/时间比较,datetime,go,datetime-comparison,Datetime,Go,Datetime Comparison,在Go中进行日期比较有什么选择吗?我必须独立地根据日期和时间对数据进行排序。所以我可能允许一个对象出现在一个日期范围内,只要它也出现在一个时间范围内。在这个模型中,我不能简单地选择最早的日期、最早的时间/最晚的日期、最晚的时间和Unix秒来比较它们。如果有任何建议,我将不胜感激 最后,我编写了一个时间解析字符串比较模块来检查时间是否在某个范围内。然而,这并不顺利;我有一些悬而未决的问题。我会把它贴在这里只是为了好玩,但我希望有更好的方式来比较时间 package main import (

在Go中进行日期比较有什么选择吗?我必须独立地根据日期和时间对数据进行排序。所以我可能允许一个对象出现在一个日期范围内,只要它也出现在一个时间范围内。在这个模型中,我不能简单地选择最早的日期、最早的时间/最晚的日期、最晚的时间和Unix秒来比较它们。如果有任何建议,我将不胜感激

最后,我编写了一个时间解析字符串比较模块来检查时间是否在某个范围内。然而,这并不顺利;我有一些悬而未决的问题。我会把它贴在这里只是为了好玩,但我希望有更好的方式来比较时间

package main

import (
    "strconv"
    "strings"
)

func tryIndex(arr []string, index int, def string) string {
    if index <= len(arr)-1 {
        return arr[index]
    }
    return def
}

/*
 * Takes two strings of format "hh:mm:ss" and compares them.
 * Takes a function to compare individual sections (split by ":").
 * Note: strings can actually be formatted like "h", "hh", "hh:m",
 * "hh:mm", etc. Any missing parts will be added lazily.
 */
func timeCompare(a, b string, compare func(int, int) (bool, bool)) bool {
    aArr := strings.Split(a, ":")
    bArr := strings.Split(b, ":")
    // Catches margins.
    if (b == a) {
        return true
    }
    for i := range aArr {
        aI, _ := strconv.Atoi(tryIndex(aArr, i, "00"))
        bI, _ := strconv.Atoi(tryIndex(bArr, i, "00"))
        res, flag := compare(aI, bI)
        if res {
            return true
        } else if flag { // Needed to catch case where a > b and a is the lower limit
            return false
        }
    }
    return false
}

func timeGreaterEqual(a, b int) (bool, bool) {return a > b, a < b}
func timeLesserEqual(a, b int) (bool, bool) {return a < b, a > b}

/*
 * Returns true for two strings formmated "hh:mm:ss".
 * Note: strings can actually be formatted like "h", "hh", "hh:m",
 * "hh:mm", etc. Any missing parts will be added lazily.
 */
func withinTime(timeRange, time string) bool {
    rArr := strings.Split(timeRange, "-")
    if timeCompare(rArr[0], rArr[1], timeLesserEqual) {
        afterStart := timeCompare(rArr[0], time, timeLesserEqual)
        beforeEnd := timeCompare(rArr[1], time, timeGreaterEqual)
        return afterStart && beforeEnd
    }
    // Catch things like `timeRange := "22:00:00-04:59:59"` which will happen
    // with UTC conversions from local time.
    // THIS IS THE BROKEN PART I BELIEVE
    afterStart := timeCompare(rArr[0], time, timeLesserEqual)
    beforeEnd := timeCompare(rArr[1], time, timeGreaterEqual)
    return afterStart || beforeEnd
}
所以TLDR,我写了一个WithinterRange时间函数,但它不能完全正确工作。事实上,大多数情况下只是第二种情况,即时间范围跨越几天的情况被打破。最初的部分起作用了,我刚刚意识到在从本地转换到UTC时需要考虑这一点

如果有更好的内置方式,我很想听听

注: 举个例子,我用Javascript解决了这个问题,使用了以下函数:

function withinTime(start, end, time) {
    var s = Date.parse("01/01/2011 "+start);
    var e = Date.parse("01/0"+(end=="24:00:00"?"2":"1")+"/2011 "+(end=="24:00:00"?"00:00:00":end));
    var t = Date.parse("01/01/2011 "+time);
    return s <= t && e >= t;
}
但是,我确实希望在服务器端执行此筛选。

使用包处理Go中的时间信息

可以使用Before、After和Equal来比较时间瞬间 方法。子方法减去两个瞬间,产生一个持续时间。 Add方法添加时间和持续时间,生成时间

例如:

package main

import (
    "fmt"
    "time"
)

func inTimeSpan(start, end, check time.Time) bool {
    return check.After(start) && check.Before(end)
}

func main() {
    start, _ := time.Parse(time.RFC822, "01 Jan 15 10:00 UTC")
    end, _ := time.Parse(time.RFC822, "01 Jan 16 10:00 UTC")

    in, _ := time.Parse(time.RFC822, "01 Jan 15 20:00 UTC")
    out, _ := time.Parse(time.RFC822, "01 Jan 17 10:00 UTC")

    if inTimeSpan(start, end, in) {
        fmt.Println(in, "is between", start, "and", end, ".")
    }

    if !inTimeSpan(start, end, out) {
        fmt.Println(out, "is not between", start, "and", end, ".")
    }
}

下面解决了将字符串转换为日期的问题

包干管

import (
    "fmt"
    "time"
)

func main() {
    value  := "Thu, 05/19/11, 10:47PM"
    // Writing down the way the standard time would look like formatted our way
    layout := "Mon, 01/02/06, 03:04PM"
    t, _ := time.Parse(layout, value)
    fmt.Println(t)
}

// => "Thu May 19 22:47:00 +0000 2011"
用于两次使用之间的比较

程序输出:

Lifespan is 3h0m0s

比如说,当你的间歇期结束时,它是一个没有小时的日期,比如 从2017-01-01到2017-01-16的全天,最好将间隔时间调整为23小时59分59秒,如:

end = end.Add(time.Duration(23*time.Hour) + time.Duration(59*time.Minute) + time.Duration(59*time.Second)) 

if now.After(start) && now.Before(end) {
    ...
}

最近的协议倾向于使用RFC3339

通常,对于坚持该格式的服务器,应使用RFC1123Z而不是RFC1123,对于新协议,应首选RFC3339。RFC822、RFC822Z、RFC1123和RFC1123Z用于格式化;与time.Parse一起使用时,它们不接受RFC允许的所有时间格式


如果您有兴趣为了测试目的比较一个时间是否接近另一个时间,您可以使用。例如:

expectedTime := time.Now()
actualTime := expectedTime.Add(100*time.Millisecond)
assert.WithinDuration(t, expectedTime, actualTime, 1*time.Second) // pass
assert.WithinDuration(t, expectedTime, actualTime, 1*time.Millisecond) // fail
否则,assert.WithinDuration的实现可以在代码中重新使用,以确定两个时间之间的接近程度,从另一个日期减去一个日期会产生时差:

func WithinDuration(expected, actual time.Time, delta time.Duration) bool {
   dt := expected.Sub(actual)
   return dt >= -delta && dt <= delta
}

也许我看不懂,但我没有看到任何关于时间比较的东西。如果有的话,你能给我指一篇确切的文章吗?试着比较一下,或者找出两次之间的区别。报告时间瞬间t是否在u之后。诡异这一切都很好,但与问题无关,是吗?你是对的@matthiaskrull。它并没有回答比较日期的问题,但在一定程度上帮助了轻松解析日期。还有一些人也这样做了。我只是说,在评论中链接一些东西会比用随机有用的位来回答更合适。这正是我需要比较存储的时间戳和当前时间的地方。这是最好的答案。
expectedTime := time.Now()
actualTime := expectedTime.Add(100*time.Millisecond)
assert.WithinDuration(t, expectedTime, actualTime, 1*time.Second) // pass
assert.WithinDuration(t, expectedTime, actualTime, 1*time.Millisecond) // fail
func WithinDuration(expected, actual time.Time, delta time.Duration) bool {
   dt := expected.Sub(actual)
   return dt >= -delta && dt <= delta
}