-1

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?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
user3418135
  • 115
  • 1
  • 2
  • 9
  • @danicheeta no, I only want get timezone from country code, not get current timestamp from timezones. – user3418135 Jul 15 '18 at 09:11
  • 3
    Russia has 8 time zones or so, which one would you expect to get by “ru” code? USA has I think 3. – Alexander Trakhimenok Jul 15 '18 at 10:26
  • @AlexanderTrakhimenok, I want get first timezone in that list. – user3418135 Jul 15 '18 at 10:42
  • 2
    First means the one is getting sun earlier or a capital one, or the one that has the least deviation from other time zones from the same country? You better get capital of country and use it time zone. – Alexander Trakhimenok Jul 15 '18 at 12:57
  • USA has at least 5 geographic timezones. More if you count the oddball states that change DST at different times of the year, or not at all. And almost every country in the world has at least two, if you count DST (and you should for most purposes). – Jonathan Hall Jul 15 '18 at 15:30
  • @Flimzy: For this purpose, we do not count DST. Almost every country in the world does not have DST: [Daylight saving time by country - Wikipedia](https://en.wikipedia.org/wiki/Daylight_saving_time_by_country). Most of the world's population doesn't have DST. – peterSO Jul 15 '18 at 17:48
  • @peterSO: I should have said that most geographic time zones also use DST, which is true. Due to DST, and based on the map you referenced, DST nearly doubles the number of expected timezones (although in practice, it more than doubles that number, since not all political regions follow the same DST rules). – Jonathan Hall Jul 16 '18 at 07:09
  • Possible duplicate of [How to get the current timestamp in other timezones in Golang?](https://stackoverflow.com/questions/27991671/how-to-get-the-current-timestamp-in-other-timezones-in-golang) – Martin Tournoij Jul 17 '18 at 07:30

2 Answers2

4

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
$ 
peterSO
  • 158,998
  • 31
  • 281
  • 276
-1

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.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250