Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Тема
Описание
Доп.
  • std::time::Duration - для представления временных интервалов
  • std::time::Instant - для измерения времени выполнения (Бенчмаркинг)
  • std::time::SystemTime - для работы с реальным календарным временем, датами
  • chrono::Duration - для работы с календарным временем (даты, месяцы, годы)
  • crate chrono - библиотека для работы с датами, временем и временными зонами
  • crate time - проверка временных зон в runtime

std::time::Duration

для представления временных интервалов

std/Duration

Тип продолжительности, представляющий промежуток времени в секундах или меньше, обычно используемый для системных тайм-аутов. Состоит из целого числа секунд и дробной части, представленной в наносекундах ( 1 миллиард = 1 секунда)


use std::time::Duration;
fn main(){
    // Создание из различных единиц времени
    let sec = Duration::from_secs(5);        // 5 секунд
    let millis = Duration::from_millis(500); // 500 миллисекунд
    let micros = Duration::from_micros(1000);// 1000 микросекунд
    let nanos = Duration::from_nanos(1_000_000); // 1 миллисекунда

    // Использование констант
    let zero = Duration::ZERO;      // Нулевая длительность
    let max = Duration::MAX;        // Максимально возможная длительность

    // Извлечение компонентов
    let duration = Duration::from_millis(1234567);

    println!("Секунды: {}", duration.as_secs());        // 1234
    println!("Миллисекунды: {}", duration.as_millis()); // 1234567
    println!("Микросекунды: {}", duration.as_micros()); // 1234567000
    println!("Наносекунды: {}", duration.as_nanos());   // 1234567000000

    // Дробная часть секунд
    println!("Дробные секунды: {:?}", duration.subsec_nanos()); // 567000000
}

Полезные методы:


fn main(){
    let mut duration = Duration::from_secs(10);

    // Проверка на нулевую длительность
    println!("Is zero: {}", duration.is_zero()); // false

    // Получение минимального/максимального значения
    println!("Min: {:?}", duration.min(Duration::from_secs(5))); // 5 сек
    println!("Max: {:?}", duration.max(Duration::from_secs(5))); // 10 сек

    // Saturating операции (без паники при переполнении)
    let saturated = duration.saturating_add(Duration::MAX);
    println!("Saturated add: {:?}", saturated);
}

Арифметические операции:


fn main(){
    let d1 = Duration::from_secs(10);
    let d2 = Duration::from_secs(5);

    // Сложение
    let sum = d1 + d2; // 15 секунд

    // Вычитание
    let diff = d1 - d2; // 5 секунд

    // Умножение на скаляр
    let doubled = d1 * 2; // 20 секунд

    // Деление на скаляр
    let half = d1 / 2; // 5 секунд

    // Сравнение Duration
    let short = Duration::from_secs(1);
    let long = Duration::from_secs(10);

    println!("short < long: {}", short < long);   // true
    println!("short == long: {}", short == long); // false
    println!("short > long: {}", short > long);   // false
}

Практические примеры

Измерение времени выполнения


use std::time::{Duration, Instant};

fn expensive_operation() {
    // Имитация тяжелой операции
    std::thread::sleep(Duration::from_millis(100));
}

fn main() {
    let start = Instant::now();
    expensive_operation();
    let duration = start.elapsed();
    
    println!("Операция заняла: {:?}", duration);
    println!("В миллисекундах: {} ms", duration.as_millis());
}

Таймауты и задержки


use std::thread;
use std::time::Duration;
fn main(){
    // Задержка выполнения
    println!("Начало");
    thread::sleep(Duration::from_secs(2));
    println!("Прошло 2 секунды");

    // Таймаут для операций
    let result = some_operation.timeout(Duration::from_secs(5));
}

Работа с системным временем


use std::time::{Duration, SystemTime};
fn main(){
    let now = SystemTime::now();
    let future = now + Duration::from_secs(3600); // Через час

    match future.duration_since(SystemTime::UNIX_EPOCH) {
        Ok(duration) => println!("UNIX timestamp: {}", duration.as_secs()),
        Err(e) => println!("Ошибка: {:?}", e),
    }
}

Агрегация времени


