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

Exercícios

  1. Crie um programa que exiba a data e hora atuais no formato "dd/mm/aaaa HH:MM:SS" (horário de Brasília).
  2. ✓ Resposta:
    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))
    }
  3. 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.
  4. ✓ Resposta:
    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)
    }
  5. Crie um timer que, após 3 segundos, imprima "Tempo esgotado!" e encerre o programa.
  6. ✓ Resposta:
    package main
    
    import (
        "fmt"
        "time"
    )
    
    func main() {
        timer := time.NewTimer(3 * time.Second)
        <-timer.C
        fmt.Println("Tempo esgotado!")
    }
  7. Implemente um ticker que imprima a hora atual a cada segundo, executando por 5 segundos, e depois pare.
  8. ✓ Resposta:
    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
            }
        }
    }
  9. 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".
  10. ✓ Resposta:
    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))
    }