Получить список допустимых часовых поясов в Go

#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
}