在Golang中进行日期比较有什么选择吗?我必须根据日期和时间对数据进行排序 - 独立。因此,我可能允许在一系列日期内发生的对象,只要它也在一定范围内发生。在这个模型中,我不能简单地选择最早的日期,最年轻的时间/最晚的日期,最新的时间和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(范围,时间)函数,但它没有完全正常工作。 (事实上,大多数情况下,第二种情况,时间跨度超过几天都会被打破。原来的部分有效,我只是意识到在从本地转换到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;
}
但是我真的想做这个过滤器服务器端。
答案 0 :(得分:72)
使用time包处理Go中的时间信息。
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, ".")
}
}
答案 1 :(得分:17)
两次比较 使用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
答案 2 :(得分:10)
对于你的间隔结束的情况,它的日期没有数小时 “从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) {
...
}
答案 3 :(得分:1)
最近的协议更喜欢每golang time package documentation使用RFC3339。
通常,对于坚持使用该格式的服务器,应使用RFC1123Z而不是RFC1123,并且RFC3339应该是新协议的首选。 RFC822,RFC822Z,RFC1123和RFC1123Z对格式化非常有用;当与time.Parse一起使用时,它们不接受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).
答案 4 :(得分:0)
以下解决了将字符串转换为日期的问题
package main
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"
答案 5 :(得分:0)
如果您有兴趣比较一个时间是否与另一个时间接近以进行测试,您可以使用 testify 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
}