-
Notifications
You must be signed in to change notification settings - Fork 18k
time: Time.AddDate(0,0,0) can change underlying instant #50445
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm not convinced this is a bug. Right now it seems to be the case that AddDate guarantees that the result matches what you'd get from time.Date given the constituent parts. If it did preserve the old time, then it would have a different inconsistency, which could just as easily be filed as a bug report. Given the choice between two inconsistent behaviors - you have to pick one! - it seems like we should pick the one we already have instead of changing from one to the other. |
If I may drop my 2 cents (Canadian, so it is like 1.5 US). Yes, there is an inconsistency possible given the time point chosen. That said - adding a zero assumed to be idempotent operation by default by pretty much every developer. If we are trying to follow a rule of "less surprise", I would argue adding a zero should not change an a result here. (The fact that it is discovered THAT late makes me think changing (well - fixing) this behavior might not be a big problem). Thank you. |
If we change t.AddDate(0, 0, 0), next someone will point out that The fundamental problem is that if you are asking to work in terms of dates, |
Who can elaborate more on the background logic? I totally don't get it. Why does this only happen when N == 1? And only at the date 2021/Oct/31? package main
import (
"fmt"
"time"
)
const N = 1
func main() {
berlinLocation, err := time.LoadLocation("Europe/Berlin")
fmt.Println(err) // <nil>
t1 := time.Date(2021, 10, 31, 1, 0, 0, 0, berlinLocation)
t2 := t1.Add(time.Hour * N)
t3 := t2.AddDate(0, 0, 0)
t4 := t2.Add(time.Hour * N)
fmt.Println(t3.Equal(t2)) // false
fmt.Println(t3.Equal(t4)) // true
fmt.Println(t3.Sub(t2)) // 1h0m0s
fmt.Println(t1) // 2021-10-31 01:00:00 +0200 CEST
fmt.Println(t2) // 2021-10-31 02:00:00 +0200 CEST
fmt.Println(t3) // 2021-10-31 02:00:00 +0100 CET
fmt.Println(t4) // 2021-10-31 02:00:00 +0100 CET
fmt.Println(t1.UTC()) // 2021-10-30 23:00:00 +0000 UTC
fmt.Println(t2.UTC()) // 2021-10-31 00:00:00 +0000 UTC
fmt.Println(t3.UTC()) // 2021-10-31 01:00:00 +0000 UTC
fmt.Println(t4.UTC()) // 2021-10-31 01:00:00 +0000 UTC
} |
@go101 As @rsc said, the time 2021-10-31 02:00:00 in the Europe/Berlin timezone is ambiguous. It happened twice. The first time the clock reached 2021-10-31 02:00:00, it rolled back one hour as the timezone changed from summer time to winter time. One hour later the time 2021-10-31 02:00:00 happened again. Calculations involving ambiguous times are inevitably surprising. The only question is exactly where the surprises occur. |
So does it only happen this year (2021), but not other years? |
It happens every year that there is a transition from summer time to winter time. Of course, that transition doesn't always happen on October 31. For 2020, for example, use |
TIL. |
Closing as working as intended. |
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, this is happening in the playground versions "release" and "go dev branch"
What operating system and processor architecture are you using (
go env
)?go env
Output(I emptied GONOPROXY, GONOSUMDB and GOPRIVATE, because they are pointing to a private gitlab instance)
What did you do?
Playground: https://go.dev/play/p/pC1w7JVWqUX
What did you expect to see?
That .AddDate(0,0,0) does not create a different time.Date
What did you see instead?
the time.Date, that .AddDate(0,0,0) created has a difference of one hour
I know, that AddDate does Normalization:
but I still think, that
.AddDate(0,0,0)
should create the same time.DateThis behaviour does not appear with
.Add(0)
The text was updated successfully, but these errors were encountered: