O tratamento do tempo é bastante complexo. Suposições incorretas comuns sobre o tempo incluem o seguinte.

  1. Um dia consiste em 24 horas.
  2. Uma hora contém 60 minutos.
  3. Uma semana consiste em sete dias.
  4. Um ano compreende 365 dias.

Por exemplo, 1 indica que adicionar 24 horas a um ponto específico no tempo nem sempre resulta em um novo dia no calendário.

Portanto, ao lidar com o tempo, sempre use o pacote "time" pois ele ajuda a lidar com essas suposições incorretas de forma mais segura e precisa.

Utilizando time.Time para Representar o Tempo Instantâneo

Ao lidar com o tempo instantâneo, utilize time.Time e seus métodos para comparar, adicionar ou subtrair tempo.

Não recomendado:

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

Recomendado:

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

Utilizando time.Duration para Representar Durações de Tempo

Ao lidar com durações de tempo, utilize time.Duration.

Não recomendado:

func poll(delay int) {
  for {
    // ...
    time.Sleep(time.Duration(delay) * time.Millisecond)
  }
}
poll(10) // Está em segundos ou milissegundos?

Recomendado:

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

Voltando ao primeiro exemplo, ao adicionar 24 horas a um tempo instantâneo, o método utilizado depende da intenção. Se quisermos o mesmo ponto no tempo no próximo dia do calendário (o dia após o dia atual), devemos usar Time.AddDate. No entanto, se queremos garantir que um certo momento seja 24 horas após o anterior, devemos usar Time.Add.

novoDia := t.AddDate(0 /* anos */, 0 /* meses */, 1 /* dias */)
talvezNovoDia := t.Add(24 * time.Hour)

Usando time.Time e time.Duration com Sistemas Externos

Sempre que possível, use time.Duration e time.Time na interação com sistemas externos, por exemplo:

Quando time.Duration não puder ser usado nessas interações, use int ou float64 e inclua a unidade no nome do campo.

Por exemplo, uma vez que encoding/json não suporta time.Duration, a unidade é incluída no nome do campo.

Não recomendado:

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

Recomendado:

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

Quando time.Time não puder ser usado nessas interações, a menos que acordado de outra forma, use string e formate os carimbos de tempo de acordo com RFC 3339. Por padrão, Time.UnmarshalText usa este formato e pode ser usado em Time.Format e time.Parse através de time.RFC3339.

Embora não seja um problema prático, observe que o pacote "time" não suporta a análise de carimbos de tempo de segundo bissexto (8728), e não leva em consideração os segundos bissextos em cálculos (15190). Se comparar dois momentos no tempo, a diferença não incluirá nenhum segundo bissexto que possa ter ocorrido entre esses dois momentos.