fn calculate_total_time(operations: Vec) -> Duration {
    operations.iter().sum()
}
fn main(){
    let times = vec![
        Duration::from_secs(10),
        Duration::from_millis(500),
        Duration::from_secs(30),
    ];
    let total = calculate_total_time(times);
    println!("Общее время: {:?}", total); // 40.5 секунд
}

std::time::Instant

для измерения времени выполнения (Бенчмаркинг)

std/Instant

Чтобы измерить время какой-либо операции, поскольку он обеспечивает измерение монотонных часов:

  • Времени выполнения кода
  • Интервалов между событиями
  • Таймаутов
  • Бенчмаркинга

Ключевые особенности

Только для измерения интервалов

Не привязан к календарному времени

Монотонность


use std::time::Instant;
fn main(){
    let start = Instant::now();
    // Операция, время которой мы измеряем
    let end = Instant::now();

    let duration = end - start;
    println!("Время выполнения: {:?}", duration);
}

use std::time::{Duration, Instant}; 
fn main() {
   let now = Instant::now();

// спим в течение 2 секунд
   std::thread::sleep(std::time::Duration::new(2, 0));
   println!("{}", now.elapsed().as_secs()); // 2
}


use std::time::{Duration, Instant};
use std::thread::sleep;
fn main(){
    let now = Instant::now();// стартуем метку

// спим
    sleep(Duration::new(3, 0));// или sleep(Duration::from_secs(3));
    let new_now = Instant::now();// новая метка

// фиксируем продолжительность между отрезками
    println!("{:?}", new_now.duration_since(now).as_secs());// 3
    println!("{:?}",now.elapsed().as_secs());// 3 паникует если текущее время меньше чем текущее время
}

Практические примеры

Измерение времени выполнения

fn expensive_calculation() {
    // Имитация тяжелых вычислений
    let mut sum = 0;
    for i in 0..1_000_000 {
        sum += i;
    }
}

fn main() {
    let start = Instant::now();
    expensive_calculation();
    let duration = start.elapsed();
    
    println!("Вычисления заняли: {:.2} мс", duration.as_secs_f64() * 1000.0);
}

FPS (кадров в секунду) счетчик

use std::thread;
use std::time::{Instant, Duration};

let mut last_frame = Instant::now();
let mut frame_count = 0;

loop {
    // Отрисовка кадра
    render_frame();
    
    frame_count += 1;
    let now = Instant::now();
    let elapsed = now - last_frame;
    
    if elapsed >= Duration::from_secs(1) {
        println!("FPS: {}", frame_count);
        frame_count = 0;
        last_frame = now;
    }
}

Таймаут операций

fn operation_with_timeout(timeout: Duration) -> Result<String, &'static str> {
    let start = Instant::now();
    
    while Instant::now() - start < timeout {
        if let Some(result) = try_get_result() {
            return Ok(result);
        }
        thread::sleep(Duration::from_millis(10));
    }
    
    Err("Таймаут операции")
}

Профилирование кода

fn profile_function() {
    let timings = vec![
        ("parse_input", Instant::now()),
        ("process_data", Instant::now()),
        ("generate_output", Instant::now()),
    ];
    
    // Замеряем каждый этап
    parse_input();
    let parse_time = timings[0].1.elapsed();
    
    process_data();
    let process_time = timings[1].1.elapsed();
    
    generate_output();
    let output_time = timings[2].1.elapsed();
    
    println!("Профилирование:");
    println!("  Parse: {:?}", parse_time);
    println!("  Process: {:?}", process_time);
    println!("  Output: {:?}", output_time);
}

Дебаунсинг (антидребезг) - это техника обработки входных сигналов, которая устраняет ложные срабатывания, вызванные механическими вибрациями или электрическими помехами.

struct Debouncer {
    last_event: Option<Instant>,
    cooldown: Duration,
}
impl Debouncer {
    fn new(cooldown: Duration) -> Self {
        Self { last_event: None, cooldown }
    }
    fn should_trigger(&mut self) -> bool {
        let now = Instant::now();
        match self.last_event {
            Some(last) if now - last < self.cooldown => false,
            _ => {
                self.last_event = Some(now);
                true
            }
        }
    }
}

std::time::SystemTime

работа с реальным календарным временем, датами

представление календарного времени, привязанное к системным часам.

std/SystemTime

Измерение системных часов, полезных для общения с внешними объектами, такими как файловая система или другие процессы. Внутреннее хронометрирование не заботится о часовых поясах

