Обработка времени довольно сложна. Общие неправильные предположения о времени включают в себя следующее.
- Сутки состоят из 24 часов.
- Час содержит 60 минут.
- Неделя состоит из семи дней.
- Год включает 365 дней.
Например, 1 указывает на то, что добавление 24 часов к определенному моменту времени не всегда приводит к новому календарному дню.
Поэтому при работе с временем всегда используйте пакет "time"
, поскольку он помогает обрабатывать эти неправильные предположения более безопасным и точным способом.
Использование time.Time
для представления мгновенного времени
При работе с мгновенным временем используйте time.Time
и его методы для сравнения, добавления или вычитания времени.
Не рекомендуется:
func isActive(now, start, stop int) bool {
return start <= now && now < stop
}
Рекомендуется:
func isActive(now, start, stop time.Time) bool {
return (start.Before(now) || start.Equal(now)) && now.Before(stop)
}
Использование time.Duration
для представления продолжительности времени
При работе с продолжительностями времени используйте time.Duration
.
Не рекомендуется:
func poll(delay int) {
for {
// ...
time.Sleep(time.Duration(delay) * time.Millisecond)
}
}
poll(10) // Это в секундах или миллисекундах?
Рекомендуется:
func poll(delay time.Duration) {
for {
// ...
time.Sleep(delay)
}
}
poll(10*time.Second)
Возвращаясь к первому примеру, когда добавляется 24 часа к мгновенному времени, используемый метод зависит от намерения. Если мы хотим получить тот же момент времени на следующий календарный день (на следующий день после текущего), мы должны использовать Time.AddDate
. Однако, если нас интересует то, чтобы убедиться, что определенный момент на 24 часа позже предыдущего, мы должны использовать Time.Add
.
newDay := t.AddDate(0 /* годы */, 0 /* месяцы */, 1 /* дни */)
maybeNewDay := t.Add(24 * time.Hour)
Использование time.Time
и time.Duration
с внешними системами
Взаимодействуя с внешними системами, по возможности используйте time.Duration
и time.Time
, например:
- Командные флаги:
flag
поддерживаетtime.Duration
черезtime.ParseDuration
. - JSON:
encoding/json
поддерживает кодированиеtime.Time
в строку RFC 3339 с помощью методаUnmarshalJSON
. - SQL:
database/sql
поддерживает преобразование столбцовDATETIME
илиTIMESTAMP
вtime.Time
и возвращает значение, если базовый драйвер поддерживает это. - YAML:
gopkg.in/yaml.v2
поддерживает использованиеtime.Time
как строки RFC 3339 иtime.Duration
черезtime.ParseDuration
.
Когда time.Duration
нельзя использовать в таких взаимодействиях, используйте int
или float64
и включайте единицу измерения в имя поля.
Например, поскольку encoding/json
не поддерживает time.Duration
, единица измерения включается в имя поля.
Не рекомендуется:
// {"interval": 2}
type Config struct {
Interval int `json:"interval"`
}
Рекомендуется:
// {"intervalMillis": 2000}
type Config struct {
IntervalMillis int `json:"intervalMillis"`
}
Когда time.Time
нельзя использовать в таких взаимодействиях, если не оговорено иное, используйте string
и форматируйте метки времени согласно RFC 3339. По умолчанию Time.UnmarshalText
использует этот формат, и его можно использовать в Time.Format
и time.Parse
через time.RFC3339
.
Хотя это не практическая проблема, обратите внимание, что пакет "time"
не поддерживает разбор меток времени с високосными секундами (8728) и не учитывает високосные секунды при расчетах (15190). Если вы сравниваете два момента времени, разница не будет включать в себя високосные секунды, которые могли произойти между этими двумя моментами.