How to get timezone from country

2020-08-05 11:09发布

I am converting a function from PHP to Go.

I want to get timezone from country code in Go. It is similar this function in PHP

public static array DateTimeZone::listIdentifiers ([ int $what = DateTimeZone::ALL [, string $country = NULL ]] )

Which function have similar feature in Go?

2条回答
ら.Afraid
2楼-- · 2020-08-05 11:33

The Go standard library does not have a function for this. Look for an open-source Go package that does this for you. Or, since this is Go, write a simple Go function yourself. You will have to download the IANA tzdata zone cross-reference file.

For example,

package main

import (
    "bufio"
    "fmt"
    "os"
    "path/filepath"
    "strings"
    "time"
)

// Download IANA tzdata zone file:
// $ wget https://raw.githubusercontent.com/eggert/tz/master/zone1970.tab -O zone1970.tab

// countryZones returns a map of IANA Time Zone Database (tzdata) zone names
// by ISO 3166 2-character country code: map[country][]zone.
func countryZones(dir string) (map[string][]string, error) {
    fname := filepath.Join(dir, `zone1970.tab`)
    f, err := os.Open(fname)
    if err != nil {
        return nil, err
    }
    defer f.Close()

    countries := make(map[string][]string)
    s := bufio.NewScanner(f)
    for s.Scan() {
        line := s.Text()
        if strings.HasPrefix(line, "#") {
            continue
        }
        n := 3
        fields := strings.SplitN(line, "\t", n+1)
        if len(fields) < n {
            continue
        }
        zone := fields[2]
        for _, country := range strings.Split(fields[0], ",") {
            country = strings.ToUpper(country)
            zones := countries[country]
            zones = append(zones, zone)
            countries[country] = zones
        }
    }
    if err = s.Err(); err != nil {
        return nil, err
    }
    return countries, nil
}

func main() {
    zones, err := countryZones("")
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        return
    }

    utc := time.Now().UTC()
    for _, country := range []string{"RU", "CA"} {
        fmt.Println("Country:", country)
        zones := zones[country]
        fmt.Println(utc, "UTC")
        for _, zone := range zones {
            loc, err := time.LoadLocation(zone)
            if err != nil {
                fmt.Fprintln(os.Stderr, err)
                continue
            }
            fmt.Println(utc.In(loc), zone)
        }
    }
}

Output:

$ wget https://raw.githubusercontent.com/eggert/tz/master/zone1970.tab -O zone1970.tab
--2018-07-15 09:44:02--  https://raw.githubusercontent.com/eggert/tz/master/zone1970.tab
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.184.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.184.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 17810 (17K) [text/plain]
Saving to: ‘zone1970.tab’

zone1970.tab             100%[==================================>]  17.39K  --.-KB/s    in 0.03s   

2018-07-15 09:44:02 (582 KB/s) - ‘zone1970.tab’ saved [17810/17810]