Измерение системных часов, полезных для общения с внешними объектами, такими как файловая система или другие процессы.

Отличается от Instant типа, это измерение времени не монотонно. Это означает, что вы можете сохранить файл в файловой системе, а затем сохранить другой файл в файловой системе, а второй файл имеет значение SystemTime раньше, чем первое. Другими словами, операция, которая происходит после другой операции в режиме реального времени, может иметь более раннюю версию SystemTime!

Следовательно, сравнение двух экземпляров SystemTime, чтобы узнать о продолжительности между ними, возвращает результат, а не безошибочную Длительность, чтобы указать, что такой вид дрейфа времени может произойти и должен быть обработан.

Несмотря на то, что SystemTime не может быть непосредственно проверен, константа UNIX_EPOCH предоставляется в этом модуле в качестве привязки во времени, чтобы узнать информацию о SystemTime. Вычисляя продолжительность с этой фиксированной точки во времени, SystemTime может быть преобразовано в человеко-читаемое время или, возможно, в другое строковое представление.

Размер структуры SystemTime может варьироваться в зависимости от целевой операционной системы.

Основные характеристики

Привязан к реальному времени


use std::time::SystemTime;
fn main(){
    let now = SystemTime::now();
    println!("Текущее системное время: {:?}", now);
}

Можно преобразовать в UNIX timestamp


fn main(){
    let now = SystemTime::now();
    match now.duration_since(SystemTime::UNIX_EPOCH) {
        Ok(duration) => println!("UNIX timestamp: {} секунд", duration.as_secs()),
        Err(e) => println!("Ошибка: {:?}", e),
    }
}

Поддерживает операции с датами


use std::time::{SystemTime, Duration};
fn main(){
    let now = SystemTime::now();
    let one_hour_later = now + Duration::from_secs(3600);
    let one_day_ago = now - Duration::from_secs(86400);
}

Обработка ошибок SystemTime может работать с датами до UNIX EPOCH (1 января 1970):


fn handle_pre_epoch_time() {
    let pre_epoch = SystemTime::UNIX_EPOCH - Duration::from_secs(3600);
    
    match pre_epoch.duration_since(SystemTime::UNIX_EPOCH) {
        Ok(_) => unreachable!(), // Не должно случиться
        Err(e) => {
            println!("Время до EPOCH: {:?}", e);
            println!("На {:?} до EPOCH", e.duration());
        }
    }
}
fn main(){
    handle_pre_epoch_time();
}

Практические примеры

Измерение времени с учетом реального времени

fn track_operation_time() {
    let start = SystemTime::now();
    
    // Выполняем операцию
    std::thread::sleep(Duration::from_secs(2));
    
    match start.elapsed() {
        Ok(elapsed) => {
            println!("Операция заняла: {:?}", elapsed);
            println!("Началась в: {:?}", start);
            println!("Закончилась в: {:?}", SystemTime::now());
        }
        Err(e) => println!("Ошибка измерения: {:?}", e),
    }
}

Проверка возраста файла

use std::fs;
use std::time::{SystemTime, Duration};

fn is_file_old(path: &str, max_age: Duration) -> bool {
    if let Ok(metadata) = fs::metadata(path) {
        if let Ok(modified) = metadata.modified() {
            if let Ok(age) = SystemTime::now().duration_since(modified) {
                return age > max_age;
            }
        }
    }
    false
}
fn main(){
    // Проверяем, старше ли файл 1 часа
    if is_file_old("data.txt", Duration::from_secs(3600)) {
        println!("Файл устарел");
    }
}

Кеширование с временем жизни

use std::collections::HashMap;

struct Cache<T> {
    data: HashMap<String, (T, SystemTime)>,
    ttl: Duration,
}
impl<T> Cache<T> {
    fn new(ttl: Duration) -> Self {
        Self {
            data: HashMap::new(),
            ttl,
        }
    }
    fn insert(&mut self, key: String, value: T) {
        self.data.insert(key, (value, SystemTime::now()));
    }
    fn get(&mut self, key: &str) -> Option<&T> {
        if let Some((value, timestamp)) = self.data.get(key) {
            if let Ok(age) = SystemTime::now().duration_since(*timestamp) {
                if age <= self.ttl {
                    return Some(value);
                } else {
                    self.data.remove(key); // Удаляем просроченное
                }
            }
        }
        None
    }
}

Синхронизация времени между системами

fn check_time_sync(server_time: u64) -> Result<(), String> {
    let local_time = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .unwrap()
        .as_secs();
    
    let diff = (local_time as i64 - server_time as i64).abs();
    
    if diff > 60 {
        Err(format!("Расхождение времени: {} секунд", diff))
    } else {
        Ok(())
    }
}

Логирование с временными метками

fn log_with_timestamp(message: &str) {
    let timestamp = SystemTime::now()
        .duration_since(SystemTime::UNIX_EPOCH)
        .unwrap()
        .as_secs();
    
    println!("[{}] {}", timestamp, message);
}

Работа с UNIX EPOCH

Создание из UNIX timestamp


use std::time::{SystemTime, Duration};
fn main(){
    // Из секунд
    let from_seconds = SystemTime::UNIX_EPOCH + Duration::from_secs(1640995200); // 1 Jan 2022

    // Из миллисекунд
    let from_millis = SystemTime::UNIX_EPOCH + Duration::from_millis(1640995200000);
}

Преобразование в разные форматы


use std::time::{SystemTime, Duration};
fn format_system_time(time: SystemTime) -> String {
    match time.duration_since(SystemTime::UNIX_EPOCH) {
        Ok(duration) => {
            let seconds = duration.as_secs();
            let minutes = seconds / 60;
            let hours = minutes / 60;
            let days = hours / 24;
            
            format!("{} дней, {} часов, {} минут", days, hours % 24, minutes % 60)
        }
        Err(_) => "Время до UNIX EPOCH".to_string(),
    }
}
fn main(){
    let from_seconds = SystemTime::UNIX_EPOCH + Duration::from_secs(1640995200); // 1 Jan 2022
    println!("{}",format_system_time(from_seconds));
}

Сравнение SystemTime

Сравнение двух моментов времени


use std::time::{SystemTime, Duration};
fn main(){
    let time1 = SystemTime::now();
    std::thread::sleep(Duration::from_secs(1));
    let time2 = SystemTime::now();

    match time1.cmp(&time2) {
        std::cmp::Ordering::Less => println!("time1 раньше time2"),
        std::cmp::Ordering::Equal => println!("Времена равны"),
        std::cmp::Ordering::Greater => println!("time1 позже time2"),
    }
}

Разница между временами


use std::time::{SystemTime, Duration};
fn main(){
    let earlier = SystemTime::now();
    std::thread::sleep(Duration::from_secs(3));
    let later = SystemTime::now();

    match later.duration_since(earlier) {
        Ok(diff) => println!("Разница: {:?}", diff),
        Err(e) => println!("Ошибка: {:?}", e), // Если earlier > later
    }
}

Практические примеры

Rate limiting


struct RateLimiter {
    last_request: SystemTime,
    min_interval: Duration,
}

impl RateLimiter {
    fn new(min_interval: Duration) -> Self {
        Self {
            last_request: SystemTime::UNIX_EPOCH, // Давно в прошлом
            min_interval,
        }
    }
    
    fn can_make_request(&mut self) -> bool {
        let now = SystemTime::now();
        if let Ok(elapsed) = now.duration_since(self.last_request) {
            if elapsed >= self.min_interval {
                self.last_request = now;
                return true;
            }
        }
        false
    }
}
fn main(){
 
}

Валидация временных меток


fn is_timestamp_valid(timestamp: u64, max_age: Duration) -> bool {
    let event_time = SystemTime::UNIX_EPOCH + Duration::from_secs(timestamp);
    let now = SystemTime::now();
    
    match now.duration_since(event_time) {
        Ok(age) => age <= max_age,
        Err(_) => false, // Время из будущего
    }
}
fn main(){
 ...
}

chrono::Duration

для работы с календарным временем (даты, месяцы, годы)

crate chrono

chrono/Duration

Ключевые особенности chrono::Duration

Отрицательные значения


use chrono::{Duration, TimeDelta};
fn main(){
    // chrono поддерживает отрицательные длительности
    let negative_duration = Duration::seconds(-5);
    let past_date = some_date + negative_duration; // Перемещение в прошлое
}

Богатый API для извлечения компонентов


