Trabalhando com fusos horários em Rust: guia completo para desenvolvedores backend

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Introdução: por que o tempo é uma dor de cabeça

\n\n

Em qualquer projeto sério em Rust, seja um servidor web em Actix, um parser de logs ou um sistema de monitoramento, mais cedo ou mais tarde surge a questão: como trabalhar corretamente com fusos horários em Rust. Parece simples, não? Pegue um timestamp, exiba na tela — e pronto. Mas a realidade é cruel: um fuso horário esquecido transforma logs em bagunça, e o banco de dados começa a mentir.

\n\n

Neste artigo, vamos explorar como o ecossistema Rust resolve o problema do tempo. Você aprenderá por que o chrono se tornou o padrão de facto, como não enlouquecer com UTC e Local, e como lidar com fusos horários exóticos como "Asia/Yekaterinburg" sem dor. Vamos lá!

\n\n

Por que a biblioteca padrão do Rust não é suficiente?

\n\n

Em std::time temos SystemTime, Instant e Duration. Isso é suficiente para medições de desempenho e temporizadores simples. Mas quando se trata de trabalhar com fusos horários em Rust, a biblioteca padrão falha: não há parsing de strings como "2024-03-15T10:30:00+05:00", nem informações sobre fusos horários, nem conversão de UTC para hora local.

\n\n

É aqui que entra a crate chrono. É um canivete suíço para datas e horas em Rust. Vamos instalá-la no Cargo.toml:

\n\n
[dependencies]\nchrono = { version = "0.4", features = ["serde"] }
\n\n

A flag serde é necessária para serialização/desserialização — será útil se você trabalhar com APIs JSON.

\n\n

Fundamentos do chrono: UTC, Local e tempo ingênuo

\n\n

No chrono, existem três tipos principais para representar um momento no tempo:

\n\n
    \n
  • DateTime<Utc> — hora em UTC. O padrão ouro para servidores.
  • \n
  • DateTime<Local> — hora local do sistema. Conveniente para logs no desktop.
  • \n
  • NaiveDateTime — hora "ingênua" sem fuso horário. Perigoso, mas às vezes necessário.
  • \n
\n\n

Vamos ver como obter a hora atual em diferentes fusos:

\n\n
use chrono::{Utc, Local, DateTime};\n\nfn main() {\n    let utc_now: DateTime<Utc> = Utc::now();\n    println!("Agora em UTC: {}", utc_now);\n\n    let local_now: DateTime<Local> = Local::now();\n    println!("Agora localmente: {}", local_now);\n}
\n\n

Execute este código — e você verá a diferença. Observe: DateTime é um tipo genérico parametrizado pelo fuso horário. Isso significa que o compilador não permitirá que você acidentalmente some hora UTC com Local sem uma conversão explícita. Segurança de tipos a serviço do tempo!

\n\n

Conversão entre fusos horários

\n\n

A tarefa mais comum é converter UTC para a hora local do usuário. Suponha que seu servidor armazene tudo em UTC e o cliente esteja no fuso horário Asia/Yekaterinburg (UTC+5). Como fazer isso?

\n\n

Use o método with_timezone:

\n\n
use chrono::{Utc, Local, TimeZone, DateTime};\n\nfn main() {\n    let utc_time: DateTime<Utc> = Utc::now();\n    \n    // Converter para a hora local do sistema\n    let local_time: DateTime<Local> = utc_time.with_timezone(&Local);\n    println!("UTC: {} -> Local: {}", utc_time, local_time);\n    \n    // Se precisar de um fuso específico — use FixedOffset\n    let ekb_offset = chrono::FixedOffset::east_opt(5 * 3600).unwrap();\n    let ekb_time: DateTime<FixedOffset> = utc_time.with_timezone(&ekb_offset);\n    println!("UTC: {} -> EKB: {}", utc_time, ekb_time);\n}
\n\n

Observe: FixedOffset::east_opt retorna Option, porque nem todo deslocamento é válido (por exemplo, 25 horas é exagero). Sempre trate o None.

\n\n

E se o seu trabalho com fusos horários em Rust for mais complexo do que um simples deslocamento fixo? Por exemplo, precisa considerar o horário de verão? É aqui que a crate

Blogs

Book Recommendations