Trewq
Trewq

Reputation: 3237

convering 00:33 to duration in golang

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

Upvotes: 0

Views: 605

Answers (2)

HALF9000
HALF9000

Reputation: 628

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

}

https://go.dev/play/p/maGeyA0KWd3

Upvotes: 2

Walsh grat
Walsh grat

Reputation: 29

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.

Upvotes: 0

Related Questions