go 语言时间比较,可以直接比较时间字符串????

2019-03-28 18:59:49 +08:00
 Junjunya

看到同事这么写的时间比较

if now < "2019-04-10 19:00:00" {
    result["isDo"] = 0
}else if now > "2019-04-11 00:00:00"  {
    result["isDo"] = 2
}else {
    result["isDo"] = 1
}

震惊了,居然可以这么写。自己试了下,可以比较

但是网上搜索了一下,居然没找到相关的说明。想知道这样写的原理是什么

8753 次点击
所在节点    Go 编程语言
19 条回复
www5070504
2019-03-28 19:04:51 +08:00
按 ascii 码逐个字符比较?
dremy
2019-03-28 19:05:28 +08:00
ascii 比较呗,肯定是能比的
cpdyj0
2019-03-28 19:07:50 +08:00
没用过 Go,处理 ASCII 比较,会不会是运算符重载之类的?(不知道 Go 有没有这种东西)
mengzhuo
2019-03-28 19:31:06 +08:00
字符比较,按 ascii,当然可以啦,效率嘛……比 time.Time 慢至少 2 倍多

不过有些特殊情况就搞不定了,比如说两个不同时区的时间比较~(虽然国内程序员很少遇到)
misaka19000
2019-03-28 19:34:56 +08:00
某些情况下是能比较的,不过能写出这种代码的程序员水平也真是拙计
liyunlong41
2019-03-28 19:51:12 +08:00
@mengzhuo 有 benchmarks 吗?很好奇为啥会慢
pwrliang
2019-03-28 19:55:38 +08:00
逐个字符比较呗,SQL 里经常这么写,感觉会比转换成日期类型还快
iRiven
2019-03-28 19:58:00 +08:00
有才华 比解析一遍时间来的效率
blankme
2019-03-28 19:59:18 +08:00
@liyunlong41
timestamp 比较只需要比一次数字,string 比较的话,一个一个字符比。。。
petelin
2019-03-28 20:06:10 +08:00
@blankme 难道不要计算构造 time 对象的花销?
azh7138m
2019-03-28 20:36:54 +08:00
@petelin 时间戳是个数字,直接比较,构建啥 time 对象?
gamexg
2019-03-28 20:40:22 +08:00
package main

import (
"fmt"
"time"
)

func main() {
testData := "2006-01-02 15:04:05"

nowStr := time.Now().Format("2006-01-02 15:04:05")
f1 := func() bool {
return testData > nowStr
}

f2 := func() bool {
nowStr := time.Now().Format("2006-01-02 15:04:05")
return testData > nowStr
}

f3 := func() bool {
t, err := time.Parse("2006-01-02 15:04:05", testData)
if err != nil {
panic(err)
}
return time.Now().After(t)
}

T("字符串比较", f1)
T("now 转换为字符串后和字符串比较", f2)
T("字符串解析为 time 后比较", f3)

}

func T(name string, f func() bool) {
s := time.Now()
for i := 0; i < 1000000; i++ {
f()
}
fmt.Printf("%v 耗时 %v\r\n", name, time.Now().Sub(s))
}

字符串比较 耗时 5.0145ms
now 转换为字符串后和字符串比较 耗时 203.3878ms
字符串解析为 time 后比较 耗时 190.563ms
blankme
2019-03-28 20:43:33 +08:00
@petelin
其实要省时间可以把那串时间直接写成数字,然后边上注释一下
(不过 9102 年了,干这种事没什么意义
laminux29
2019-03-28 21:00:50 +08:00
[YYYY-MM-dd HH:mm:ss.fff] 格式的字符串,能进行比较的本质原因,是因为该字符串是一种 [进位数值系统] 。

整数 123456 这种是以 10 作为进位的数值系统,它能进行比较。

而 [YYYY-MM-dd HH:mm:ss.fff] 格式的字符串,也是进位的数值系统,只是它的进位是非固定的,比如时分位是右位 12 进 1,但月位却是右位 28、30、31 进 1。
yippees
2019-03-28 21:28:42 +08:00
now 也是 time.Now()转的吧,转换成数字比较更快吧
如果涉及到金钱相关,跨个时区
WilliamYang
2019-03-28 21:52:13 +08:00
这个时间格式本来就不带有时区, 当然可以这样比较啊
skiy
2019-03-28 22:03:08 +08:00
...
我一般是转成时间戳再比较的,我是不是做错了?
wweir
2019-03-29 06:57:00 +08:00
@skiy 那怎么转换成时间戳呢?不构建 time 对象生撸?
mengzhuo
2019-03-29 09:36:37 +08:00
@blankme 并不是,Go 会用 AVX 并行优化这部分代码,而字符串时间是 19 个字节,19*8 = 152 < 256。一次比较就能得出结果。大概率是慢在内存加载上(懒得做分析了,摊手~

@liyunlong41 嗯,有探索精神,可惜懒了点。
我跑了跑,不是 2 倍( 100%),是~70%。

差别嘛~自己看 objdump 吧

```
func BenchmarkISOString(b *testing.B) {
a := "2019-04-10 19:00:00"
c := "2019-04-10 19:00:01"
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = a < c
}
}

func BenchmarkTime(b *testing.B) {
a := time.Now()
c := time.Now().Add(time.Second)
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = a.Before(c)
}
}


goos: linux
goarch: amd64
BenchmarkISOString-12 200000000 6.68 ns/op
BenchmarkISOString-12 200000000 6.71 ns/op
BenchmarkISOString-12 200000000 6.55 ns/op
BenchmarkTime-12 500000000 3.89 ns/op
BenchmarkTime-12 500000000 4.07 ns/op
BenchmarkTime-12 500000000 3.93 ns/op
PASS
ok _/root/hoho 13.189s
```

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/549657

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX