Как получить текущее время в миллисекундах в Rust?
Используем стандартную библиотеку: самый простой и надёжный способ
В Rust получение текущего времени в миллисекундах — не такая тривиальная задача, как в интерпретируемых языках, но после понимания пары концепций всё становится просто. Основная сложность — работа с типами Result и Duration. Давай разберёмся по шагам.
Самый прямолинейный способ — использовать std::time::SystemTime и UNIX_EPOCH. Вот готовый код:
use std::time::{SystemTime, UNIX_EPOCH};
fn main() {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("System time is before UNIX epoch!");
let millis = now.as_millis(); // u128
println!("Текущее время в миллисекундах: {}", millis);
}
Объяснение по шагам:
SystemTime::now()— получаем текущий момент времени (структураSystemTime)..duration_since(UNIX_EPOCH)— вычисляем разницу между текущим временем и началом эпохи Unix (1 января 1970 года). ВозвращаетResult<Duration, SystemTimeError>..expect(...)— если время оказалось раньше 1970 года (что маловероятно), программа запаникует с понятным сообщением. Для продакшена лучше использоватьunwrap()или обработку ошибок.as_millis()— метод уDuration, который возвращает общее количество миллисекунд какu128(от 0 до 2^128-1, что хватит на миллиарды лет).
Если тебе нужно именно u64 (например, для совместимости с API), можно преобразовать:
let millis_u64 = now.as_millis() as u64;
Или если нужны секунды с дробной частью (как в JavaScript):
let secs_f64 = now.as_secs_f64();
let millis_f64 = secs_f64 * 1000.0;
Альтернатива: крейт chrono (для сложных манипуляций с датами)
Если тебе нужно не только текущее время, но и форматирование, часовые пояса, парсинг — лучше использовать chrono. Добавь в Cargo.toml:
[dependencies]
chrono = "0.4"
Код для получения миллисекунд:
use chrono::Utc;
fn main() {
let now = Utc::now();
let millis = now.timestamp_millis(); // i64 (может быть отрицательным для дат до 1970 года)
println!("Текущее время: {}", millis);
}
Обрати внимание: timestamp_millis() возвращает i64, а не u64, потому что chrono поддерживает даты с 0001 по 9999 год. Для современных дат это не проблема.
Какой способ выбрать?
- Только замер времени или timestamp — используй стандартную библиотеку (быстрее, без зависимостей).
- Работа с датами, форматирование, часовые пояса — бери
chrono. - Замер производительности — лучше использовать
std::time::Instant, он монотонный и не зависит от системных изменений времени.
Пример с Instant для замера:
use std::time::Instant;
let start = Instant::now();
// ... твой код ...
let duration = start.elapsed();
println!("Время выполнения: {} ms", duration.as_millis());
Надеюсь, теперь стало понятнее! Главное — запомнить цепочку: SystemTime::now() → duration_since(UNIX_EPOCH) → as_millis(). Удачи в изучении Rust!
Бонус: получаем миллисекунды без unwrap и с обработкой ошибок
Если ты пишешь библиотеку или критичный к ошибкам код, лучше избегать expect и unwrap. Вот вариант с корректной обработкой:
use std::time::{SystemTime, UNIX_EPOCH};
fn get_millis() -> Option<u64> {
SystemTime::now()
.duration_since(UNIX_EPOCH)
.ok()
.map(|d| d.as_millis() as u64)
}
fn main() {
match get_millis() {
Some(millis) => println!("{}", millis),
None => eprintln!("Ошибка: системное время раньше 1970 года"),
}
}
Метод .ok() преобразует Result в Option, а .map() применяет функцию к значению внутри Some. Такой код безопаснее и не вызовет панику.
Ещё один лайфхак: если тебе нужно время в миллисекундах для логирования, часто проще использовать крейт log с форматтером, который сам добавляет timestamp. Но для ручного контроля — приведённый выше способ идеален.