Menu

Time en Golang : Now, Sleep, Format, Parse et durées

Comment manipuler les dates et les heures en Go : time.Now et time.Sleep, l'arithmétique des Duration, la disposition de référence 2006-01-02 15:04:05 pour Format et Parse, les fuseaux horaires, les timestamps Unix, et les timers et tickers.

Cette page contient des éditeurs exécutables - modifiez, exécutez et voyez la sortie instantanément.

L'essentiel en un programme

time.Now() renvoie l'heure locale actuelle, time.Sleep met en pause la goroutine courante, time.Since mesure le temps écoulé, et time.Date construit un instant précis. La suite de cette page reprend chaque élément un par un. Les exemples utilisent des dates fixes et l'UTC pour que leur sortie soit la même où que vous les exécutiez.

Sleep et Duration

Un time.Duration est un int64 qui compte des nanosecondes. Le package définit des constantes pour construire des valeurs lisibles :

ConstanteValeur
time.Nanosecond1
time.Microsecond1000 ns
time.Millisecond1000 µs
time.Second1000 ms
time.Minute60 s
time.Hour60 min

Il n'y a pas de time.Day, parce qu'une journée ne fait pas toujours 24 heures quand un fuseau horaire passe à l'heure d'été. Utilisez AddDate pour les jours calendaires (voir plus bas).

Deux bugs courants viennent du fait que Duration est un entier :

  • time.Sleep(5) dort 5 nanosecondes. Multipliez toujours par une unité : time.Sleep(5 * time.Second).
  • time.Sleep(n * time.Second) ne compile pas quand n est une variable int. Convertissez-la : time.Duration(n) * time.Second. Une constante comme 5 fonctionne sans conversion parce que les constantes non typées s'adaptent au type Duration.

ParseDuration accepte ns, us (ou µs), ms, s, m et h, combinés comme "2h45m" ou "1.5s". Il n'a pas d'unité pour les jours.

Formatage : la disposition de référence 2006-01-02

Go n'utilise ni %Y-%m-%d ni yyyy-MM-dd. Une disposition (layout) est l'heure de référence

Mon Jan 2 15:04:05 MST 2006

écrite comme vous voulez que votre sortie apparaisse. Les valeurs sont choisies pour que chacune soit unique : mois 1, jour 2, heure 3 (ou 15), minute 4, seconde 5, année 6 (2006), décalage horaire -7 (-0700). Lisez-la comme 01/02 03:04:05PM '06 -0700.

Les éléments de disposition dont vous aurez le plus besoin :

ÉlémentSignificationExemple
2006 / 06année, sur 4 ou 2 chiffres2026 / 26
01 / 1 / Jan / Januarymois03 / 3 / Mar / March
02 / 2 / _2jour du mois (complété par zéro, simple, complété par espace)05 / 5 / " 5"
Mon / Mondayjour de la semaineThu / Thursday
15heure, horloge de 24 heures09
03 / 3heure, horloge de 12 heures09 / 9
04 / 4minute07 / 7
05 / 5seconde03 / 3
PM / pmmarqueur AM ou PMAM
.000 / .999fractions de seconde (fixes / zéros finaux retirés).250 / .25
MSTabréviation du fuseauUTC
-0700 / -07:00décalage horaire numérique+0000 / +00:00
Z07:00comme -07:00, mais affiche Z pour l'UTCZ

Dispositions prédéfinies :

ConstanteDisposition
time.RFC33392006-01-02T15:04:05Z07:00 (à utiliser pour les API et le JSON)
time.RFC3339Nano2006-01-02T15:04:05.999999999Z07:00
time.DateTime (Go 1.20)2006-01-02 15:04:05
time.DateOnly (Go 1.20)2006-01-02
time.TimeOnly (Go 1.20)15:04:05
time.Kitchen3:04PM
time.RFC1123Mon, 02 Jan 2006 15:04:05 MST (les dates HTTP utilisent plutôt http.TimeFormat)

