Tiempo en milisegundos en Rust: no caigas en estas 5 trampas
\n\n«¿Cómo obtengo la hora actual en milisegundos?» — esta pregunta en Stack Overflow ha acumulado miles de visitas. Parece que podría ser más simple, ¿verdad? Pero Rust no es Python ni JavaScript. Aquí es fácil confundir un UNIX timestamp con el tiempo monotónico, olvidarse de la dependencia de la plataforma o pisar un rastrillo con el rendimiento.
En este artículo, analizaremos los principales errores que cometen los principiantes (y no solo) al trabajar con el tiempo en Rust. Aprenderá cómo obtener el tiempo en milisegundos de forma correcta, fiable y rápida. ¡Allá vamos!
\n\nError n.º 1: Tiempo monotónico en lugar de tiempo UNIX
\n\nLa trampa más común es usar std::time::Instant para obtener la «hora actual». Instant en Rust mide el tiempo monotónico — es ideal para medir intervalos, pero es absolutamente inútil si necesita un timestamp (por ejemplo, para registro o envío a un servidor).
// ❌ ERROR: así no se obtiene un timestamp\nuse std::time::Instant;\n\nlet now = Instant::now();\n// ¡Instant no tiene el método duration_since(UNIX_EPOCH)!\n// Obtendrá un error de compilación\n\n\n¿Cómo hacerlo correctamente? Use std::time::SystemTime. Este tipo conoce la hora del sistema y puede contar desde UNIX_EPOCH (1 de enero de 1970).
use std::time::{SystemTime, UNIX_EPOCH};\n\nlet now = SystemTime::now()\n .duration_since(UNIX_EPOCH)\n .expect("¿El tiempo retrocedió?");\n \nlet millis = now.as_millis(); // u128\nprintln!("Hora actual en ms: {}", millis);\n\n\n💡 Consejo: duration_since devuelve un Result porque, en teoría, la hora del sistema podría estar configurada antes de 1970. En los sistemas modernos, esta excepción se puede manejar con expect o unwrap.
Error n.º 2: Olvidar la dependencia de la plataforma
\n\nParecería que SystemTime::now() es una solución multiplataforma. Pero hay un matiz. En algunas plataformas (por ejemplo, kernels antiguos de Linux o sistemas embebidos), SystemTime puede comportarse de manera inestable o incluso no admitir precisión de milisegundos.
La segunda piedra oculta es el desbordamiento. Es poco probable que el tipo u128 en as_millis() se desborde (alcanza para miles de millones de años), pero si necesita guardar la hora en una base de datos o transmitirla por la red, los milisegundos en u128 pueden ser una sorpresa para otros sistemas.
// ✅ Conversión segura a u64 (suficiente para ~584 millones de años)\nlet millis_u64: u64 = now.as_millis() as u64;\n\n\n¿Cómo evitarlo? Siempre revise la documentación para su plataforma objetivo. Para sistemas embebidos, considere el crate embassy-time o use std::time con precaución.
Error n.º 3: Ignorar el crate chrono
\n\nLa biblioteca estándar de Rust ofrece capacidades básicas. Pero si necesita trabajar con zonas horarias, formato o análisis de fechas, no reinvente la rueda. El crate chrono es el estándar de facto para trabajar con fecha y hora en Rust.
// Agregue a Cargo.toml: chrono = "0.4"\nuse chrono::Utc;\n\nlet now = Utc::now();\nlet millis = now.timestamp_millis(); // i64\nprintln!("Chrono timestamp: {}", millis);\n\n\n⚠️ Importante: timestamp_millis() devuelve i64, no u128. Esto se hace para la compatibilidad con el tiempo UNIX (puede ser negativo para fechas anteriores a 1970). En la mayoría de los casos, i64 es lo que necesita.
💡 Con