O pacote time
Nesta aula, exploramos o pacote time da linguagem Go, que fornece funcionalidades para manipulação de tempo, duração, formatação, timers, tickers e fusos horários. Aprendemos a usar os tipos Time e Duration, como formatar datas usando o layout de referência, criar timers e tickers com canais, e trabalhar com fusos horários. A aula inclui exemplos práticos e exercícios para fixação.
O pacote time é um dos pacotes fundamentais da biblioteca padrão de Go. Ele fornece tipos e funções para medir e manipular o tempo, como horas, datas, durações, temporizadores e fusos horários. Compreender este pacote é essencial para qualquer programa que precise lidar com agendamento, logs, medição de desempenho ou operações sensíveis ao tempo.
Nesta aula, vamos explorar os principais componentes: o tipo Time que representa um instante no tempo, o tipo Duration que representa um intervalo, a formatação de datas usando um layout de referência (diferente da maioria das linguagens), a criação de timers e tickers para eventos periódicos, e o tratamento de fusos horários.
Time e Duration
O tipo time.Time representa um ponto no tempo com precisão de nanossegundos. Você pode obter a hora atual com time.Now() e criar instantes específicos com time.Date(). O tipo time.Duration representa um intervalo entre dois instantes, expresso em nanossegundos, mas com constantes para horas, minutos, segundos etc.
Exemplo básico de criação e manipulação:
package main
import (
"fmt"
"time"
)
func main() {
agora := time.Now()
fmt.Println("Agora:", agora)
// Criar uma data específica: 2025-01-15 14:30:00 UTC
data := time.Date(2025, time.January, 15, 14, 30, 0, 0, time.UTC)
fmt.Println("Data específica:", data)
// Diferença entre duas datas
diferenca := data.Sub(agora)
fmt.Println("Diferença:", diferenca)
fmt.Println("Em horas:", diferenca.Hours())
// Adicionar duração
depois := agora.Add(2 * time.Hour)
fmt.Println("Daqui a 2 horas:", depois)
}Formatação (layout de referência)
Em Go, a formatação de datas usa um layout de referência baseado em uma data específica: Mon Jan 2 15:04:05 MST 2006 (que é 01/02 15:04:05, ou seja, mês-dia hora:minuto:segundo ano). Você usa este layout para formatar e analisar strings. Por exemplo, para formatar no formato brasileiro (dd/mm/aaaa):
package main
import (
"fmt"
"time"
)
func main() {
agora := time.Now()
layout := "02/01/2006 15:04:05"
fmt.Println("Formatado:", agora.Format(layout))
// Parse de string para time
str := "15/01/2025 10:30:00"
parsed, err := time.Parse("02/01/2006 15:04:05", str)
if err != nil {
fmt.Println("Erro:", err)
return
}
fmt.Println("Parsed:", parsed)
}O layout de referência deve ser memorizado: Mon Jan 2 15:04:05 MST 2006. Cada parte representa um campo: dia da semana, mês, dia, hora, minuto, segundo, fuso horário e ano. Você pode omitir partes não desejadas.
Timers e tickers
Timers e tickers são mecanismos para executar ações após um intervalo ou repetidamente. Um time.Timer dispara uma única vez após um determinado período, enviando um valor para o canal C. Um time.Ticker dispara repetidamente em intervalos regulares, também através de um canal.
Exemplo de timer:
package main
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(2 * time.Second)
fmt.Println("Timer iniciado, aguardando...")
<-timer.C // bloqueia até o timer disparar
fmt.Println("Timer disparou!")
// Timer pode ser parado antes de disparar
timer2 := time.NewTimer(1 * time.Second)
if timer2.Stop() {
fmt.Println("Timer2 parado antes de disparar")
}
}Exemplo de ticker:
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(500 * time.Millisecond)
go func() {
for t := range ticker.C {
fmt.Println("Tick em", t)
}
}()
time.Sleep(2 * time.Second)
ticker.Stop()
fmt.Println("Ticker parado")
}Fusos
Go suporta fusos horários através do tipo time.Location. Você pode carregar um fuso usando time.LoadLocation e associá-lo a um time. É importante usar o banco de dados IANA (ex: "America/Sao_Paulo", "Europe/London").
Exemplo:
package main
import (
"fmt"
"time"
)
func main() {
// Carregar fuso horário de São Paulo
loc, err := time.LoadLocation("America/Sao_Paulo")
if err != nil {
fmt.Println("Erro ao carregar fuso:", err)
return
}
agora := time.Now()
fmt.Println("UTC:", agora)
fmt.Println("São Paulo:", agora.In(loc))
// Criar data em um fuso específico
data := time.Date(2025, time.January, 15, 14, 30, 0, 0, loc)
fmt.Println("Data em SP:", data)
// Converter entre fusos
utc := data.UTC()
fmt.Println("Data em UTC:", utc)
}Referências
- Documentação oficial do pacote time
- Blog oficial de Go
- Lista de fusos horários IANA
- Go by Example: Time
- Go by Example: Timers
- Go by Example: Tickers
Exercícios
- Crie um programa que exiba a data e hora atuais no formato "dd/mm/aaaa HH:MM:SS" (horário de Brasília).
- Escreva uma função que receba duas strings no formato "2006-01-02 15:04:05" e retorne a diferença em horas entre elas.
- Crie um timer que, após 3 segundos, imprima "Tempo esgotado!" e encerre o programa.
- Implemente um ticker que imprima a hora atual a cada segundo, executando por 5 segundos, e depois pare.
- Crie uma função que converta uma data em UTC para o fuso horário de Tóquio (Asia/Tokyo) e exiba a data formatada como "2006/01/02 15:04:05".
package main
import (
"fmt"
"time"
)
func main() {
loc, _ := time.LoadLocation("America/Sao_Paulo")
agora := time.Now().In(loc)
layout := "02/01/2006 15:04:05"
fmt.Println(agora.Format(layout))
}
package main
import (
"fmt"
"time"
)
func diferencaHoras(data1, data2 string) (float64, error) {
layout := "2006-01-02 15:04:05"
t1, err := time.Parse(layout, data1)
if err != nil {
return 0, err
}
t2, err := time.Parse(layout, data2)
if err != nil {
return 0, err
}
return t2.Sub(t1).Hours(), nil
}
func main() {
diff, _ := diferencaHoras("2025-01-01 00:00:00", "2025-01-02 12:00:00")
fmt.Println("Diferença em horas:", diff)
}
package main
import (
"fmt"
"time"
)
func main() {
timer := time.NewTimer(3 * time.Second)
<-timer.C
fmt.Println("Tempo esgotado!")
}
package main
import (
"fmt"
"time"
)
func main() {
ticker := time.NewTicker(1 * time.Second)
done := make(chan bool)
go func() {
time.Sleep(5 * time.Second)
done <- true
}()
for {
select {
case t := <-ticker.C:
fmt.Println("Hora:", t)
case <-done:
ticker.Stop()
fmt.Println("Ticker parado")
return
}
}
}
package main
import (
"fmt"
"time"
)
func main() {
utc := time.Date(2025, time.January, 15, 14, 30, 0, 0, time.UTC)
loc, _ := time.LoadLocation("Asia/Tokyo")
tokyo := utc.In(loc)
layout := "2006/01/02 15:04:05"
fmt.Println(tokyo.Format(layout))
}