Golang : Display list of time zones with GMT




For this tutorial, we will learn how to grab the list of time zones found in Unix/Darwin(Mac)/Linux/Windows and display the list complete with GMT information. Knowing the differences in time zones can be useful in calculating the time at different locations.

NOTES:

Golang has pretty good support for time zones, but on Windows platform it can be a pain as the time zones names cannot be used directly in Golang. You will need to convert the given time zone on Windows platform to equivalent location names found in *nix platforms in order to use the time.LoadLocation().


For Windows, see https://msdn.microsoft.com/en-US/library/system.timezoneinfo.findsystemtimezonebyid(v=vs.110).aspx

Under the Remarks

FindSystemTimeZoneById tries to match id to the subkey names of the HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Time Zones branch of the registry under Windows XP and Windows Vista. This branch does not necessarily contain a comprehensive list of time zone identifiers.....

See also https://golang.org/src/time/zoneinfo_windows.go line 59 to 79

Here you go!


 package main

 import (
  "bytes"
  "fmt"
  "io/ioutil"
  "os"
  "os/exec"
  "regexp/syntax"
  "runtime"
  "strings"
  "time"
  "unicode/utf8"
  // "golang.org/x/sys/windows/registry"
 )

 // zoneDirs adapted from https://golang.org/src/time/zoneinfo_unix.go

 // https://golang.org/doc/install/source#environment
 // list of available GOOS as of 10th Feb 2017
 // android, darwin, dragonfly, freebsd, linux, netbsd, openbsd, plan9, solaris,windows

 var zoneDirs = map[string]string{
  "android": "/system/usr/share/zoneinfo/",
  "darwin": "/usr/share/zoneinfo/",
  "dragonfly": "/usr/share/zoneinfo/",
  "freebsd": "/usr/share/zoneinfo/",
  "linux": "/usr/share/zoneinfo/",
  "netbsd": "/usr/share/zoneinfo/",
  "openbsd": "/usr/share/zoneinfo/",
  // "plan9":"/adm/timezone/", -- no way to test this platform
  "solaris": "/usr/share/lib/zoneinfo/",
  "windows": `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones\`,
 }

 var zoneDir string

 var timeZones []string

 // InSlice ... check if an element is inside a slice
 func InSlice(str string, list []string) bool {
  for _, v := range list {
 if v == str {
 return true
 }
  }
  return false
 }

 // ReadTZFile ... read timezone file and append into timeZones slice
 func ReadTZFile(path string) {
  files, _ := ioutil.ReadDir(zoneDir + path)
  for _, f := range files {
 if f.Name() != strings.ToUpper(f.Name()[:1])+f.Name()[1:] {
 continue
 }
 if f.IsDir() {
 ReadTZFile(path + "/" + f.Name())
 } else {
 tz := (path + "/" + f.Name())[1:]
 // check if tz is already in timeZones slice
 // append if not
 if !InSlice(tz, timeZones) { // need a more efficient method...

 // convert string to rune
 tzRune, _ := utf8.DecodeRuneInString(tz[:1])

 if syntax.IsWordChar(tzRune) { // filter out entry that does not start with A-Za-z such as +VERSION
 timeZones = append(timeZones, tz)
 }
 }
 }
  }

 }

 func ListTimeZones() {
  if runtime.GOOS == "nacl" || runtime.GOOS == "" {
 fmt.Println("Unsupported platform")
 os.Exit(0)
  }

  // detect OS
  fmt.Println("Time zones available for : ", runtime.GOOS)
  fmt.Println("------------------------")

  fmt.Println("Retrieving time zones from : ", zoneDirs[runtime.GOOS])

  if runtime.GOOS != "windows" {
 for _, zoneDir = range zoneDirs {
 ReadTZFile("")
 }
  } else { // let's handle Windows
 // if you're building this on darwin/linux
 // chances are you will encounter
 // undefined: registry in registry.OpenKey error message
 // uncomment below if compiling on Windows platform

 //k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones`, registry.ENUMERATE_SUB_KEYS|registry.QUERY_VALUE)

 //if err != nil {
 // fmt.Println(err)
 //}
 //defer k.Close()

 //names, err := k.ReadSubKeyNames(-1)
 //if err != nil {
 // fmt.Println(err)
 //}

 //fmt.Println("Number of timezones : ", len(names))
 //for i := 0; i <= len(names)-1; i++ {
 // check if tz is already in timeZones slice
 // append if not
 // if !InSlice(names[i], timeZones) { // need a more efficient method...
 //  timeZones = append(timeZones, names[i])
 // }
 //}

 // UPDATE : Reading from registry is not reliable
 // better to parse output result by "tzutil /g" command
 // REMEMBER : There is no time difference between Coordinated Universal Time and Greenwich Mean Time ....
 cmd := exec.Command("tzutil", "/l")

 data, err := cmd.Output()

 if err != nil {
 panic(err)
 }

 fmt.Println("UTC is the same as GMT")
 fmt.Println("There is no time difference between Coordinated Universal Time and Greenwich Mean Time ....")
 GMTed := bytes.Replace(data, []byte("UTC"), []byte("GMT"), -1)

 fmt.Println(string(GMTed))

  }

  now := time.Now()

  for _, v := range timeZones {

 if runtime.GOOS != "windows" {

 location, err := time.LoadLocation(v)
 if err != nil {
 fmt.Println(err)
 }

 // extract the GMT
 t := now.In(location)
 t1 := fmt.Sprintf("%s", t.Format(time.RFC822Z))
 tArray := strings.Fields(t1)
 gmtTime := strings.Join(tArray[4:], "")
 hours := gmtTime[0:3]
 minutes := gmtTime[3:]

 gmt := "GMT" + fmt.Sprintf("%s:%s", hours, minutes)
 fmt.Println(gmt + " " + v)

 } else {
 fmt.Println(v)
 }

  }
  fmt.Println("Total timezone ids : ", len(timeZones))
 }

 func main() {

  ListTimeZones()

 }

