如何进行日期/时间比较

在 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,我写了一个 inTimeRange (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;
}

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

202739 次浏览

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

时间瞬间可以使用“之前”、“之后”和“相等”进行比较 Sub 方法减去两个实例,生成一个 Duration。 Add 方法添加一个 Time 和一个 Duration,生成一个 Time。

播放 示例:

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

对于 两次比较使用 时间

// 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

如果间隔的 end日期不包含像 “从2017-01-01到2017-01-16的一整天”最好将间隔的 end调整到第二天的午夜,以包括所有这样的毫秒:

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

最近的协议更喜欢在每个 Golang time 软件包文档中使用 RFC3339。

一般来说,对于坚持使用 RFC1123Z 格式的服务器,应该使用 RFC1123Z 代替 RFC1123,而对于新协议,应该首选 RFC3339。RFC822、 RFC822Z、 RFC1123和 RFC1123Z 对于格式化非常有用; 当与时间一起使用时。解析它们并不接受 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).

如果您有兴趣为了测试目的比较一个时间是否接近另一个时间,那么可以使用 作证 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
}

正如在 女主角中解释的那样,我们可以使用 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)
}
}

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

if expirationDate.Unix() > time.Now().Unix() {
...
}
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")
        

}
}

根据 时间: 添加时间。比较相关提交的建议,time.Compare将添加到新版本中(Go 1.20)

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