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
Tutorials
+10.6k Golang : Get UDP client IP address and differentiate clients by port number
+16.2k Golang : Delete files by extension
+19.2k Golang : How to Set or Add Header http.ResponseWriter?
+7.5k Golang : Getting Echo framework StartAutoTLS to work
+7.4k Gogland : Where to put source code files in package directory for rookie
+12.3k Golang : Get absolute path to binary for os.Exec function with exec.LookPath
+5.7k Golang : Generate multiplication table from an integer example
+19.5k Golang : Accept input from user with fmt.Scanf skipped white spaces and how to fix it
+6.2k Golang : Handling image beyond OpenCV video capture boundary
+10k Golang : Convert file content to Hex
+14.8k JavaScript/JQuery : Detect or intercept enter key pressed example
+47.6k Golang : How to convert JSON string to map and slice