En tant que programmeurs, nous devons souvent composer avec le temps. Dans Go, l'heure standard de la bibliothèque fournit une capacité correspondante.
Cet article présentera quelques fonctions et méthodes importantes dans la bibliothèque de temps, dans l'espoir d'aider les enfants qui ont besoin de Baidu lorsqu'ils rencontrent des problèmes de traitement du temps Go.
Faire face aux problèmes de fuseau horaire
En programmation, on rencontre souvent le décalage horaire de huit heures . Cela est dû aux différences de fuseaux horaires, et afin de mieux les traiter, nous devons comprendre plusieurs critères de définition de l'heure.
GMT (heure de Greenwich), heure de Greenwich. GMT, qui calcule l'heure en fonction de la rotation et de la révolution de la Terre, précise que le soleil passe devant l'observatoire royal de Greenwich dans la banlieue de Londres, en Angleterre, à midi chaque jour. GMT est l'ancien temps standard universel.
UTC (Coordinated Universal Time), Temps universel coordonné. UTC est plus précis que GMT et calcule l'heure en fonction des horloges atomiques. Dans les cas où la précision à la seconde n'est pas requise, considérez UTC=GMT. UTC est le temps universel actuel.
A partir du premier méridien de Greenwich, il est positif à l'est et négatif à l'ouest.Le monde est divisé en 24 fuseaux horaires standard, et la différence entre les fuseaux horaires adjacents est d'une heure.
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println(time.Now())
}
La Chine continentale utilise l'heure standard du fuseau horaire East Eight, à savoir l'heure de Pékin CST, China Standard Time.
$ go run main.go
2022-07-17 16:37:31.186043 +0800 CST m=+0.000066647
Ceci est le résultat dans le fuseau horaire par défaut time.Now()
et sera noté dans l'impression +0800 CST
.
En supposant que nous soyons dans le fuseau horaire de Los Angeles, quel est le résultat ?
$ TZ="America/Los_Angeles" go run main.go
2022-07-17 01:39:12.391505 -0700 PDT m=+0.000069514
On peut voir que le résultat à ce moment est l' -0700 PDT
heure, qui est PDT (Pacific Daylight Time) Pacific Daylight Time. En raison du décalage horaire, les résultats horaires des deux exécutions diffèrent de 15 heures.
Notez que lors de l'utilisation de conteneurs Docker, le fuseau horaire par défaut du système est l'heure UTC (fuseau horaire 0), qui diffère de huit heures de l'heure réelle de Pékin dont nous avons besoin. Il s'agit d'un scénario classique qui provoque le décalage horaire de huit heures .
Pour les stratégies permettant de gérer les problèmes de fuseau horaire, vous pouvez vérifier en détail la logique de chargement de la fonction initLocal() dans src/time/zoneinfo_unix.go. Par exemple, il peut être résolu en spécifiant la variable d'environnement TZ, en modifiant le fichier /etc/localtime, etc.
Parce que la question du fuseau horaire est très importante, elle est décrite dans la première partie de l'article. Commençons par présenter l'utilisation de la bibliothèque de temps.
temps instant time.Time
L'objet central de la bibliothèque de temps est la structure time.Time. Il est défini comme suit pour représenter le temps d'un certain instant.
type Time struct {
// wall and ext encode the wall time seconds, wall time nanoseconds,
// and optional monotonic clock reading in nanoseconds.
wall uint64
ext int64
loc *Location
}
En termes de traitement du temps, les ordinateurs impliquent principalement deux types d'horloges.
-
L'heure murale, également connue sous le nom d'horloge, est utilisée pour indiquer une date et une heure spécifiques.
-
Les horloges monotones, qui sont toujours garanties d'avancer, n'ont pas le problème de rappeler l'horloge murale, elles sont donc bien adaptées à la mesure des durées.
Les champs wall et ext sont utilisés pour enregistrer des horloges murales et des horloges monotones avec une précision de l'ordre de la nanoseconde. Les chiffres correspondants du champ sont associés à l'année, au mois, au jour, à l'heure, à la minute, à la seconde et à d'autres informations spécifiques utilisées pour déterminer l'heure.
Le champ loc enregistre l'emplacement du fuseau horaire. Lorsque loc est nul, la valeur par défaut est l'heure UTC.
Étant donné que time.Time est utilisé pour représenter des instants de temps avec une précision de l'ordre de la nanoseconde, les programmes doivent généralement le stocker et le transmettre en tant que valeur, et non en tant que pointeur.
Autrement dit, dans les variables de temps ou les champs struct, nous devrions utiliser time.Time au lieu de *time.Time.
obtenir du temps. Temps
Nous pouvons obtenir l'heure locale actuelle grâce à la fonction Now
func Now() Time {}
Vous pouvez également utiliser la fonction Date pour obtenir l'heure spécifiée en fonction des paramètres d'heure et de fuseau horaire tels que l'année, le mois, le jour, etc.
func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {}
Convertir l'horodatage
Dans le monde informatique, le 1er janvier 1970 UTC 0:0:0:0 est utilisé comme heure Unix 0. Le soi-disant instant temporel est converti en un horodatage Unix, c'est-à-dire que le nombre de secondes, microsecondes, etc. écoulées entre le temps Unix 0 et l'instant spécifié est calculé.
func (t Time) Unix() int64 {} // 从 Unix 时间 0 经过的秒数
func (t Time) UnixMicro() int64 {} // 从 Unix 时间 0 经过的微秒数
func (t Time) UnixMilli() int64 {} // 从 Unix 时间 0 经过的毫秒数
func (t Time) UnixNano() int64 {} // 从 Unix 时间 0 经过的纳秒数
Obtenir les champs de base
t := time.Now()
fmt.Println(t.Date()) // 2022 July 17
fmt.Println(t.Year()) // 2022
fmt.Println(t.Month()) // July
fmt.Println(t.ISOWeek()) // 2022 28
fmt.Println(t.Clock()) // 22 21 56
fmt.Println(t.Day()) // 17
fmt.Println(t.Weekday()) // Sunday
fmt.Println(t.Hour()) // 22
fmt.Println(t.Minute()) // 21
fmt.Println(t.Second()) // 56
fmt.Println(t.Nanosecond())// 494313000
fmt.Println(t.YearDay()) // 198
durée temps.Durée
La durée time.Duration est utilisée pour représenter le temps écoulé entre deux instants time.Time. Il représente le nombre de nanosecondes par int64, et la limite qui peut être représentée est d'environ 290 ans.
// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64
Dans Go, la durée n'est qu'un nombre en nanosecondes. Si la durée est égale à 1000000000, cela signifie 1 seconde ou 1000 millisecondes ou 1000000 microsecondes ou 1000000000 nanosecondes.
Par exemple, deux instants temporels distants d'une heure ont une valeur time.Time et la durée entre eux est une valeur time.Duration
1*60*60*1000*1000*1000
Ces valeurs constantes de durée sont définies dans le package horaire de Go
const (
Nanosecond Duration = 1
Microsecond = 1000 * Nanosecond
Millisecond = 1000 * Microsecond
Second = 1000 * Millisecond
Minute = 60 * Second
Hour = 60 * Minute
)
En même temps, time.Duration fournit une méthode pour obtenir la valeur de chaque granularité temporelle
func (d Duration) Nanoseconds() int64 {} // 纳秒
func (d Duration) Microseconds() int64 {} // 微秒
func (d Duration) Milliseconds() int64 {} // 毫秒
func (d Duration) Seconds() float64 {} // 秒
func (d Duration) Minutes() float64 {} // 分钟
func (d Duration) Hours() float64 {} // 小时
calcul du temps
Après avoir appris les instants temporels et les durées, voyons comment faire des calculs de temps.
func (t Time) Add(d Duration) Time {}
-
La fonction Add permet d'augmenter/diminuer (une valeur positive de d signifie augmenter, une valeur négative signifie diminuer) la durée de time.Time. Nous pouvons augmenter ou diminuer un temps spécifié en nanosecondes ou plus pour un temps instantané.
func (t Time) Sub(u Time) Duration {}
-
La fonction Sub peut déduire la durée entre deux instants.
func (t Time) AddDate(years int, months int, days int) Time {}
-
La fonction AddDate incrémente/décrémente la valeur de time.Time en fonction des dimensions de l'année, du mois et du jour.
Bien sûr, les calculs basés sur l'heure actuelle instant time.Now() sont les besoins les plus courants. Par conséquent, le package de temps fournit également les fonctions de calcul de temps pratiques suivantes.
func Since(t Time) Duration {}
La fonction Depuis est un raccourci pour time.Now().Sub(t).
func Until(t Time) Duration {}
La fonction Until est un raccourci pour t.Sub(time.Now()).
Exemple d'utilisation
t := time.Now()
fmt.Println(t) // 2022-07-17 22:41:06.001567 +0800 CST m=+0.000057466
//时间增加 1小时
fmt.Println(t.Add(time.Hour * 1)) // 2022-07-17 23:41:06.001567 +0800 CST m=+3600.000057466
//时间增加 15 分钟
fmt.Println(t.Add(time.Minute * 15))// 2022-07-17 22:56:06.001567 +0800 CST m=+900.000057466
//时间增加 10 秒钟
fmt.Println(t.Add(time.Second * 10))// 2022-07-17 22:41:16.001567 +0800 CST m=+10.000057466
//时间减少 1 小时
fmt.Println(t.Add(-time.Hour * 1)) // 2022-07-17 21:41:06.001567 +0800 CST m=-3599.999942534
//时间减少 15 分钟
fmt.Println(t.Add(-time.Minute * 15))// 2022-07-17 22:26:06.001567 +0800 CST m=-899.999942534
//时间减少 10 秒钟
fmt.Println(t.Add(-time.Second * 10))// 2022-07-17 22:40:56.001567 +0800 CST m=-9.999942534
time.Sleep(time.Second * 5)
t2 := time.Now()
// 计算 t 到 t2 的持续时间
fmt.Println(t2.Sub(t)) // 5.004318874s
// 1 年之后的时间
t3 := t2.AddDate(1, 0, 0)
// 计算从 t 到当前的持续时间
fmt.Println(time.Since(t)) // 5.004442316s
// 计算现在到明年的持续时间
fmt.Println(time.Until(t3)) // 8759h59m59.999864s
formater l'heure
Dans d'autres langages, un modèle d'heure commun est utilisé pour formater l'heure. Par exemple Python, qui utilise %Y pour l'année, %m pour le mois, %d pour le jour, etc.
Cependant, Go est différent, il utilise une heure fixe (notez qu'il n'est pas possible d'utiliser d'autres heures) comme modèle de mise en page, et cette heure fixe est l'heure de naissance du langage Go.
Mon Jan 2 15:04:05 MST 2006
Le temps de formatage implique deux fonctions de conversion
func Parse(layout, value string) (Time, error) {}
-
La fonction Parse est utilisée pour convertir une chaîne de temps en un objet time.Time selon la mise en page à laquelle elle peut correspondre.
func (t Time) Format(layout string) string {}
-
La fonction Formate est utilisée pour convertir un objet time.Time en une chaîne de temps selon la disposition donnée.
Exemple
const (
layoutISO = "2006-01-02"
layoutUS = "January 2, 2006"
)
date := "2012-08-09"
t, _ := time.Parse(layoutISO, date)
fmt.Println(t) // 2012-08-09 00:00:00 +0000 UTC
fmt.Println(t.Format(layoutUS)) // August 9, 2012
Dans la bibliothèque de temps, Go fournit des constantes de modèle de mise en page prédéfinies, qui peuvent être utilisées directement.
const (
Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
ANSIC = "Mon Jan _2 15:04:05 2006"
UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822 = "02 Jan 06 15:04 MST"
RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
RFC3339 = "2006-01-02T15:04:05Z07:00"
RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano = "Jan _2 15:04:05.000000000"
)
Vous trouverez ci-dessous un tableau comparatif de nos paramètres de mise en page facultatifs
年 06/2006
月 01/1/Jan/January
日 02/2/_2
星期 Mon/Monday
小时 03/3/15
分 04/4
秒 05/5
毫秒 .000/.999
微秒 .000000/.999999
纳秒 .000000000/.999999999
am/pm PM/pm
时区 MST
时区小时数差-0700/-07/-07:00/Z0700/Z07:00
conversion de fuseau horaire
Au début de l'article, nous avons introduit le problème du fuseau horaire. Si dans le code, nous devons obtenir les résultats du même time.Time dans différents fuseaux horaires, nous pouvons utiliser sa méthode In.
func (t Time) In(loc *Location) Time {}
Son utilisation est très simple, il suffit de regarder directement l'exemple de code
now := time.Now()
fmt.Println(now) // 2022-07-18 21:19:59.9636 +0800 CST m=+0.000069242
loc, _ := time.LoadLocation("UTC")
fmt.Println(now.In(loc)) // 2022-07-18 13:19:59.9636 +0000 UTC
loc, _ = time.LoadLocation("Europe/Berlin")
fmt.Println(now.In(loc)) // 2022-07-18 15:19:59.9636 +0200 CEST
loc, _ = time.LoadLocation("America/New_York")
fmt.Println(now.In(loc)) // 2022-07-18 09:19:59.9636 -0400 EDT
loc, _ = time.LoadLocation("Asia/Dubai")
fmt.Println(now.In(loc)) // 2022-07-18 17:19:59.9636 +0400 +04
Résumer
Dans l'ensemble, les fonctions et méthodes de traitement du temps fournies par la bibliothèque de temps répondent essentiellement à nos besoins.
Fait intéressant, la conversion du format d'heure Go doit adopter l'heure de naissance de Go, ce qui est en effet assez narcissique.