Работа с датами в Rust: обзор ключевых библиотек
Экосистема Rust предлагает несколько мощных библиотек для работы с датами и временем. В отличие от Python с его встроенным модулем datetime, в Rust стандартная библиотека предоставляет лишь минимальную функциональность (std::time::Instant и Duration), поэтому для серьёзных задач приходится обращаться к внешним крейтам. В этой статье мы рассмотрим три основные библиотеки: Chrono, Time и Jiff.
1. Chrono — де-факто стандарт
Chrono — самая популярная библиотека (более 100 млн загрузок). Она предоставляет полный набор инструментов для работы с датами, временем, часовыми поясами и форматированием.
Основные возможности:
NaiveDate,NaiveDateTime— даты и время без часового поясаDateTime<Tz>— дата-время с привязкой к часовому поясу- Поддержка
Durationи арифметических операций - Форматирование через
format!и парсинг строк - Работа с календарями (Григорианский, ISO)
Пример кода:
use chrono::{DateTime, Utc, NaiveDate, Duration};
fn main() {
// Текущее время в UTC
let now: DateTime<Utc> = Utc::now();
println!("Текущее время: {}", now.format("%Y-%m-%d %H:%M:%S"));
// Создание конкретной даты
let date = NaiveDate::from_ymd_opt(2025, 3, 15).unwrap();
println!("Дата: {}", date);
// Арифметика с датами
let future = now + Duration::days(30);
println!("Через 30 дней: {}", future.format("%d.%m.%Y"));
// Парсинг строки
let parsed = "2025-01-01 12:00:00"
.parse::<DateTime<Utc>>()
.expect("Неверный формат даты");
println!("Распарсено: {}", parsed);
}
Chrono отлично подходит для большинства проектов, но может быть избыточной, если нужна только базовая функциональность.
2. Time — современная альтернатива
Крейт Time (разработчик Jacob Pratt) позиционируется как более безопасная и эргономичная замена Chrono. Он использует строгую типизацию и избегает паник в рантайме.
Ключевые отличия:
- Все операции возвращают
Result— нет скрытых паник - Более строгая система типов: отдельные типы для дат, времени, смещений
- Встроенная поддержка ISO 8601 и RFC 3339
- Меньший размер и более быстрая компиляция
Пример кода:
use time::{Date, Month, OffsetDateTime, Duration, format_description};
fn main() -> Result<(), time::Error> {
// Текущее время
let now = OffsetDateTime::now_utc();
println!("Сейчас: {}", now);
// Создание даты (без паники)
let date = Date::from_calendar_date(2025, Month::March, 15)?;
println!("Дата: {}", date);
// Арифметика
let week_later = now + Duration::weeks(1);
println!("Через неделю: {}", week_later);
// Парсинг с явным форматом
let format = format_description::parse("[year]-[month]-[day]")?;
let parsed = Date::parse("2025-12-31", &format)?;
println!("Парсинг: {}", parsed);
Ok(())
}
Time — отличный выбор для новых проектов, где важна безопасность и предсказуемость.
3. Jiff — новейший игрок
Jiff (от BurntSushi, создателя regex и ripgrep) — самая свежая библиотека (релиз 2024 года). Она фокусируется на работе с часовыми поясами и интернационализацией.
Особенности:
- Встроенная база данных часовых поясов (IANA)
- Поддержка нестандартных календарей (Исламский, Еврейский и др.)
- Продвинутая работа с интервалами и периодами
- Высокая производительность за счёт ленивых вычислений
Пример кода:
use jiff::Zoned;
fn main() -> Result<(), jiff::Error> {
// Текущее время в конкретном часовом поясе
let moscow = Zoned::now()
.with_time_zone("Europe/Moscow")?;