Obsługa czasu jest dość skomplikowana. Powszechne błędne założenia na temat czasu obejmują następujące.
- Dzień składa się z 24 godzin.
- Godzina zawiera 60 minut.
- Tydzień składa się z siedmiu dni.
- 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:
- Flagi wiersza poleceń:
flag
obsługujetime.Duration
za pomocątime.ParseDuration
. - JSON:
encoding/json
obsługuje kodowanietime.Time
do ciągu RFC 3339 za pomocą swojej metodyUnmarshalJSON
. - SQL:
database/sql
obsługuje konwersję kolumnDATETIME
lubTIMESTAMP
dotime.Time
i zwraca, czy podstawowy sterownik to obsługuje. - YAML:
gopkg.in/yaml.v2
obsługuje użycietime.Time
jako ciągu RFC 3339 itime.Duration
za pomocątime.ParseDuration
.
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.