I have a string "12:34" that is "MM:SS" format and I want to convert it to a time.Duration. Wasted too much time on this already. What am I doing wrong in this code:
package main
import (
"fmt"
"strings"
"time"
)
func parseDuration(input string) (time.Duration, error) {
var layout string
if strings.Count(input, ":") == 1 {
layout = "04:05"
} else {
layout = "15:04:05"
}
t, err := time.Parse(layout, input)
if err != nil {
return 0, err
}
return t.Sub(time.Time{}), nil
}
func main() {
input := "00:04"
duration, err := parseDuration(input)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(int(duration.Seconds())) // I should get 4 but I get -31622396
}
https://go.dev/play/p/A-eHc-EPTrd
CodePudding user response:
The issue is with the line return t.Sub(time.Time{}), nil. You're subtracting the zero value of time.Time from t, which is equivalent to subtracting the Unix epoch time from t.
To get the duration from the string, you should use time.ParseDuration() instead:
duration, err := time.ParseDuration(input)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(int(duration.Seconds()))
This will correctly parse the duration in the string, and you'll get the expected output of 4.
CodePudding user response:
The zero value of type Time is January 1, year 1, 00:00:00.000000000 UTC.
func parseDuration(input string) (time.Duration, error) {
var layout string
if strings.Count(input, ":") == 1 {
layout = "04:05"
} else {
layout = "15:04:05"
}
t, err := time.Parse(layout, input)
if err != nil {
return 0, err
}
return t
}
fmt.Println(time.Time{})
// this prints 0001-01-01 00:00:00 0000 UTC
fmt.Println(parseDuration("00:04"))
// this prints 0000-01-01 00:00:04 0000 UTC
In your case, you should define a start
object instead of using time.Time{}
directly. For example,
package main
import (
"fmt"
"strings"
"time"
)
var origin = time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC)
func parseDuration(input string) (time.Duration, error) {
var layout string
if strings.Count(input, ":") == 1 {
layout = "04:05"
} else {
layout = "15:04:05"
}
t, err := time.Parse(layout, input)
if err != nil {
return 0, err
}
return t.Sub(origin), nil
}
func main() {
input := "00:04"
duration, err := parseDuration(input)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(duration.String()) // this prints 4s
}