How to check whether current local time is DST?

前端 未结 3 1449
孤独总比滥情好
孤独总比滥情好 2021-01-04 12:29

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

相关标签:
3条回答
  • 2021-01-04 12:42

    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.

    0 讨论(0)
  • 2021-01-04 12:55

    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
    }
    
    0 讨论(0)
  • 2021-01-04 13:00

    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
    
    0 讨论(0)
提交回复
热议问题