Sample output on LinuxMint:


Time zones available for : linux

------------------------

Retrieving time zones from : /usr/share/zoneinfo/

GMT+00:00 Africa/Abidjan

GMT+00:00 Africa/Accra

GMT+03:00 Africa/Addis_Ababa

GMT+01:00 Africa/Algiers

GMT+03:00 Africa/Asmara

GMT+03:00 Africa/Asmera

GMT+00:00 Africa/Bamako

GMT+01:00 Africa/Bangui

GMT+00:00 Africa/Banjul

GMT+00:00 Africa/Bissau

GMT+02:00 Africa/Blantyre

GMT+01:00 Africa/Brazzaville

GMT+02:00 Africa/Bujumbura

GMT+02:00 Africa/Cairo

GMT+00:00 Africa/Casablanca

GMT+01:00 Africa/Ceuta

GMT+00:00 Africa/Conakry

GMT+00:00 Africa/Dakar

GMT+03:00 Africa/DaresSalaam

GMT+03:00 Africa/Djibouti

GMT+01:00 Africa/Douala

GMT+00:00 Africa/El_Aaiun

GMT+00:00 Africa/Freetown

GMT+02:00 Africa/Gaborone

GMT+02:00 Africa/Harare

GMT+02:00 Africa/Johannesburg ....

GMT+14:00 Pacific/Apia

GMT+13:00 Pacific/Auckland

GMT+11:00 Pacific/Bougainville

GMT+13:45 Pacific/Chatham

GMT+10:00 Pacific/Chuuk

GMT-05:00 Pacific/Easter

GMT+11:00 Pacific/Efate

GMT+13:00 Pacific/Enderbury

GMT+13:00 Pacific/Fakaofo

GMT+12:00 Pacific/Fiji

GMT+12:00 Pacific/Funafuti

GMT-06:00 Pacific/Galapagos

GMT-09:00 Pacific/Gambier

GMT+11:00 Pacific/Guadalcanal

GMT+10:00 Pacific/Guam

GMT-10:00 Pacific/Honolulu

GMT-10:00 Pacific/Johnston

GMT+14:00 Pacific/Kiritimati

GMT+11:00 Pacific/Kosrae

GMT+12:00 Pacific/Kwajalein

GMT+12:00 Pacific/Majuro

GMT-09:30 Pacific/Marquesas

GMT-11:00 Pacific/Midway

GMT+12:00 Pacific/Nauru

GMT-11:00 Pacific/Niue

GMT+11:00 Pacific/Norfolk

GMT+11:00 Pacific/Noumea

GMT-11:00 Pacific/Pago_Pago

GMT+09:00 Pacific/Palau

GMT-08:00 Pacific/Pitcairn

GMT+11:00 Pacific/Pohnpei

GMT+11:00 Pacific/Ponape

GMT+10:00 Pacific/Port_Moresby

GMT-10:00 Pacific/Rarotonga

GMT+10:00 Pacific/Saipan

GMT-11:00 Pacific/Samoa

GMT-10:00 Pacific/Tahiti

GMT+12:00 Pacific/Tarawa

GMT+13:00 Pacific/Tongatapu

GMT+10:00 Pacific/Truk

GMT+12:00 Pacific/Wake

GMT+12:00 Pacific/Wallis

GMT+10:00 Pacific/Yap

GMT+01:00 Poland

GMT+00:00 Portugal

GMT+08:00 ROC

GMT+09:00 ROK

GMT+08:00 Singapore

GMT-04:00 SystemV/AST4

GMT-04:00 SystemV/AST4ADT

GMT-06:00 SystemV/CST6

GMT-06:00 SystemV/CST6CDT

GMT-05:00 SystemV/EST5

GMT-05:00 SystemV/EST5EDT

GMT-10:00 SystemV/HST10

GMT-07:00 SystemV/MST7

GMT-07:00 SystemV/MST7MDT

GMT-08:00 SystemV/PST8

GMT-08:00 SystemV/PST8PDT

GMT-09:00 SystemV/YST9

GMT-09:00 SystemV/YST9YDT

GMT+03:00 Turkey

GMT+00:00 UCT

GMT-09:00 US/Alaska

GMT-10:00 US/Aleutian

GMT-07:00 US/Arizona

GMT-06:00 US/Central

GMT-05:00 US/East-Indiana

GMT-05:00 US/Eastern

GMT-10:00 US/Hawaii

GMT-06:00 US/Indiana-Starke

GMT-05:00 US/Michigan

GMT-07:00 US/Mountain

GMT-08:00 US/Pacific

GMT-08:00 US/Pacific-New

GMT-11:00 US/Samoa

GMT+00:00 UTC

GMT+00:00 Universal

GMT+03:00 W-SU

GMT+00:00 WET

GMT+00:00 Zulu

Total timezone ids : 606


References:

https://golang.org/src/time/zoneinfo_unix.go

https://technet.microsoft.com/en-us/library/cc749073(v=ws.10).aspx

https://www.socketloop.com/tutorials/golang-detect-os-operating-system

https://www.socketloop.com/references/golang-time-time-zone-function-example

  See also : Golang : How to get time zone and load different time zone?





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement