Obsługa czasu jest dość skomplikowana. Powszechne błędne założenia na temat czasu obejmują następujące.

  1. Dzień składa się z 24 godzin.
  2. Godzina zawiera 60 minut.
  3. Tydzień składa się z siedmiu dni.
  4. Rok składa się z 365 dni.

Na przykład, 1 wskazuje, że dodanie 24 godzin do określonego punktu w czasie nie zawsze skutkuje nowym dniem kalendarzowym.

Dlatego też, przy operacjach na czasie zawsze należy korzystać z pakietu "time", ponieważ pomaga on obsługiwać te błędne założenia w sposób bezpieczniejszy i bardziej dokładny.

Używanie time.Time do reprezentowania chwili czasu

Podczas operacji na chwilach czasowych używaj time.Time i jego metod do porównywania, dodawania lub odejmowania czasu.

Nie zalecane:

func isActive(now, start, stop int) bool {
  return start <= now && now < stop
}

Zalecane:

func isActive(now, start, stop time.Time) bool {
  return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}

Używanie time.Duration do reprezentowania okresów czasowych

Podczas operacji na okresach czasowych używaj time.Duration.

Nie zalecane:

func poll(delay int) {
  for {
    // ...
    time.Sleep(time.Duration(delay) * time.Millisecond)
  }
}
poll(10) // Czy to w sekundach czy milisekundach?

Zalecane:

func poll(delay time.Duration) {
  for {
    // ...
    time.Sleep(delay)
  }
}
poll(10*time.Second)

Wracając do pierwszego przykładu, kiedy dodajemy 24 godziny do chwili czasu, używana metoda zależy od intencji. Jeśli chcemy ten sam punkt czasowy na kolejny dzień kalendarzowy (następnego dnia po bieżącym dniu), powinniśmy użyć Time.AddDate. Jednak jeśli chcemy zagwarantować, że określony moment jest 24 godziny później niż poprzedni, powinniśmy użyć Time.Add.

nowyDzien := t.AddDate(0 /* lata */, 0 /* miesiące */, 1 /* dni */)
możeNowyDzien := t.Add(24 * time.Hour)

Korzystanie z time.Time i time.Duration z zewnętrznymi systemami

Zawsze, gdy to możliwe, stosuj time.Duration i time.Time w interakcji z zewnętrznymi systemami, na przykład:

Gdy time.Duration nie może być użyty w tych interakcjach, użyj int lub float64 i dołącz jednostkę w nazwie pola.

Na przykład, ponieważ encoding/json nie obsługuje time.Duration, jednostka jest dołączana do nazwy pola.

Nie zalecane:

// {"interval": 2}
type Config struct {
  Interval int `json:"interval"`
}

Zalecane:

// {"intervalMillis": 2000}
type Config struct {
  IntervalMillis int `json:"intervalMillis"`
}

Gdy time.Time nie może być użyty w tych interakcjach, chyba że inaczej ustalono, użyj string i sformatuj znaczniki czasowe zgodnie z RFC 3339. Domyślnie Time.UnmarshalText używa tego formatu i można go użyć w Time.Format oraz time.Parse za pomocą time.RFC3339.

Choć nie jest to praktyczny problem, należy zauważyć, że pakiet "time" nie obsługuje analizy znaczników czasu sekundy przestępnej (8728) i nie uwzględnia sekund przestępnych w obliczeniach (15190). Jeśli porównujesz dwie chwile czasu, różnica nie będzie uwzględniała ewentualnych sekund przestępnych, które mogły wystąpić między tymi dwoma momentami.