use chrono::{Duration, TimeDelta};
fn main(){
    let duration = Duration::hours(25) + Duration::minutes(30);

    println!("Полное время: {}", duration);
    println!("Часы: {}", duration.num_hours());        // 25
    println!("Минуты: {}", duration.num_minutes());    // 1530
    println!("Секунды: {}", duration.num_seconds());   // 91800

}

Практические примеры

Работа с датами и календарем


use chrono::{Duration, Local, TimeDelta};
fn main(){
    let now = Local::now();
    println!("Сейчас: {}", now);

    // Календарные операции
    let tomorrow = now + Duration::days(1);
    let next_week = now + Duration::weeks(1);
    let next_month = now + Duration::days(30);

    println!("Завтра: {}", tomorrow);
    println!("Через неделю: {}", next_week);
}

Разница между датами с учетом календаря


use chrono::{Duration, NaiveDate, TimeDelta};
fn main(){
    let start = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
    let end = NaiveDate::from_ymd_opt(2024, 2, 1).unwrap();

    let difference: Duration = end - start;
    println!("Разница между датами: {} дней", difference.num_days());
}

Сложные временные интервалы


use chrono::{Duration, TimeDelta};
fn main(){
    // Создание сложных интервалов
    let complex_duration = Duration::days(5) + 
                          Duration::hours(12) + 
                          Duration::minutes(30) +
                          Duration::seconds(45);

    println!("Сложный интервал: {}", complex_duration);
}

Обработка временных зон


use chrono::{Duration, Utc, FixedOffset, TimeDelta};
fn main(){
    let utc_time = Utc::now();
    let moscow_offset = FixedOffset::east_opt(3 * 3600).unwrap();
    let moscow_time = utc_time.with_timezone(&moscow_offset);

    // Добавление времени с учетом смещения
    let later_in_moscow = moscow_time + Duration::hours(2);
}

Парсинг и форматирование длительностей

use chrono::{Duration, TimeDelta};

// Из строки в Duration (примерный парсинг)
fn parse_duration(s: &str) -> Option<Duration> {
    let parts: Vec<&str> = s.split_whitespace().collect();
    if parts.len() != 2 {
        return None;
    }
    
    let value: i64 = parts[0].parse().ok()?;
    match parts[1] {
        "days" => Some(Duration::days(value)),
        "hours" => Some(Duration::hours(value)),
        "minutes" => Some(Duration::minutes(value)),
        "seconds" => Some(Duration::seconds(value)),
        _ => None,
    }
}

if let Some(duration) = parse_duration("2 days") {
    println!("Parsed duration: {:?}", duration);
}

Преобразование между chrono::Duration и std::time::Duration

Из std в chrono


use std::time::Duration as StdDuration;
use chrono::{Duration as ChronoDuration, TimeDelta};
fn main(){
    let std_duration = StdDuration::from_secs(3600);
    let chrono_duration = ChronoDuration::from_std(std_duration).unwrap();

    println!("1 час в chrono: {:?}", chrono_duration);
}

Из chrono в std


use chrono::{Duration as ChronoDuration, TimeDelta};
use std::time::Duration as StdDuration;
fn main(){
    let chrono_duration = ChronoDuration::hours(1);
    let std_duration = chrono_duration.to_std().unwrap();

    println!("1 час в std: {:?}", std_duration);
}

Обработка ошибок преобразования


use chrono::{Duration as ChronoDuration, TimeDelta};
fn main(){
    // Отрицательные длительности нельзя преобразовать в std
    let negative_chrono = ChronoDuration::seconds(-5);

    match negative_chrono.to_std() {
        Ok(std_dur) => println!("Успех: {:?}", std_dur),
        Err(e) => println!("Ошибка: {}", e), // Будет ошибка!
    }
}

crate chrono

Chrono - это наиболее популярная и полная библиотека для работы с датами, временем и временными зонами в Rust.

crate chrono

Основные возможности Chrono

Богатый набор типов данных


use chrono::{DateTime, Local, Utc, FixedOffset};
use chrono::naive::{NaiveDate, NaiveTime, NaiveDateTime};
use chrono::format::{ParseResult, Parsed};
fn main(){
    // Различные представления времени
    let local: DateTime = Local::now();
    let utc: DateTime = Utc::now();
    let with_offset: DateTime = FixedOffset::east_opt(3600).unwrap().from_utc_datetime(&utc.naive_utc());
// NaiveDateTime быстрее чем DateTime
}

