Fuso Horário & Gotchas do time.Parse
Um relatório mostra a data de ontem para eventos que aconteceram hoje, mas apenas para usuários em um fuso horário e apenas após o horário de verão.
Busque em todas as páginas da documentação
Um relatório mostra a data de ontem para eventos que aconteceram hoje, mas apenas para usuários em um fuso horário e apenas após o horário de verão.
Esta página cobre as regras de localização do time.Parse, o comportamento do relógio monotônico, a serialização JSON e as etapas de depuração que expõem defeitos de tempo sem adivinhação.
Valores time.Time representam um instante na linha do tempo mais um local opcional para exibição.
Erros de análise - omitir a zona no layout, misturar local e UTC, ignorar o horário de verão - produzem bugs sutis de horas de diferença que testes em uma zona não detectam.
APIs JSON adicionam outra camada: a serialização padrão usa RFC3339 UTC, enquanto os clientes podem interpretar strings como hora local de parede.
Cartão de receita de referência rápida - pronto para copiar e colar.
// Analisa com zona explícita no layout
t, err := time.Parse(time.RFC3339, "2026-07-15T09:00:00-07:00")
// Analisa hora local de parede em uma zona específica
loc, _ := time.LoadLocation("America/Los_Angeles")
t, err := time.ParseInLocation("2006-01-02 15:04", "2026-07-15 09:00", loc)
// Armazena/compara em UTC, exibe na zona do usuário
utc := t.UTC()
display := utc.In(loc)Quando usar isso:
time.Now() com tempos históricos analisadospackage main
import (
"encoding/json"
"fmt"
"time"
)
type Event struct {
At time.Time `json:"at"`
}
func main() {
// Análise sem zona -> UTC
t1, _ := time.Parse("2006-01-02 15:04:05", "2026-07-15 09:00:00")
fmt.Println("analisado sem zona:", t1.Format(time.RFC3339), "loc", t1.Location())
loc, _ := time.LoadLocation("America/New_York")
t2, _ := time.ParseInLocation("2006-01-02 15:04:05", "2026-07-15 09:00:00", loc)
fmt.Println("analisado NY: ", t2.Format(time.RFC3339), "loc", t2.Location())
fmt.Println("instante igual?", t1.Equal(t2))
b, _ := json.Marshal(Event{At: t2})
fmt.Println("json:", string(b))
}O que isso demonstra:
time.Parse sem zona na string de layout atribui UTC para entrada sem zonaEqual compara instantes; a saída de Format depende do localZ para UTCMon Jan 2 15:04:05 MST 2006 → use o estilo 2006-01-02 nos layoutstime.Parse usa UTC quando o layout não tem zona; ParseInLocation define a zona pretendidatime.Time pode incluir leitura monotônica para Sub/Since; removido por Format e JSONtime.Now() retorna a zona local do ambiente, a menos que você chame UTC()| Entrada | Bug Típico | Correção |
|---|---|---|
Apenas data "2026-07-15" | Analisado como meia-noite UTC | Documente o contrato; use time.Date com zona |
| RFC3339 com deslocamento | OK se o layout incluir deslocamento | Use a constante time.RFC3339 |
| Número de milissegundos Unix | Instante agnóstico de zona | Prefira para APIs que cruzam zonas |
Valor zero de time.Time | JSON "0001-01-01T00:00:00Z" | Use ponteiro ou omita vazio |
// Compare instantes, não strings formatadas
if !a.UTC().Equal(b.UTC()) { /* momento diferente */ }
// Trunca para o dia do calendário em uma zona
day := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, loc)"2006-01-02 15:04:05" se torna UTC, não local. Correção: ParseInLocation ou exija deslocamento na entrada.Format - Strings diferem para o mesmo instante em zonas diferentes. Correção: Equal ou compare unix UTC.time.Now().Location() é UTC em contêineres - Imagens sem TZ podem usar UTC; laptops usam local. Correção: defina TZ ou sempre UTC() em servidores.LoadLocation falha em distroless sem o pacote tzdata. Correção: incorpore a importação _ "time/tzdata".Sub. Correção: use t.UTC() antes da aritmética entre tempos analisados e de relógio.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Armazenar segundos/milissegundos Unix em JSON | APIs globais, clientes simples | Humanos leem JSON bruto com frequência |
Strings time.RFC3339 | Interoperabilidade padrão HTTP/JSON | Precisa apenas de data sem hora |
Tipos de data civil (terceiros) | Agendamento de calendário sem zona | Já comprometido com time.Time em todos os lugares |
| Sempre UTC no banco de dados | Consistência de relatórios | Regras de cobrança de meia-noite local precisam de tabela de zona |
MarshalJSON em time.Time emite RFC3339 UTC.
O instante é preservado; a zona de exibição é perdida, a menos que você adicione um campo separado.
Use os componentes de tempo de referência: ano 2006, mês 01, dia 02, hora 15, minuto 04, segundo 05, zona MST ou -0700.
Copie constantes como time.RFC3339 quando corresponderem à entrada.
Não para layouts sem zona - UTC é usado.
Apenas ParseInLocation ou deslocamentos na string definem a zona.
Uma leitura interna para medir durações imune a saltos do relógio de parede.
Ele não aparece na saída formatada e é removido ao serializar.
Registre t.Format(time.RFC3339), t.Location() e t.UTC().Format(time.RFC3339).
Verifique se a entrada não tinha deslocamento e foi analisada como UTC.
Imagens mínimas não possuem arquivos de informações de zona.
Incorpore _ "time/tzdata" ou instale tzdata na imagem.
Armazene e compare em UTC; converta para a zona do usuário na fronteira da UI.
Documente o contrato da API se os clientes enviarem tempos locais.
Drivers escaneiam para time.Time com localização frequentemente UTC.
Escanear para string perde a segurança do tipo - prefira time.Time e zona explícita na escrita.
time.Parse("2006-01-02", "2026-07-15") é meia-noite UTC.
Regras de "dia local" de faturamento precisam de ParseInLocation com a zona comercial.
Add usa duração absoluta na linha do tempo.
A aritmética de dias do calendário precisa de AddDate na localização de destino.
timestamppb armazena instante UTC.
Converta com AsTime() e .In(loc) para exibição.
Teste em tabela com time.FixedZone e deslocamentos conhecidos.
Defina TZ na matriz de CI ou use LoadLocation com tzdata incorporado.
Versões de Stack: Esta página foi escrita para Go 1.26.x (GC padrão Green Tea, go fix modernizers - verifique o patch na compilação), chi (última versão - verifique na compilação), gin (última versão - verifique na compilação), echo (última versão - verifique na compilação), google.golang.org/grpc (última versão - verifique na compilação), sigs.k8s.io/controller-runtime (última versão - verifique na compilação), kubebuilder (última versão - verifique na compilação), tinygo (última versão - verifique os alvos de placa na compilação), wazero (última versão - verifique na compilação) e golangci-lint (última versão - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 19 de jul. de 2026