|
|
|
для представления временных интервалов
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/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/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 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));
}
|
|
|
Сравнение двух моментов времени
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(){
...
}
|
|
для работы с календарным временем (даты, месяцы, годы)
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), // Будет ошибка!
}
}
|
|
|
|
|
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
}
}
|
|
проверка временных зон в 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 будет лучшим выбором.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|