Используйте правильные типы:

  • chrono::naive::{NaiveDate, NaiveTime, NaiveDateTime} - когда временная зона не важна
  • chrono::DateTime<chrono::Utc> - для хранения времени в UTC
  • chrono::DateTime<chrono::Local> - для отображения пользователю

Наивные даты и время (без временных зон)


use chrono::naive::{NaiveDate, NaiveTime, NaiveDateTime};
fn main(){
    // Только дата
    let date = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
    println!("Дата: {}", date);

    // Только время
    let time = NaiveTime::from_hms_opt(14, 30, 0).unwrap();
    println!("Время: {}", time);

    // Дата и время вместе
    let datetime = NaiveDateTime::new(date, time);
    println!("Дата и время: {}", datetime);
}

Работа с временными зонами


use chrono::{Utc, Local, FixedOffset, TimeZone};
fn main(){
    // UTC время
    let utc_now = Utc::now();
    println!("UTC: {}", utc_now);

    // Локальное время системы
    let local_now = Local::now();
    println!("Локальное: {}", local_now);

    // Конкретная временная зона (UTC+3)
    let moscow_offset = FixedOffset::east_opt(3 * 3600).unwrap();
    let moscow_time = moscow_offset.from_utc_datetime(&utc_now.naive_utc());
    println!("Москва: {}", moscow_time);

    // Преобразование между зонами
    let local_in_utc = local_now.with_timezone(&Utc);
    println!("Локальное в UTC: {}", local_in_utc);
}

Форматирование и парсинг

Форматирование дат


use chrono::{Local, Datelike, Timelike};
fn main(){
    let now = Local::now();

    // Стандартное форматирование
    println!("RFC2822: {}", now.to_rfc2822());
    println!("RFC3339: {}", now.to_rfc3339());
    println!("ISO8601: {}", now.to_rfc3339());

    // Кастомное форматирование
    println!("Custom: {}", now.format("%Y-%m-%d %H:%M:%S"));
    println!("Russian: {}", now.format("%d.%m.%Y %H:%M"));

    // Доступ к компонентам
    println!("Год: {}, Месяц: {}, День: {}", 
        now.year(), now.month(), now.day());
    println!("Час: {}, Минута: {}, Секунда: {}",
        now.hour(), now.minute(), now.second());
}

Парсинг из строк


use chrono::{DateTime, Local, NaiveDate};
fn main(){
    // Парсинг RFC3339
    let rfc_str = "2024-01-15T14:30:00+03:00";
    let dt: DateTime = DateTime::parse_from_rfc3339(rfc_str).unwrap();
    println!("Parsed: {}", dt);

    // Парсинг кастомных форматов
    let custom_str = "15.01.2024 14:30";
    let naive_dt = NaiveDateTime::parse_from_str(custom_str, "%d.%m.%Y %H:%M").unwrap();
    println!("Parsed naive: {}", naive_dt);

    // Парсинг даты
    let date_str = "2024-01-15";
    let date = NaiveDate::parse_from_str(date_str, "%Y-%m-%d").unwrap();
    println!("Parsed date: {}", date);
}

Арифметические операции

Операции с датами


use chrono::{Local, Duration, Months, TimeDelta};
fn main(){
    let now = Local::now();

    // Добавление Duration
    let tomorrow = now + Duration::days(1);
    let next_hour = now + Duration::hours(1);

    // Добавление месяцев (с учетом разной длины месяцев)
    let next_month = now + Months::new(1);
    let three_months_later = now + Months::new(3);

    // Вычитание
    let yesterday = now - Duration::days(1);
    let last_month = now - Months::new(1);

    // Разница между датами
    let diff = tomorrow - now;
    println!("До завтра: {:?}", diff);
}

Сравнение дат


use chrono::Local;
fn main(){
    let now = Local::now();
    let future = now + Duration::days(1);

    println!("now < future: {}", now < future);
    println!("now == future: {}", now == future);
    println!("now > future: {}", now > future);

    // Проверка на равенство с допуском
    let almost_now = now + Duration::milliseconds(500);
    let is_almost_equal = (now - almost_now).num_seconds().abs() < 1;
    println!("Почти одинаково: {}", is_almost_equal);
}

Сериализация и десериализация

