为什么要时间?由于在Windows上返回负时长?

I have been trying to work with some go, and have found some weird behavior on windows. If I construct a time object from parsing a time string in a particular format, and then use functions like time.Since(), I get negative durations.

Code sample:

package main

import (
    "fmt"
    "time"
    "strconv"
)

func convertToTimeObject(dateStr string) time.Time {
    layout := "2006-01-02T15:04:05.000Z"
    t, _:= time.Parse(layout, dateStr)

    return t
}

func main() {
    timeOlder := convertToTimeObject(time.Now().Add(-30*time.Second).Format("2006-01-02T15:04:05.000Z"))
    duration := time.Since(timeOlder)
    fmt.Println("Duration in seconds: " + strconv.Itoa(int(duration.Seconds())))
}

If you run it on Linux or the Go Playground link, you get the result as Duration in seconds: 30 which is expected.

However, on Windows, running the same piece of code with Go 1.10.3 gives Duration in seconds: -19769.

I've banged my head on this for hours. Any help on what I might be missing? The only leads I've had since now are that when go's time package goes to calculate the seconds for both time objects (time.Now() and my parsed time object), one of them has the property hasMonotonic and one doesn't, which results in go calculating vastly different seconds for both.

I'm not the expert in time, so would appreciate some help. I was going to file a bug for Go, but thought to ask here from the experts if there's something obvious I might be missing.

I think I figured out what the reason for the weird behavior of your code snippet is and can provide a solution. The relevant docs read as follows:

since returns the time elapsed since t. It is shorthand for time.Now().Sub(t).

But:

now returns the current local time.

That means you are formatting timeOlder and subtract it from an unformatted local time. That of course causes unexpected behavior. A simple solution is to parse the local time according to your format before subtracting timeOlder from it.

A solution that works on my machine (it probably does not make a lot of sense to give a playground example, though):

func convertToTimeObject(dateStr string) time.Time {
    layout := "2006-01-02T15:04:05.000Z"
    t, err := time.Parse(layout, dateStr)
    // check the error!
    if err != nil {
        log.Fatalf("error while parsing time: %s
", err)
    }
    return t
}

func main() {
    timeOlder := convertToTimeObject(time.Now().Add(-30 * time.Second).Format("2006-01-02T15:04:05.000Z"))
    duration := time.Since(timeOlder)

    // replace time.Since() with a correctly parsed time.Now(), because
    // time.Since() returns the time elapsed since the current LOCAL time.
    t := time.Now().Format("2006-01-02T15:04:05.000Z")
    timeNow := convertToTimeObject(t)

    // print the different results
    fmt.Println("duration in seconds:", strconv.Itoa(int(duration.Seconds())))
    fmt.Printf("duration: %v
", timeNow.Sub(timeOlder))
}

Outputs:

duration in seconds: 14430
duration: 30s