#go #timezone
#Вперед #Часовой пояс
Вопрос:
Я хотел бы написать метод, который будет заполнять массив языка Go общими часовыми поясами, которые принимаются time.Format()
вызовом, для использования в шаблоне HTML (форма выберите, чтобы позволить им читать и выбирать свой часовой пояс). Есть ли общий способ сделать это?
Комментарии:
1.
func (t Time) Format(layout string)
не принимает часовой пояс (кроме «MST», чтобы указать, куда вы хотите, чтобы часовой пояс отображался в выходных данных).2. Документация по времени. Местоположение загрузки описывает, где Go ищет информацию о часовом поясе.
3. Если вы можете вызвать библиотеку C , я могу показать, как это сделать.
Ответ №1:
Чтобы получить список часовых поясов, вы можете использовать что-то вроде:
package main
import (
"fmt"
"io/ioutil"
"strings"
)
var zoneDirs = []string{
// Update path according to your OS
"/usr/share/zoneinfo/",
"/usr/share/lib/zoneinfo/",
"/usr/lib/locale/TZ/",
}
var zoneDir string
func main() {
for _, zoneDir = range zoneDirs {
ReadFile("")
}
}
func ReadFile(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() {
ReadFile(path "/" f.Name())
} else {
fmt.Println((path "/" f.Name())[1:])
}
}
}
вывод:
Africa/Abidjan
Africa/Accra
Africa/Addis_Ababa
Africa/Algiers
Africa/Asmara
Africa/Asmera
Africa/Bamako
Africa/Bangui
...
Комментарии:
1. Фантастика! Хотя, я думаю, что в
ReadFile("")
есть опечатка — не так лиReadFile(zoneDir)
?2. Нет, никакой опечатки) Это из-за рекурсии. Также это больше похоже на прототип, поэтому вы можете где-то доработать и интегрировать, но вам, вероятно, нужно сохранить результаты вместо простой печати.
3. Есть идеи, как включить резервные данные по умолчанию, расположенные внутри
$GOROOT/lib/time
?4. В macOS 11 есть файл
VERSION
в/usr/share/zoneinfo/
. Вы должны пропустить этот файл.5. В каталогах macOS и некоторых дистрибутивах Linux есть некоторые файлы, которые не являются файлами TZ. Лучший способ проверить это — попробовать загрузить зону с помощью
time.LoadLocation()
и проверить наличие ошибок. Если ошибки нет, файл является файлом TZ.if _, err := time.LoadLocation(tzFilename); err != nil { continue }
Ответ №2:
Go’s time pkg использует базу данных часовых поясов.
Вы можете загрузить местоположение часового пояса следующим образом:
loc, err := time.LoadLocation("America/Chicago")
if err != nil {
// handle error
}
t := time.Now().In(loc)
Format
Функция не связана с установкой часового пояса, эта функция принимает фиксированное базовое время, что позволяет вам форматировать дату так, как вы хотели бы. Взгляните на документы time pkg.
Например:
fmt.Println(t.Format("MST")) // outputs CST
Вот работающий пример
Комментарии:
1. Это не отвечает на вопрос. Почему за это так много голосов.
2. Вопросы немного неясны. В вопросе ошибочно указано, как работает
Format
метод. В этом ответе объясняется, как загрузить правильное местоположение и отобразить время, используя загруженное местоположение. Отображение списка в шаблоне html кажется легкой частью, поэтому я предполагаю, что люди находят написанное полезным, отсюда и положительные отзывы.
Ответ №3:
Вот пример:https://play.golang.org/p/KFGQiW5A1P
package main
import (
"fmt"
"io/ioutil"
"strings"
"unicode"
)
func main() {
fmt.Println(GetOsTimeZones())
}
func GetOsTimeZones() []string {
var zones []string
var zoneDirs = []string{
// Update path according to your OS
"/usr/share/zoneinfo/",
"/usr/share/lib/zoneinfo/",
"/usr/lib/locale/TZ/",
}
for _, zd := range zoneDirs {
zones = walkTzDir(zd, zones)
for idx, zone := range zones {
zones[idx] = strings.ReplaceAll(zone, zd "/", "")
}
}
return zones
}
func walkTzDir(path string, zones []string) []string {
fileInfos, err := ioutil.ReadDir(path)
if err != nil {
return zones
}
isAlpha := func(s string) bool {
for _, r := range s {
if !unicode.IsLetter(r) {
return false
}
}
return true
}
for _, info := range fileInfos {
if info.Name() != strings.ToUpper(info.Name()[:1]) info.Name()[1:] {
continue
}
if !isAlpha(info.Name()[:1]) {
continue
}
newPath := path "/" info.Name()
if info.IsDir() {
zones = walkTzDir(newPath, zones)
} else {
zones = append(zones, newPath)
}
}
return zones
}