Go语言 如何进行日期/时间比较

tvokkenx  于 2022-12-07  发布在  Go
关注(0)|答案(9)|浏览(346)

在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,我写了一个withinTimeRange(range,time)函数,但它不能完全正确地工作。(事实上,主要是第二种情况,时间范围跨越了几天。最初的部分工作正常,我只是意识到在从本地转换到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;
}

不过,我真的想做这个过滤器服务器端。

pxyaymoc

pxyaymoc1#

使用time包在Go语言中处理时间信息。
可以使用Before、After和Equal方法比较时间瞬间。Sub方法减去两个瞬间,产生持续时间。Add方法将时间和持续时间相加,产生时间。
Play示例:

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, ".")
    }
}
fhg3lkii

fhg3lkii2#

对于***两个时间之间的比较***使用time.sub()

// utc life
loc, _ := time.LoadLocation("UTC")

// setup a start and end time
createdAt := time.Now().In(loc).Add(1 * time.Hour)
expiresAt := time.Now().In(loc).Add(4 * time.Hour)

// get the diff
diff := expiresAt.Sub(createdAt)
fmt.Printf("Lifespan is %+v", diff)

程序输出:

Lifespan is 3h0m0s

http://play.golang.org/p/bbxeTtd4L6

pbgvytdp

pbgvytdp3#

对于间隔的end日期不包含小时(如“从2017-01-01到2017-01-16全天”)的情况,最好将间隔的end调整为第二天的午夜,以包括所有毫秒,如下所示:

if now.After(start) && now.Before(end.Add(24 * time.Hour).Truncate(24 * time.Hour)) {
    ...
}
xam8gpfp

xam8gpfp4#

可以使用int64的Unix纪元以秒为粒度来比较日期。如果你需要更精确的比较,如毫秒或微秒等,我想@Oleg Neumyvakin的答案是完美的。

if expirationDate.Unix() > time.Now().Unix() {
...
}
h7wcgrx3

h7wcgrx35#

如果你有兴趣比较一个时间是否接近另一个时间以进行测试,你可以使用testi assert.WithinDuration来完成这个任务。

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
}
cbjzeqam

cbjzeqam6#

最近的协议更倾向于使用RFC 3339/golang time package documentation
通常,对于坚持RFC 1123 Z格式的服务器,应该使用RFC 1123 Z而不是RFC 1123,对于新协议,应该首选RFC 3339。RFC 822、RFC 822 Z、RFC 1123和RFC 1123 Z对于格式化是有用的;它们不接受RFC允许的所有时间格式。

cutOffTime, _ := time.Parse(time.RFC3339, "2017-08-30T13:35:00Z")
// POSTDATE is a date time field in DB (datastore)
query := datastore.NewQuery("db").Filter("POSTDATE >=", cutOffTime).
bwleehnv

bwleehnv7#

the theread中所述,我们可以在测试中使用github.com/google/go-cmp/cmp包进行日期比较。

func TestDates(t *testing.T) {
    date, _ := time.Parse(time.RFC3339, "2021-11-05T12:00:00+02:00")
    dateEqual, _ := time.Parse(time.RFC3339, "2021-11-05T11:00:00+01:00")
    dateNotEqual, _ := time.Parse(time.RFC3339, "2021-11-05T12:00:01+02:00")

    assertDates(t, date, dateEqual)    //pass
    assertDates(t, date, dateNotEqual) //fail
}

func assertDates(t *testing.T, expected, actual time.Time) {
    t.Helper()

    if diff := cmp.Diff(expected, actual); diff != "" {
        t.Errorf("mismatch (-expected +actual):\n%s", diff)
    }
}
v8wbuo2f

v8wbuo2f8#

package main

import (
    "fmt"
    "time"
)

func main() {
    fmt.Println("Hello World")
    maxRep := 5
    repPeroid := 6
    expiry := maxRep * repPeroid
    fmt.Println("Expiry: ", expiry)
    fmt.Println(time.Now())
    CorrIdtime := time.Now().Add(time.Second * time.Duration(expiry)).Format(time.RFC3339)
    Notifytime := time.Now().Add(2 * time.Second * time.Duration(expiry)).Format(time.RFC3339)
    
    fmt.Println(CorrIdtime)
    fmt.Println(Notifytime)

    if CorrIdtime < Notifytime {
        fmt.Println("Discarded")
    } else {
        fmt.Println("Accepted")
        
    }
}
yyyllmsg

yyyllmsg9#

根据提议time: add Time.Comparerelated commit,将在新版本(Go 1.20)中添加time.Compare

// Compare compares the time instant t with u. If t is before u, it returns -1;
// if t is after u, it returns +1; if they're the same, it returns 0.
func (t Time) Compare(u Time) int {

样品

var t1, t2 Time

result := t1.Compare(t2)

相关问题