How to parse timestamp with underscores in Golang

Viewed 443

I'm trying to parse access log timestamp like "2020/11/06_18:17:25_455" in Filebeat according to Golang spec.
Here is my test program to verify layout:

package main

import (
    "fmt"
    "log"
    "time"
)

func main() {

    eventDateLayout := "2006/01/02_15:04:05_000"

    eventCheckDate, err := time.Parse(eventDateLayout, "2020/11/06_18:17:25_455")
    if err != nil {
        log.Fatal(err)
    }

    fmt.Println(eventCheckDate)

}  

Result:

2009/11/10 23:00:00 parsing time "2020/11/06_18:17:25_455" as "2006/01/02_15:04:05_000": cannot parse "455" as "_000"

As I understand underscore has a special meaning in Golang, but from documentation it's not clear how to escape it.
Any ideas, please?

2 Answers

It doesn't seem possible to use any escape characters for the time layout (e.g. "\\_" doesn't work), so one would have to do something different.

This issue describes the same problem, but it was solved in a very non-general way that doesn't seem to apply to your format.

So your best bet seems to be replacing _ with something else/stripping it from the string, then using a layout without it. To make sure that the millisecond part ist also parsed, it must be separated with a . instead of _, then it's recognized as part of the seconds (05) format.

eventDateLayout := "2006/01/02.15:04:05"

val := strings.Replace("2020/11/06_18:17:25_455", "_", ".", 2)

eventCheckDate, err := time.Parse(eventDateLayout, val)
if err != nil {
    panic(err)
}
fmt.Println(eventCheckDate)

Playground link

From time.Format

A fractional second is represented by adding a period and zeros to the end of the seconds section of layout string, as in "15:04:05.000" to format a time stamp with millisecond precision.

You cannot specify millisecond precision with an underscore you need 05.000 instead:

// eventDateLayout := "2006/01/02_15:04:05_000"  // invalid format
eventDateLayout := "2006/01/02_15:04:05.000"
eventCheckDate, err := time.Parse(eventDateLayout, "2020/11/06_18:17:25.455")

So basically use a simple translate function to convert the final _ to a . and use the above parser.

https://play.golang.org/p/POPgXC_qe81

Related