In Ruby, for example, there\'s the Time#dst?
function, which returns true in the case it is daylight saving time. Is there a Go standard library API call to do
The Location api doesn't export the DST value of the timezone. This was brought up in the golang-nuts forum several years ago. One suggestion is to compare the January 1 timezone offset to the July 1 timezone offset. A working solution of this was posted using this method. One caveat is that goplay has the wrong local time, so it doesn't correctly report the information if you run it there. You can run it locally to verify that it does work.
Another way would be to use reflection via the reflect package. A solution that I wrote to do this is available here. There are a lot of problems with this method.
Edit: Really it should probably use cacheZone
but does a linear search of the zones to find one that matches. This can lead to errors because some timezones share name and offset. The correct way would be to look at cacheZone
and use that if it is set. Otherwise, you'll need to either look at zoneTrans
or at least look at how lookup(int64)
is implemented.
In a pinch, this should do the trick:
func inDST(t time.Time) bool {
jan1st := time.Date(t.Year(), 1, 1, 0, 0, 0, 0, t.Location()) // January 1st is always outside DST window
_, off1 := t.Zone()
_, off2 := jan1st.Zone()
return off1 != off2
}
You can infer the result. For example,
package main
import (
"fmt"
"time"
)
// isTimeDST returns true if time t occurs within daylight saving time
// for its time zone.
func isTimeDST(t time.Time) bool {
// If the most recent (within the last year) clock change
// was forward then assume the change was from std to dst.
hh, mm, _ := t.UTC().Clock()
tClock := hh*60 + mm
for m := -1; m > -12; m-- {
// assume dst lasts for least one month
hh, mm, _ := t.AddDate(0, m, 0).UTC().Clock()
clock := hh*60 + mm
if clock != tClock {
if clock > tClock {
// std to dst
return true
}
// dst to std
return false
}
}
// assume no dst
return false
}
func main() {
pstLoc, err := time.LoadLocation("America/Los_Angeles")
if err != nil {
fmt.Println(err)
return
}
utc := time.Date(2018, 10, 29, 14, 0, 0, 0, time.UTC)
fmt.Println(utc, utc.Location(), ": DST", isTimeDST(utc))
local := utc.In(time.Local)
fmt.Println(local, local.Location(), ": DST", isTimeDST(local))
pst := utc.In(pstLoc)
fmt.Println(pst, pst.Location(), ": DST", isTimeDST(pst))
utc = utc.AddDate(0, 3, 0)
fmt.Println(utc, utc.Location(), ": DST", isTimeDST(utc))
local = utc.In(time.Local)
fmt.Println(local, local.Location(), ": DST", isTimeDST(local))
pst = utc.In(pstLoc)
fmt.Println(pst, pst.Location(), ": DST", isTimeDST(pst))
}
Output:
2018-10-29 14:00:00 +0000 UTC UTC : DST false
2018-10-29 10:00:00 -0400 EDT Local : DST true
2018-10-29 07:00:00 -0700 PDT America/Los_Angeles : DST true
2019-01-29 14:00:00 +0000 UTC UTC : DST false
2019-01-29 09:00:00 -0500 EST Local : DST false
2019-01-29 06:00:00 -0800 PST America/Los_Angeles : DST false