Time in Milliseconds in Rust: Don't Fall into These 5 Traps
\n\n“How do I get the current time in milliseconds?” — this question from Stack Overflow has gathered thousands of views. It seems simple, right? But Rust is not Python or JavaScript. Here, it's easy to confuse a UNIX timestamp with monotonic time, forget about platform dependence, or step on performance landmines.
In this article, we'll break down the top mistakes that beginners (and not only) make when working with time in Rust. You'll learn how to get time in milliseconds correctly, reliably, and quickly. Let's go!
\n\nMistake #1: Monotonic Time Instead of UNIX Time
\n\nThe most common trap is using std::time::Instant to get the “current time”. Instant in Rust measures monotonic time — it's perfect for measuring intervals, but absolutely useless if you need a timestamp (e.g., for logging or sending to a server).
// ❌ ERROR: you can't get a timestamp this way\nuse std::time::Instant;\n\nlet now = Instant::now();\n// Instant has no method duration_since(UNIX_EPOCH)!\n// You will get a compilation error\n\n\nHow to do it correctly? Use std::time::SystemTime. This type knows about system time and can count from UNIX_EPOCH (January 1, 1970).
use std::time::{SystemTime, UNIX_EPOCH};\n\nlet now = SystemTime::now()\n .duration_since(UNIX_EPOCH)\n .expect("Time went backwards?");\n \nlet millis = now.as_millis(); // u128\nprintln!("Current time in ms: {}", millis);\n\n\n💡 Tip: duration_since returns a Result because, theoretically, system time could be set before 1970. On modern systems, you can safely handle this exception with expect or unwrap.
Mistake #2: Forgetting About Platform Dependence
\n\nIt would seem that SystemTime::now() is a cross-platform solution. But there's a nuance. On some platforms (e.g., old Linux kernels or embedded systems), SystemTime may behave unstably or not even support millisecond precision.
The second pitfall is overflow. The u128 type in as_millis() is unlikely to overflow (it's enough for billions of years), but if you need to store the time in a database or transmit it over a network — milliseconds in u128 might be unexpected for other systems.
// ✅ Safe conversion to u64 (enough for ~584 million years)\nlet millis_u64: u64 = now.as_millis() as u64;\n\n\nHow to avoid it? Always check the documentation for your target platform. For embedded systems, consider the embassy-time crate or use std::time with caution.
Mistake #3: Ignoring the chrono Crate
\n\nThe Rust standard library provides basic capabilities. But if you need to work with time zones, formatting, or date parsing — don't reinvent the wheel. The chrono crate is the de facto standard for working with dates and times in Rust.
// Add to 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⚠️ Important: timestamp_millis() returns i64, not u128. This is done for compatibility with UNIX time (it can be negative for dates before 1970). In most cases, i64 is what you need.
💡 Co