Visao Geral do Modulo std::time
O modulo std::time fornece os tipos fundamentais para trabalhar com tempo em Rust. Diferente de muitas linguagens que misturam tempo absoluto e duracoes, Rust separa esses conceitos em tres tipos distintos:
Duration— representa um intervalo de tempo (sempre positivo)Instant— um ponto no tempo monotonicamente crescente, ideal para medir duracao de operacoesSystemTime— o relogio do sistema, que pode ser ajustado e pode retroceder
Essa separacao intencional evita bugs comuns como usar timestamps do sistema para medir performance (que falha quando o relogio e ajustado). O modulo faz parte da biblioteca padrao e nao requer crates externas para operacoes basicas de tempo.
Tipos e Funcoes Principais
Duration
Duration representa um intervalo de tempo com precisao de nanossegundos. E sempre nao-negativo e imutavel.
| Metodo | Descricao |
|---|---|
Duration::from_secs(u64) | Cria Duration a partir de segundos |
Duration::from_millis(u64) | Cria Duration a partir de milissegundos |
Duration::from_micros(u64) | Cria Duration a partir de microssegundos |
Duration::from_nanos(u64) | Cria Duration a partir de nanossegundos |
Duration::from_secs_f64(f64) | Cria Duration a partir de um float de segundos |
Duration::ZERO | Duration de zero |
.as_secs() | Retorna apenas a parte inteira em segundos |
.as_millis() | Retorna duracao total em milissegundos |
.as_micros() | Retorna duracao total em microssegundos |
.as_nanos() | Retorna duracao total em nanossegundos |
.as_secs_f64() | Retorna como float de segundos |
.subsec_millis() | Retorna a parte fracionaria em milissegundos |
.checked_add(Duration) | Adicao segura (retorna Option) |
.saturating_mul(u32) | Multiplicacao com saturacao |
Instant
Instant usa um relogio monotonico do sistema operacional. Ele nunca retrocede e e ideal para medir duracoes.
| Metodo | Descricao |
|---|---|
Instant::now() | Captura o instante atual |
.elapsed() | Duracao desde este instante ate agora |
.duration_since(Instant) | Duracao entre dois instantes |
.checked_duration_since(Instant) | Versao segura (retorna Option) |
.checked_add(Duration) | Adiciona duracao ao instante |
.checked_sub(Duration) | Subtrai duracao do instante |
SystemTime
SystemTime representa o relogio do sistema (wall clock). Pode ser ajustado pelo usuario ou NTP, podendo retroceder.
| Metodo | Descricao |
|---|---|
SystemTime::now() | Hora atual do sistema |
SystemTime::UNIX_EPOCH | 1 de janeiro de 1970, 00:00:00 UTC |
.duration_since(SystemTime) | Duracao entre dois pontos (pode falhar) |
.elapsed() | Duracao desde este ponto ate agora |
Exemplos Praticos
1. Medindo Tempo de Execucao com Instant
O uso mais comum de std::time e medir quanto tempo uma operacao leva. Instant e a escolha certa porque usa um relogio monotonico:
use std::time::Instant;
fn operacao_custosa() -> u64 {
(0..1_000_000u64).sum()
}
fn main() {
let inicio = Instant::now();
let resultado = operacao_custosa();
let duracao = inicio.elapsed();
println!("Resultado: {resultado}");
println!("Tempo decorrido: {:.2?}", duracao);
println!("Em milissegundos: {:.3}ms", duracao.as_secs_f64() * 1000.0);
}
2. Comparando Performance de Algoritmos
use std::time::Instant;
fn busca_linear(dados: &[i32], alvo: i32) -> Option<usize> {
dados.iter().position(|&x| x == alvo)
}
fn busca_binaria(dados: &[i32], alvo: i32) -> Option<usize> {
dados.binary_search(&alvo).ok()
}
fn medir<F, R>(nome: &str, iteracoes: u32, mut func: F)
where
F: FnMut() -> R,
{
let inicio = Instant::now();
for _ in 0..iteracoes {
std::hint::black_box(func());
}
let total = inicio.elapsed();
let media = total / iteracoes;
println!("{nome}: total={total:.2?}, media={media:.2?}");
}
fn main() {
let dados: Vec<i32> = (0..10_000).collect();
let alvo = 9_999;
let iteracoes = 1_000;
medir("Busca linear ", iteracoes, || busca_linear(&dados, alvo));
medir("Busca binaria", iteracoes, || busca_binaria(&dados, alvo));
}
3. Trabalhando com SystemTime e UNIX_EPOCH
use std::time::{SystemTime, UNIX_EPOCH, Duration};
fn main() {
// Timestamp atual em segundos desde UNIX_EPOCH
let agora = SystemTime::now();
let timestamp = agora
.duration_since(UNIX_EPOCH)
.expect("O relogio do sistema esta antes de 1970!")
.as_secs();
println!("Timestamp Unix atual: {timestamp}");
// Convertendo um timestamp de volta para SystemTime
let data_especifica = UNIX_EPOCH + Duration::from_secs(1_700_000_000);
match data_especifica.elapsed() {
Ok(duracao) => println!("Essa data foi ha {:.1} dias", duracao.as_secs_f64() / 86400.0),
Err(e) => println!("Essa data esta no futuro por {:.1} dias",
e.duration().as_secs_f64() / 86400.0),
}
// SystemTime pode falhar (o relogio pode retroceder)
let t1 = SystemTime::now();
let t2 = SystemTime::now();
match t2.duration_since(t1) {
Ok(d) => println!("Diferenca: {d:?}"),
Err(e) => println!("O relogio retrocedeu! Erro: {e:?}"),
}
}
4. Criando e Manipulando Duracoes
use std::time::Duration;
fn formatar_duracao(d: Duration) -> String {
let total_secs = d.as_secs();
let horas = total_secs / 3600;
let minutos = (total_secs % 3600) / 60;
let segundos = total_secs % 60;
let millis = d.subsec_millis();
if horas > 0 {
format!("{horas}h {minutos}m {segundos}s")
} else if minutos > 0 {
format!("{minutos}m {segundos}s")
} else {
format!("{segundos}.{millis:03}s")
}
}
fn main() {
// Diferentes formas de criar Duration
let d1 = Duration::from_secs(3661); // 1h 1m 1s
let d2 = Duration::from_millis(1500);
let d3 = Duration::from_secs_f64(0.5);
println!("{}", formatar_duracao(d1)); // 1h 1m 1s
println!("{}", formatar_duracao(d2)); // 1.500s
println!("{}", formatar_duracao(d3)); // 0.500s
// Operacoes aritmeticas
let soma = d2 + d3;
println!("Soma: {soma:?}"); // 2s
// Multiplicacao
let triplicado = d3 * 3;
println!("Triplicado: {triplicado:?}"); // 1.5s
// Comparacao
assert!(d1 > d2);
assert_eq!(d2 + d3, Duration::from_secs(2));
}
5. Timeout Simples com Instant
use std::time::{Duration, Instant};
fn processar_com_timeout<F>(timeout: Duration, mut trabalho: F) -> Result<(), String>
where
F: FnMut() -> bool,
{
let inicio = Instant::now();
loop {
if trabalho() {
return Ok(());
}
if inicio.elapsed() > timeout {
return Err(format!(
"Timeout apos {:.2}s",
timeout.as_secs_f64()
));
}
}
}
fn main() {
let mut contador = 0u64;
let resultado = processar_com_timeout(
Duration::from_millis(100),
|| {
contador += 1;
contador >= 1_000_000
},
);
match resultado {
Ok(()) => println!("Concluido apos {contador} iteracoes"),
Err(msg) => println!("{msg} (parcial: {contador} iteracoes)"),
}
}
Padroes Comuns
Medindo Secoes de Codigo
O padrao mais frequente e envolver uma operacao entre Instant::now() e .elapsed():
use std::time::Instant;
fn main() {
let t = Instant::now();
// ... operacao ...
eprintln!("[benchmark] operacao levou {:?}", t.elapsed());
}
Gerando Timestamps para Logs
Para logs e registros, use SystemTime com UNIX_EPOCH:
use std::time::{SystemTime, UNIX_EPOCH};
fn timestamp_millis() -> u128 {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_millis()
}
Aritmetica com Duration
Duration suporta soma, subtracao, multiplicacao e divisao. Versoes checked_* e saturating_* evitam panic em overflow:
use std::time::Duration;
fn main() {
let base = Duration::from_secs(1);
let dobro = base.saturating_mul(2);
let soma = base.checked_add(Duration::from_millis(500));
println!("{dobro:?}, {soma:?}");
}
Quando Usar (e Quando Nao Usar)
Use std::time quando:
- Precisar medir tempo de execucao de operacoes
- Precisar de timestamps Unix simples
- Quiser implementar timeouts basicos
- Precisar comparar performance entre abordagens
Nao use std::time quando:
- Precisar de datas formatadas (dia, mes, ano) — use a crate
chronooutime - Precisar de fusos horarios — use crates externas
- Precisar de benchmarks estatisticamente rigorosos — use
criterion - Precisar de temporizadores assincronos — use
tokio::time
Dica de performance: Instant::now() e extremamente rapido na maioria dos sistemas operacionais (usa clock_gettime no Linux com CLOCK_MONOTONIC). Nao hesite em usa-lo mesmo em hot paths.
Atencao com SystemTime: O resultado de duration_since pode ser um Err se o relogio do sistema foi ajustado para tras. Sempre trate esse caso, especialmente em codigo de producao.
Veja Tambem
- Medir Tempo de Execucao — receita pratica para benchmarking
- Trabalhar com Datas — usando crates externas para datas completas
- Modulo std::fmt — para formatar duracoes em saida customizada
- Visao Geral de std::collections — estruturas de dados cujo desempenho voce pode medir com
Instant - Documentacao oficial — std::time