$ go run zones.go
Country: RU
2018-07-15 17:40:03.09524872 +0000 UTC UTC
2018-07-15 19:40:03.09524872 +0200 EET Europe/Kaliningrad
2018-07-15 20:40:03.09524872 +0300 MSK Europe/Moscow
2018-07-15 20:40:03.09524872 +0300 MSK Europe/Simferopol
2018-07-15 20:40:03.09524872 +0300 +03 Europe/Volgograd
2018-07-15 20:40:03.09524872 +0300 +03 Europe/Kirov
2018-07-15 21:40:03.09524872 +0400 +04 Europe/Astrakhan
2018-07-15 21:40:03.09524872 +0400 +04 Europe/Saratov
2018-07-15 21:40:03.09524872 +0400 +04 Europe/Ulyanovsk
2018-07-15 21:40:03.09524872 +0400 +04 Europe/Samara
2018-07-15 22:40:03.09524872 +0500 +05 Asia/Yekaterinburg
2018-07-15 23:40:03.09524872 +0600 +06 Asia/Omsk
2018-07-16 00:40:03.09524872 +0700 +07 Asia/Novosibirsk
2018-07-16 00:40:03.09524872 +0700 +07 Asia/Barnaul
2018-07-16 00:40:03.09524872 +0700 +07 Asia/Tomsk
2018-07-16 00:40:03.09524872 +0700 +07 Asia/Novokuznetsk
2018-07-16 00:40:03.09524872 +0700 +07 Asia/Krasnoyarsk
2018-07-16 01:40:03.09524872 +0800 +08 Asia/Irkutsk
2018-07-16 02:40:03.09524872 +0900 +09 Asia/Chita
2018-07-16 02:40:03.09524872 +0900 +09 Asia/Yakutsk
2018-07-16 02:40:03.09524872 +0900 +09 Asia/Khandyga
2018-07-16 03:40:03.09524872 +1000 +10 Asia/Vladivostok
2018-07-16 03:40:03.09524872 +1000 +10 Asia/Ust-Nera
2018-07-16 04:40:03.09524872 +1100 +11 Asia/Magadan
2018-07-16 04:40:03.09524872 +1100 +11 Asia/Sakhalin
2018-07-16 04:40:03.09524872 +1100 +11 Asia/Srednekolymsk
2018-07-16 05:40:03.09524872 +1200 +12 Asia/Kamchatka
2018-07-16 05:40:03.09524872 +1200 +12 Asia/Anadyr
Country: CA
2018-07-15 17:40:03.09524872 +0000 UTC UTC
2018-07-15 15:10:03.09524872 -0230 NDT America/St_Johns
2018-07-15 14:40:03.09524872 -0300 ADT America/Halifax
2018-07-15 14:40:03.09524872 -0300 ADT America/Glace_Bay
2018-07-15 14:40:03.09524872 -0300 ADT America/Moncton
2018-07-15 14:40:03.09524872 -0300 ADT America/Goose_Bay
2018-07-15 13:40:03.09524872 -0400 AST America/Blanc-Sablon
2018-07-15 13:40:03.09524872 -0400 EDT America/Toronto
2018-07-15 13:40:03.09524872 -0400 EDT America/Nipigon
2018-07-15 13:40:03.09524872 -0400 EDT America/Thunder_Bay
2018-07-15 13:40:03.09524872 -0400 EDT America/Iqaluit
2018-07-15 13:40:03.09524872 -0400 EDT America/Pangnirtung
2018-07-15 12:40:03.09524872 -0500 EST America/Atikokan
2018-07-15 12:40:03.09524872 -0500 CDT America/Winnipeg
2018-07-15 12:40:03.09524872 -0500 CDT America/Rainy_River
2018-07-15 12:40:03.09524872 -0500 CDT America/Resolute
2018-07-15 12:40:03.09524872 -0500 CDT America/Rankin_Inlet
2018-07-15 11:40:03.09524872 -0600 CST America/Regina
2018-07-15 11:40:03.09524872 -0600 CST America/Swift_Current
2018-07-15 11:40:03.09524872 -0600 MDT America/Edmonton
2018-07-15 11:40:03.09524872 -0600 MDT America/Cambridge_Bay
2018-07-15 11:40:03.09524872 -0600 MDT America/Yellowknife
2018-07-15 11:40:03.09524872 -0600 MDT America/Inuvik
2018-07-15 10:40:03.09524872 -0700 MST America/Creston
2018-07-15 10:40:03.09524872 -0700 MST America/Dawson_Creek
2018-07-15 10:40:03.09524872 -0700 MST America/Fort_Nelson
2018-07-15 10:40:03.09524872 -0700 PDT America/Vancouver
2018-07-15 10:40:03.09524872 -0700 PDT America/Whitehorse
2018-07-15 10:40:03.09524872 -0700 PDT America/Dawson
$ 
查看更多
可以哭但决不认输i
3楼-- · 2020-08-05 11:49

The timezone is accessible from time.LoadLocation(): example

package main

import (
    "fmt"
    "time"
    "log"
)

func main() {
    var ParisLocation, err = time.LoadLocation("Europe/Paris")
    if(err != nil) {
        log.Fatal(err)
    }

    fmt.Println(ParisLocation)
}

As seen in golang/go issue 21881, it won't work on Windows because $GOROOT/lib/time/zoneinfo.zip is not included by default, hence the need for projects like 4d63.com/tz.

查看更多
登录 后发表回答