8
votes

Définir le fuseau horaire globalement dans Golang

J'essaye de modifier le fuseau horaire de Golang pour mon application

J'ai jeté un œil au package time , l'initialisation du fuseau horaire a lieu dans

heure / zoneinfo_unix.go @ initLocal

La fonction essaie simplement de lire la variable d'environnement TZ et si elle est valide, elle la charge

et si ce n'est pas le cas, il revient à / etc / localtime et s'il n'est pas valide, il revient à UTC


ce que j'ai essayé jusqu'à présent

1- fonctionne bien -Mais je ne veux utiliser aucune de ces approches -:

  • dans mon fichier docker, je passe une ENV au conteneur, TZ = Africa / Cairo
  • entrer dans le conteneur bash, exécutant $ export TZ = Africa / Cairo

2- N'a pas fonctionné

  • dans l'initialisation de mon application (l'initialisation de l'application est dans un package séparé qui est importé dans le main), j'utilise os.SetEnv ("TZ", "Africa / Cairo")

Quand je simplifie le principal et que j'utilise os.SetEnv ("TZ", "Africa / Cairo") sans importer d'autres packages que "os-time", cela fonctionne comme prévu


Des idées sur la façon de faire fonctionner la deuxième approche?

Image Docker: golang: 1.11.2


5 commentaires

L'appel de os.Setenv () en premier dans main () semble fonctionner, voir ici: play.golang.org/p/pckEDxd6p8F .


Merci pour votre réponse, j'ai essayé cela et cela ne fonctionne que lorsque le main est très simple comme l'exemple que vous avez fourni, mais dans mon cas, le principal n'est pas si simple et il utilise un package externe pour l'initialisation de l'application


Ensuite, mettez-le dans une fonction init () dans le paquet principal? Et juste pour ajouter mes deux p - il me semble parfaitement bien de définir la var env dans le conteneur ...


@Havelock Cela ne fonctionnerait pas si le package main importe un autre package qui utilise le package time , qui serait exécuté avant le code principal init () pourrait fonctionner.


Puisque vous faites référence à docker, je suppose que c'est un service et non un outil CLI. Si vous vous souciez du fuseau horaire par défaut, considérez qu'il s'agit d'un défaut et retravaillez votre conception de manière à ce qu'elle soit indépendante du système TZ. Les services doivent accepter les entrées dans n'importe quel fuseau horaire, les gérer en UTC, les stocker en UTC et les rendre dans n'importe quel fuseau horaire. Le fuseau horaire du système doit être totalement hors de propos.


3 Réponses :


18
votes

Vous pouvez réaliser ce que vous voulez depuis l'intérieur de votre application en utilisant os.Setenv ("TZ", "Africa / Cairo") , ce qui compte, c'est que vous devez appeler cela avant que tout autre package n'utilise quoi que ce soit du package time .

Comment s'en assurer? Créez un package qui ne fait rien d'autre que définir le fuseau horaire (plus tard, vous pourrez y ajouter d'autres choses, mais pour notre exemple, cela suffit).

Comme ceci:

package main

import _ "path/to/tzinit"

// Your other, "regular" imports:
import (
    "fmt"
    "os"
    "time"
    ...
)


4 commentaires

Merci beaucoup pour votre réponse


Vous ne pouvez pas vous fier à l'ordre des instructions d'importation. La commande d'importation concerne le package dans son ensemble, plutôt que la commande dans un seul fichier. (En fait, ils sont actuellement dans l'ordre en fonction de l'ordre d'analyse des fichiers du package, mais je ne pense pas que cet ordre soit spécifié)


@JimB Oui, je voulais ajouter cela comme avertissement, mais je n'ai pas eu le temps pour cela. Faire maintenant.


J'avais des problèmes avec une application Go qui n'obtenait pas les informations de fuseau horaire correctement, et il s'est avéré qu'il manquait un package "tzdata". L'ajout de ce package et la définition de la variable TZ pourraient aider à résoudre le problème.



1
votes

Je suis peut-être en retard, mais définir le fuseau horaire dans un environnement global n'est pas une approche fiable. Il doit être défini globalement dans une variable ou dans une structure. Voici un exemple de fuseau horaire défini dans une variable. Également dans Go Playground

package main

import (
    "fmt"
    "log"
    "time"
)

func main() {
    if err := setTimezone("America/Los_Angeles"); err != nil {
        log.Fatal(err) // most likely timezone not loaded in Docker OS
    }
    t := getTime(time.Now())
    fmt.Println(t)
}

var loc *time.Location

func setTimezone(tz string) error {
    location, err := time.LoadLocation("America/Los_Angeles")
    if err != nil {
        return err
    }
    loc = location
    return nil
}

func getTime(t time.Time) time.Time {
    return t.In(loc)
}


0 commentaires

0
votes

Ajout de ma réponse ici pour les personnes qui sont tombées sur cette page. Il y a une variable globale dans le package time , utilisez-la comme ceci dans main.go

package main

import (
    "time"
    _ "time/tzdata"
)

func main() {
    loc, err := time.LoadLocation("Africa/Cairo")
    // handle err
    time.Local = loc // -> this is setting the global timezone
}

Votre système doit avoir une base de données de fuseaux horaires installée. Dans le docker, vous devez apt get / apk add tzdata . Mais si vous utilisez go1.15, vous pouvez également intégrer la base de données des fuseaux horaires sans installer tzdata sur le système.

package main

import "time"

func main() {
    loc, err := time.LoadLocation("Africa/Cairo")
    // handle err
    time.Local = loc // -> this is setting the global timezone
}


0 commentaires