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

报告相同问题?

悬赏问题

  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)
  • ¥100 set_link_state
  • ¥15 虚幻5 UE美术毛发渲染
  • ¥15 CVRP 图论 物流运输优化
  • ¥15 Tableau online 嵌入ppt失败
  • ¥100 支付宝网页转账系统不识别账号
  • ¥15 基于单片机的靶位控制系统
  • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)