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

报告相同问题?

悬赏问题

  • ¥15 蓝牙硬件,可以用哪几种方法控制手机点击和滑动
  • ¥15 生物医学数据分析。基础课程就v经常唱课程舅成牛逼
  • ¥15 云环境云开发云函数对接微信商户中的分账功能
  • ¥15 空间转录组CRAD遇到问题
  • ¥20 materialstudio计算氢键脚本问题
  • ¥15 有没有代做有偿主要做数据可视化部分即可(2023全国高考更省一本线理科类)
  • ¥15 配置FPT报错,该如何处理
  • ¥15 请大家看一下这个代码咋写,一点思路都没有,最好能做一下,不要伪代码,有偿
  • ¥15 有偿请人帮写个安卓系统下禁止装软件及禁止拷入文件的程序
  • ¥100 用 H.265 对音视频硬编码 (CUDA)