L'erreur classique consiste à écrire une disposition avec les mauvais chiffres, par exemple "2023-01-01". Go ne la rejette pas. Il recopie les caractères qu'il ne reconnaît pas et remplace ceux qu'il reconnaît : chaque 2 est le jour, 3 est l'heure sur 12 heures et les deux 01 sont le mois, donc le 5 mars à 9 h 07 s'affiche 5059-03-03. Une disposition comme "YYYY-MM-DD" ne contient aucun élément et s'affiche telle quelle. Si des dates formatées ont l'air étranges, vérifiez que la disposition utilise exactement les valeurs de référence.

Parser des chaînes en instants

time.Parse(layout, value) utilise les mêmes dispositions, et renvoie une erreur que vous devez vérifier :

Sans fuseau dans l'entrée, Parse renvoie de l'UTC. La même chaîne d'heure locale peut désigner des instants différents selon le fuseau, c'est pourquoi ParseInLocation existe. Le message d'erreur nomme la partie qui n'a pas correspondu, ce qui aide quand vous déboguez une disposition.

Fuseaux horaires

Un time.Time est un instant plus une localisation utilisée pour l'affichage. Changer la localisation avec In change la façon dont il s'affiche, pas l'instant qu'il représente.

  • time.UTC est toujours disponible. Stockez et transmettez les instants en UTC (ou en RFC 3339 avec un décalage) et ne convertissez que pour l'affichage.
  • time.Local est le fuseau de la machine. Sur les serveurs et dans les conteneurs, c'est souvent l'UTC, et sur un portable ce n'est pas le cas, donc le code qui en dépend se comporte différemment selon l'endroit.
  • time.LoadLocation("Europe/Berlin") lit la base IANA du système d'exploitation. Les images de conteneur minimales ne l'ont souvent pas, et l'appel renvoie alors une erreur. L'import blanc _ "time/tzdata" intègre la base dans votre binaire (environ 450 Ko) pour que cela fonctionne toujours. Gérez toujours l'erreur.
  • time.FixedZone(name, offsetSeconds) crée un fuseau avec un décalage constant. Il n'a pas de règles d'heure d'été, donc utilisez-le pour des décalages que vous avez reçus, pas pour des régions nommées.

Arithmétique et comparaison

À remarquer dans la sortie :

  • AddDate(0, 1, 0) sur le 31 janvier donne le 3 mars, pas le 28 février. Go ajoute un mois pour obtenir « 31 février » puis normalise le dépassement. Si vous avez besoin de « même jour le mois suivant, borné », écrivez cette logique vous-même.
  • Sub renvoie une Duration, qui plafonne à environ 292 ans. Pour des différences en jours calendaires, comparez des dates à minuit UTC et divisez par 24 heures.
  • Pour obtenir le début de la journée, reconstruisez l'instant à partir de Date(). t.Truncate(24 * time.Hour) arrondit par rapport à l'instant zéro en UTC, donc donne une mauvaise réponse pour tout fuseau autre que l'UTC.

Comparez avec Equal, Before, After, jamais avec ==. time.Now() inclut une lecture de l'horloge monotone, utilisée pour que time.Since reste correct si l'horloge murale est ajustée. == compare aussi cette lecture et la localisation, donc deux valeurs Time du même instant peuvent être inégales. Pour la même raison, n'utilisez pas time.Time comme clé de map sans le normaliser d'abord (t.UTC().Round(0) retire la lecture monotone).

Le time.Time zéro est le 1er janvier de l'an 1, 00:00 UTC. Testez-le avec t.IsZero().

Mesurer le temps écoulé

start := time.Now()
doWork()
log.Printf("doWork took %v", time.Since(start))

time.Since(start) équivaut à time.Now().Sub(start), et time.Until(deadline) à deadline.Sub(time.Now()). Les deux utilisent l'horloge monotone quand elle est disponible, donc ils résistent aux changements de l'horloge système. Pour mesurer les performances du code, utilisez les benchmarks du package testing plutôt qu'un chronométrage à la main.

Timers et tickers

time.After(d) renvoie un channel qui reçoit une fois après d. Un time.Timer est la même chose avec une méthode Stop. Un time.Ticker fournit une valeur à chaque période jusqu'à ce que vous l'arrêtiez.

Les trois ticks à 20, 40 et 60 ms arrivent bien avant le timer de 110 ms, donc le programme s'arrête après le troisième tick. time.AfterFunc(d, f) exécute f dans sa propre goroutine après d, ce qui est pratique pour un travail différé ponctuel.

