V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Junjunya
V2EX  ›  Go 编程语言

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

  •  
  •   Junjunya · 2019-03-28 18:59:49 +08:00 · 8721 次点击
    这是一个创建于 2072 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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
    }
    

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

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

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

    不过有些特殊情况就搞不定了,比如说两个不同时区的时间比较~(虽然国内程序员很少遇到)
    misaka19000
        5
    misaka19000  
       2019-03-28 19:34:56 +08:00
    某些情况下是能比较的,不过能写出这种代码的程序员水平也真是拙计
    liyunlong41
        6
    liyunlong41  
       2019-03-28 19:51:12 +08:00 via iPhone
    @mengzhuo 有 benchmarks 吗?很好奇为啥会慢
    pwrliang
        7
    pwrliang  
       2019-03-28 19:55:38 +08:00 via Android
    逐个字符比较呗,SQL 里经常这么写,感觉会比转换成日期类型还快
    iRiven
        8
    iRiven  
       2019-03-28 19:58:00 +08:00 via Android
    有才华 比解析一遍时间来的效率
    blankme
        9
    blankme  
       2019-03-28 19:59:18 +08:00 via Android
    @liyunlong41
    timestamp 比较只需要比一次数字,string 比较的话,一个一个字符比。。。
    petelin
        10
    petelin  
       2019-03-28 20:06:10 +08:00 via iPhone
    @blankme 难道不要计算构造 time 对象的花销?
    azh7138m
        11
    azh7138m  
       2019-03-28 20:36:54 +08:00
    @petelin 时间戳是个数字,直接比较,构建啥 time 对象?
    gamexg
        12
    gamexg  
       2019-03-28 20:40:22 +08:00   ❤️ 1
    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
        13
    blankme  
       2019-03-28 20:43:33 +08:00   ❤️ 1
    @petelin
    其实要省时间可以把那串时间直接写成数字,然后边上注释一下
    (不过 9102 年了,干这种事没什么意义
    laminux29
        14
    laminux29  
       2019-03-28 21:00:50 +08:00   ❤️ 2
    [YYYY-MM-dd HH:mm:ss.fff] 格式的字符串,能进行比较的本质原因,是因为该字符串是一种 [进位数值系统] 。

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

    而 [YYYY-MM-dd HH:mm:ss.fff] 格式的字符串,也是进位的数值系统,只是它的进位是非固定的,比如时分位是右位 12 进 1,但月位却是右位 28、30、31 进 1。
    yippees
        15
    yippees  
       2019-03-28 21:28:42 +08:00
    now 也是 time.Now()转的吧,转换成数字比较更快吧
    如果涉及到金钱相关,跨个时区
    WilliamYang
        16
    WilliamYang  
       2019-03-28 21:52:13 +08:00
    这个时间格式本来就不带有时区, 当然可以这样比较啊
    skiy
        17
    skiy  
       2019-03-28 22:03:08 +08:00
    ...
    我一般是转成时间戳再比较的,我是不是做错了?
    wweir
        18
    wweir  
       2019-03-29 06:57:00 +08:00 via iPhone
    @skiy 那怎么转换成时间戳呢?不构建 time 对象生撸?
    mengzhuo
        19
    mengzhuo  
       2019-03-29 09:36:37 +08:00   ❤️ 1
    @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
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1131 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 103ms · UTC 19:13 · PVG 03:13 · LAX 11:13 · JFK 14:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.