Chrono отлично интегрируется с Serde


use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct Event {
    name: String,
    #[serde(with = "chrono::serde::ts_seconds")]
    timestamp: DateTime,
}
fn main(){
    // JSON сериализация
    let event = Event {
        name: "Meeting".to_string(),
        timestamp: Utc::now(),
    };

    let json = serde_json::to_string(&event).unwrap();
    println!("JSON: {}", json);

    // Десериализация
    let decoded: Event = serde_json::from_str(&json).unwrap();
    println!("Decoded: {}", decoded.timestamp);
}

Планировщик задач

use chrono::{DateTime, Local, Duration, TimeDelta};
use std::collections::BinaryHeap;

struct ScheduledTask {
    execute_at: DateTime<Local>,
    task: Box<dyn FnOnce()>,
}
impl PartialOrd for ScheduledTask {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(other.execute_at.cmp(&self.execute_at)) // Для min-heap
    }
}
impl PartialEq for ScheduledTask {
    fn eq(&self, other: &Self) -> bool {
        self.execute_at == other.execute_at
    }
}
struct Scheduler {
    tasks: BinaryHeap<ScheduledTask>,
}
impl Scheduler {
    fn new() -> Self {
        Self { tasks: BinaryHeap::new() }
    }
    fn schedule<F>(&mut self, delay: Duration, task: F) where F: FnOnce() + 'static, {
        let execute_at = Local::now() + delay;
        self.tasks.push(ScheduledTask {
            execute_at,
            task: Box::new(task),
        });
    }
    fn run_pending(&mut self) {
        let now = Local::now();
        while let Some(task) = self.tasks.peek() {
            if task.execute_at <= now {
                let task = self.tasks.pop().unwrap();
                (task.task)();
            } else {
                break;
            }
        }
    }
}

Логгер с временными метками


use chrono::{Local, DateTime};

struct Logger;

impl Logger {
    fn log(&self, level: &str, message: &str) {
        let timestamp: DateTime = Local::now();
        println!("[{}] {}: {}", timestamp.format("%Y-%m-%d %H:%M:%S"), level, message);
    }
    
    fn error(&self, message: &str) {
        self.log("ERROR", message);
    }
    
    fn info(&self, message: &str) {
        self.log("INFO", message);
    }
}
fn main(){
 ...
}

Работа с временными интервалами

use chrono::{DateTime, Local, Duration, TimeDelta};

struct TimeInterval {
    start: DateTime<Local>,
    end: DateTime<Local>,
}

impl TimeInterval {
    fn new(start: DateTime<Local>, end: DateTime<Local>) -> Self {
        Self { start, end }
    }
    
    fn duration(&self) -> Duration {
        self.end - self.start
    }
    
    fn contains(&self, point: DateTime<Local>) -> bool {
        point >= self.start && point <= self.end
    }
    
    fn overlap(&self, other: &TimeInterval) -> bool {
        self.start <= other.end && self.end >= other.start
    }
}

crate time

проверка временных зон в runtime

docs.rs/time

crate time

Основное отличие от chrono в том, что chrono параметризует часовой пояс в конкретных типах DateTime<Utc>, DateTime<Local>, DateTime<FixedOffset>, а у crate time обработка часового пояса во время выполнения (Runtime). Т.е. за счет обрабатывания смещения в runtime пресутсвуют накладные расходы:

use time::{OffsetDateTime, UtcOffset};
fn main(){
    // Один тип для всех временных зон
    let utc = OffsetDateTime::now_utc();
    let local = OffsetDateTime::now_local().unwrap();

    // Преобразование - просто изменение смещения
    let utc_to_local = utc.to_offset(UtcOffset::current());
}

chrono

// Компилятор не даст смешать разные зоны
fn process_utc_time(dt: DateTime<Utc>) {
    // Гарантированно UTC
}

fn process_local_time(dt: DateTime<Local>) {
    // Гарантированно локальное время
}
fn main(){
    process_utc_time(local_time); // ❌ Ошибка компиляции
}

time

// Один тип для всех случаев
fn process_time(dt: OffsetDateTime) {
    // Нужно проверять смещение в runtime
    if dt.offset() == UtcOffset::UTC {
        println!("Это UTC время");
    }
}

Если вам нужна надежность и конкретность, то Chrono будет лучшим выбором.