Работа с датами и временем в Rust: от А до Я
Работа с датами и временем — одна из ключевых задач в разработке любого приложения: от веб-сервисов до систем логирования. В Rust, известном своей безопасностью и производительностью, работа с датами реализована через мощную библиотеку chrono. В этой статье мы разберём все аспекты работы с датами и временем: от базовых операций до сложных манипуляций с временными зонами.
1. Установка и настройка библиотеки chrono
Библиотека chrono является де-факто стандартом для работы с датами и временем в Rust. Она предоставляет полный набор инструментов: от простых объектов даты до сложных типов с учётом временных зон.
Чтобы начать работу, добавьте зависимость в файл Cargo.toml:
[dependencies]
chrono = "0.4"
После этого импортируйте необходимые модули в ваш код:
use chrono::{NaiveDate, NaiveDateTime, DateTime, Utc, Local, Duration};
use chrono::format::ParseError;
2. Основные типы данных для работы с датами
В chrono существует несколько ключевых типов, которые покрывают все потребности разработчика:
NaiveDate— дата без времени и временной зоны (например, 2024-01-15).NaiveTime— время без даты и временной зоны (например, 14:30:00).NaiveDateTime— комбинация даты и времени без временной зоны.DateTime<Tz>— дата и время с указанием временной зоны (например,DateTime<Utc>илиDateTime<Local>).
Рассмотрим пример создания объектов каждого типа:
// Создание NaiveDate
let date = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap();
println!("Дата: {}", date); // 2024-01-15
// Создание NaiveTime
let time = NaiveTime::from_hms_opt(14, 30, 0).unwrap();
println!("Время: {}", time); // 14:30:00
// Создание NaiveDateTime
let datetime = NaiveDateTime::new(date, time);
println!("Дата и время: {}", datetime); // 2024-01-15 14:30:00
// Создание DateTime с временной зоной UTC
let utc_datetime = Utc::now();
println!("Текущее время UTC: {}", utc_datetime);
// Создание DateTime с локальной временной зоной
let local_datetime = Local::now();
println!("Текущее локальное время: {}", local_datetime);
3. Форматирование и парсинг дат
Одна из самых частых задач — преобразование дат в строки и обратно. chrono использует форматные строки, похожие на strftime из C.
Форматирование даты в строку
Для форматирования используйте метод .format():
use chrono::Utc;
let now = Utc::now();
// Стандартный формат ISO 8601
println!("ISO 8601: {}", now.format("%Y-%m-%dT%H:%M:%S%z"));
// Русскоязычный формат
println!("Русский формат: {}", now.format("%d.%m.%Y %H:%M"));
// Только дата
println!("Только дата: {}", now.format("%A, %d %B %Y"));
// Вывод:
// ISO 8601: 2024-01-15T14:30:00+0000
// Русский формат: 15.01.2024 14:30
// Только дата: Monday, 15 January 2024
Основные спецификаторы формата:
%Y— год (4 цифры)%m— месяц (01-12)%d— день (01-31)%H— часы (00-23)%M— минуты (00-59)%S— секунды (00-59)%z— смещение временной зоны%A— полное название дня недели%B— полное название месяца
Парсинг строки в дату
Для преобразования строки в дату используйте метод parse_from_str():
use chrono::NaiveDate;
use chrono::format::ParseError;
fn parse_date(date_str: &str) -> Result<NaiveDate, ParseError> {
NaiveDate::parse_from_str(date_str, "%d.%m.%Y")
}
fn main() {
match parse_date("15.01.2024") {
Ok(date) => println!("Распарсена дата: {}", date),
Err(e) => println!("Ошибка парсинга: {}", e),
}
// Парсинг ISO 8601
let iso_date = NaiveDate::parse_from_str("2024-01-15", "%Y-%m-%d").unwrap();
println!("ISO дата: {}", iso_date);
}
4. Арифметические операции с датами и временем
Библиотека chrono поддерживает все основные арифметические операции: сложение, вычитание, вычисление разницы.
Сложение и вычитание временных интервалов
use chrono::{Utc, Duration};
let now = Utc::now();
println!("Сейчас: {}", now);
// Добавляем 5 дней
let in_five_days = now + Duration::days(5);
println!("Через 5 дней: {}", in_five_days);
// Вычитаем 2 часа
let two_hours_ago = now - Duration::hours(2);
println!("2 часа назад: {}", two_hours_ago);
// Добавляем 30 минут
let in_half_hour = now + Duration::minutes(30);
println!("Через 30 минут: {}", in_half_hour);
// Работа с неделями
let next_week = now + Duration::weeks(1);
println!("Через неделю: {}", next_week);
Вычисление разницы между датами
use chrono::{NaiveDate, Duration};
let start = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap();
let end = NaiveDate::from_ymd_opt(2024, 12, 31).unwrap();
// Разница в днях
let diff = end - start;
println