ChatGPT解决这个技术问题 Extra ChatGPT

Difference between two time.Time objects

Very new to the 'Go'. Question might be basic one.

I have two time.Time objects and I want to get the difference between the two in terms of hours/minutes/seconds. Lets say:

t1 = 2016-09-09 19:09:16 +0530 IST
t2 = 2016-09-09 19:09:16 +0530 IST

In above case, since the difference is 0. It should give me 00:00:00. Consider another case:

t1 = 2016-09-14 14:12:48 +0530 IST
t2 = 2016-09-14 14:18:29 +0530 IST

In this case, difference would be 00:05:41. I looked at the https://godoc.org/time but could not make anything out of it.


C
Community

You may use Time.Sub() to get the difference between the 2 time.Time values, result will be a value of time.Duration.

When printed, a time.Duration formats itself "intelligently":

t1 := time.Now()
t2 := t1.Add(time.Second * 341)

fmt.Println(t1)
fmt.Println(t2)

diff := t2.Sub(t1)
fmt.Println(diff)

Output:

2009-11-10 23:00:00 +0000 UTC
2009-11-10 23:05:41 +0000 UTC
5m41s

If you want the time format HH:mm:ss, you may constuct a time.Time value and use its Time.Format() method like this:

out := time.Time{}.Add(diff)
fmt.Println(out.Format("15:04:05"))

Output:

00:05:41

Try the examples on the Go Playground.

Of course this will only work if the time difference is less than a day. If the difference may be bigger, then it's another story. The result must include days, months and years. Complexity increases significnatly. See this question for details:

golang time.Since() with months and years

The solution presented there solves this issue by showing a function with signature:

func diff(a, b time.Time) (year, month, day, hour, min, sec int)

You may use that even if your times are within 24 hours (in which case year, month and day will be 0).


Bang on! Thank you.
How about if I say I need only hours or minutes?
@HemantBhargava Then use a different layout string, one that only contains hours and minutes: out.Format("15:04")
This is not working. t1 := time.Now() t2 := t1.Add(time.Second * 34100) diff := t2.Sub(t1) fmt.Println(diff.Minutes()) out := time.Time{}.Add(diff) fmt.Println(out.Format("15:30")) This outputs : 568.3333333333334 09:90 Which is not correct.
@HemantBhargava Yes of course because "15:30" is an invalid layout string. Please take the time and read the doc at Time.Format() to know what the layout string is. Using out.Format("15:04:05") outputs 09:28:20 which is correct. If you only need hour+min, then use out.Format("15:04") which outputs 09:28, as you can see this on the Go Playground.
P
Pallav Jha

Actually, the time package's documentation does discuss it:

https://godoc.org/time#Time.Sub

https://godoc.org/time#Duration.Hours

You should produce a Duration object using Sub() and then use one of the Seconds(), Minutes(), Hours().

package main

import (
        "fmt"
        "time"
)

func main() {
        t1 := time.Date(1984, time.November, 3, 13, 0, 0, 0, time.UTC)
        t2 := time.Date(1984, time.November, 3, 10, 0, 0, 0, time.UTC)
        fmt.Printf("The hours difference is: %f", t1.Sub(t2).Hours())
}

Okay, Thanks for the quick answer. I did it: var duration time.Duration = trip.EndTime.Sub(trip.StartTime) fmt.Println("Time difference: Minutes", duration.Minutes(), "Seconds: ", duration.Seconds()) But this does not seem to be giving the right numbers.
What is trip.EndTime\StartTime ?
Sorry! Think of it as: t1 = trip.StartTime t2 = trip.EndTime
It is OK, but how does it implemented ?
Implemented what? I did not write anything else than above two lines for the duration.
t
thwd

To complement Shmulik Klein's answer:

Another way to calculate disjoint hours/minutes/seconds out of a time.Duration:

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

package main

import (
    "fmt"
    "math"
    "time"
)

func main() {
    t1 := time.Date(1984, time.November, 3, 13, 0, 0, 0, time.UTC)
    t2 := time.Date(1984, time.November, 3, 10, 23, 34, 0, time.UTC)

    hs := t1.Sub(t2).Hours()

    hs, mf := math.Modf(hs)
    ms := mf * 60

    ms, sf := math.Modf(ms)
    ss := sf * 60

    fmt.Println(hs, "hours", ms, "minutes", ss, "seconds")
}

2 hours 36 minutes 25.999999999999375 seconds

note:

slight precision loss due to the use of the float64 type

we ignore leap seconds and assume every minute has 60 seconds


leap seconds considerations and data type consideration? this is a $1000 answer to $10 question...
S
STEEL

DEMO


package main

import (
    "fmt"
    "math"
    "time"
)

func TimeAsString(dt float64) string {
    time := dt
    hours := math.Floor(time / 3600)
    minutes := math.Ceil(math.Mod(time, 3600)/60) - 1
    seconds := int(time) % 60
    return fmt.Sprintf("%v:%v:%v", hours, minutes, seconds)
}

func main() {
    mytime := 0.0
    last := time.Now()

    tick := time.Tick(33 * time.Millisecond)
    for {

        select {
        case <-tick:
            dt := time.Since(last).Seconds()
            last = time.Now()

            mytime += dt
            fmt.Println(TimeAsString(mytime))
        }

    }
}