Depuis Go 1.23, les timers et tickers qui ne sont plus référencés sont récupérés par le ramasse-miettes même si vous n'appelez jamais Stop, et le channel d'un timer arrêté ou réinitialisé ne fournit plus de valeur périmée. Appeler Stop avec defer reste la façon claire de dire que la vie du ticker est terminée. Quand une limite de temps s'applique à toute une opération plutôt qu'à une seule attente, un context.WithTimeout se lit généralement mieux qu'un timer.

Le temps en JSON

time.Time se sérialise automatiquement en JSON vers et depuis des chaînes RFC 3339, avec une précision à la nanoseconde :

type Event struct {
	Name string    `json:"name"`
	At   time.Time `json:"at"`
}
// {"name":"deploy","at":"2026-09-23T14:30:00Z"}

Une chaîne JSON dans un autre format échoue à la désérialisation. Pour des timestamps Unix ou des formats personnalisés, stockez un int64 ou une chaîne et convertissez, ou définissez un type avec son propre UnmarshalJSON.

Erreurs courantes

  • time.Sleep(1) ou time.Sleep(n) avec un nombre seul. Ce sont des nanosecondes.
  • Des dispositions avec les mauvais chiffres. "2023-01-01" ou "YYYY-MM-DD" ne sont pas des dispositions. Utilisez "2006-01-02".
  • Confondre minutes et mois. Les minutes sont 04, les mois 01. "15:01" affiche l'heure puis le mois, pas la minute.
  • Comparer avec ==. Utilisez Equal.
  • Compter sur time.Local. Il diffère d'une machine à l'autre. Soyez explicite avec time.UTC ou une localisation chargée.
  • Ignorer l'erreur de LoadLocation ou de Parse. Les deux échouent sur de vraies entrées. Un Parse en échec renvoie l'instant zéro, qui s'affiche comme l'an 1, et un LoadLocation en échec renvoie une localisation nil qui fait paniquer t.In(loc).

Questions fréquentes

Comment faire une pause (sleep) en Go ?

Appelez time.Sleep avec un time.Duration : time.Sleep(2 * time.Second) ou time.Sleep(500 * time.Millisecond). Un nombre seul comme time.Sleep(2) compile mais dort 2 nanosecondes, parce qu'une Duration compte des nanosecondes. Sleep ne bloque que la goroutine courante.

Pourquoi Go utilise-t-il 2006-01-02 15:04:05 pour les formats de date ?

Go formate les dates par l'exemple. La disposition est l'heure de référence Mon Jan 2 15:04:05 MST 2006 écrite comme vous voulez que votre sortie apparaisse. Ses parties se suivent dans l'ordre américain : mois 1, jour 2, heure 3 (15 sur une horloge de 24 heures), minute 4, seconde 5, année 6 (2006), décalage horaire 7 (-0700). Donc "2006-01-02" signifie année-mois-jour et "02/01/2006" signifie jour/mois/année.

Comment parser une chaîne de date en Go ?

Utilisez time.Parse(layout, value) avec une disposition écrite à partir de l'heure de référence : t, err := time.Parse("2006-01-02", "2026-09-23"). Vérifiez toujours err. Sans information de fuseau dans la chaîne, le résultat est en UTC ; utilisez time.ParseInLocation pour l'interpréter dans un autre fuseau.

Comment obtenir un timestamp Unix en Go ?

time.Now().Unix() renvoie les secondes écoulées depuis le 1er janvier 1970 UTC sous forme de int64. UnixMilli(), UnixMicro() et UnixNano() donnent des unités plus fines. Pour la conversion inverse, utilisez time.Unix(sec, 0) ou time.UnixMilli(ms).

Comment comparer deux instants en Go ?

Utilisez t1.Before(t2), t1.After(t2) et t1.Equal(t2). N'utilisez pas == : il compare aussi la localisation et la lecture de l'horloge monotone, donc deux valeurs du même instant peuvent être inégales. t2.Sub(t1) donne la différence sous forme de Duration.

Coddy programming languages illustration

Apprendre à coder avec Coddy

COMMENCER