dongnai6973 2014-11-30 18:09
浏览 362
已采纳

在Golang中解析日期和时间的最佳方法

I have a lot of datetime values incoming as string into my golang program. The format is fixed in number of digit:

2006/01/02 15:04:05

I started to parse these dates with the time.Parse function

const dtFormat = "2006/01/02 15:04:05"

func ParseDate1(strdate string) (time.Time, error) {
    return time.Parse(dtFormat, strdate)
}

but I had some performances issue with my program. Thus I tried to tune it by writting my own parsing function, taking into account that my format is kind of fixed:

func ParseDate2(strdate string) (time.Time, error) {
    year, _ := strconv.Atoi(strdate[:4])
    month, _ := strconv.Atoi(strdate[5:7])
    day, _ := strconv.Atoi(strdate[8:10])
    hour, _ := strconv.Atoi(strdate[11:13])
    minute, _ := strconv.Atoi(strdate[14:16])
    second, _ := strconv.Atoi(strdate[17:19])

    return time.Date(year, time.Month(month), day, hour, minute, second, 0, time.UTC), nil
}

finally I did a benchmark on top of these 2 functions and got the following result:

 BenchmarkParseDate1      5000000               343 ns/op
 BenchmarkParseDate2     10000000               248 ns/op

This is a performance improvement by 27%. Is there a better way in terms of performances that could improve such datetime parsing ?

  • 写回答

2条回答 默认 最新

  • dongya3627 2014-11-30 19:30
    关注

    I would expect to make your entire program much faster. For example, ParseDate3,

    func ParseDate3(date []byte) (time.Time, error) {
        year := (((int(date[0])-'0')*10+int(date[1])-'0')*10+int(date[2])-'0')*10 + int(date[3]) - '0'
        month := time.Month((int(date[5])-'0')*10 + int(date[6]) - '0')
        day := (int(date[8])-'0')*10 + int(date[9]) - '0'
        hour := (int(date[11])-'0')*10 + int(date[12]) - '0'
        minute := (int(date[14])-'0')*10 + int(date[15]) - '0'
        second := (int(date[17])-'0')*10 + int(date[18]) - '0'
        return time.Date(year, month, day, hour, minute, second, 0, time.UTC), nil
    }
    

    Benchmarks:

    $ go test -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkParseDate1  5000000           308 ns/op
    BenchmarkParseDate2 10000000           225 ns/op
    BenchmarkParseDate3 30000000            44.9 ns/op
    ok      so/test 5.741s
    $ go test -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkParseDate1  5000000           308 ns/op
    BenchmarkParseDate2 10000000           226 ns/op
    BenchmarkParseDate3 30000000            45.4 ns/op
    ok      so/test 5.757s
    $ go test -bench=.
    testing: warning: no tests to run
    PASS
    BenchmarkParseDate1  5000000           312 ns/op
    BenchmarkParseDate2 10000000           225 ns/op
    BenchmarkParseDate3 30000000            45.0 ns/op
    ok      so/test 5.761s
    $ 
    

    Reference:

    Profiling Go Programs


    If you insist on using date string, use ParseDate4,

    func ParseDate4(date string) (time.Time, error) {
        year := (((int(date[0])-'0')*10+int(date[1])-'0')*10+int(date[2])-'0')*10 + int(date[3]) - '0'
        month := time.Month((int(date[5])-'0')*10 + int(date[6]) - '0')
        day := (int(date[8])-'0')*10 + int(date[9]) - '0'
        hour := (int(date[11])-'0')*10 + int(date[12]) - '0'
        minute := (int(date[14])-'0')*10 + int(date[15]) - '0'
        second := (int(date[17])-'0')*10 + int(date[18]) - '0'
        return time.Date(year, month, day, hour, minute, second, 0, time.UTC), nil
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 关于php录入完成后,批量更新数据库
  • ¥15 请教往复密封润滑问题
  • ¥15 cocos creator发布ios包
  • ¥15 comsol压电材料数据
  • ¥35 用python实现除法算法中goldschmidt算法
  • ¥15 汇编代码转换成C代码
  • ¥15 除法算法中的归一化具体是怎么变的?
  • ¥20 集成电路的逻辑电路和晶体管简化图
  • ¥15 下载windows builder后的问题
  • ¥15 端口连接数为什么会有限制