Trabajo con fechas y horas en Rust: técnicas avanzadas y bibliotecas

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Trabajo avanzado con fechas y horas en Rust: de NaiveDateTime a Timezone



Trabajar con fechas y horas es una de las tareas más comunes en el desarrollo backend, registro de eventos, sistemas financieros y procesamiento de datos. En Rust, la biblioteca estándar proporciona el módulo básico std::time, pero para proyectos serios no es suficiente. A nivel avanzado, recurrimos a la crate chrono, el estándar de facto para trabajar con fechas y horas. En este artículo, analizaremos escenarios complejos: trabajo con zonas horarias, análisis sintáctico de formatos no estándar, manipulaciones con duraciones y optimización del rendimiento.



1. Instalación y estructura básica de chrono



Añada la dependencia en Cargo.toml:



[dependencies]chrono = { version = "0.4", features = ["serde"] }


Tipos principales de chrono para trabajo avanzado:

  • NaiveDateTime — fecha-hora sin zona horaria (local).
  • DateTime<Tz> — fecha-hora vinculada a una zona horaria (por ejemplo, Utc, Local, FixedOffset).
  • Duration — intervalo de tiempo (diferente de std::time::Duration, admite valores negativos).
  • TimeDelta — sinónimo de Duration en versiones nuevas.


Ejemplo de creación del momento actual en UTC y hora local:



use chrono::{Utc, Local, DateTime};

fn main() { let utc_now: DateTime<Utc> = Utc::now(); let local_now: DateTime<Local> = Local::now(); println!("UTC: {}", utc_now); println!("Local: {}", local_now);}


2. Trabajo con zonas horarias (Timezone)



Una de las capacidades potentes de chrono es el soporte de la base de datos de zonas horarias Olson a través de la crate chrono-tz. Esto permite trabajar con nombres de zonas como "Europe/Moscow" o "America/New_York".



Instale:



[dependencies]chrono = "0.4"chrono-tz = "0.8"


Ejemplo de conversión de hora entre zonas:



use chrono::{Utc, DateTime, TimeZone};use chrono_tz::Europe::Moscow;

fn main() { let utc_time: DateTime<Utc> = Utc::now(); let moscow_time = utc_time.with_timezone(&Moscow); println!("UTC: {}", utc_time); println!("Moscow: {}", moscow_time);}


Punto importante: siempre almacene la hora en UTC en la base de datos, y conviértala a hora local solo al mostrarla al usuario. Esto evita confusiones con el horario de verano/invierno.



2.1. Trabajo con FixedOffset



Si conoce un desplazamiento fijo (por ejemplo, +03:00), use FixedOffset:



use chrono::{FixedOffset, DateTime, Utc};

fn main() { let offset = FixedOffset::east_opt(3 * 3600).unwrap(); // +03:00 let now_utc: DateTime<Utc> = Utc::now(); let now_offset = now_utc.with_timezone(&offset); println!("Con desplazamiento +03:00: {}", now_offset);}


3. Análisis sintáctico y formateo de fechas (técnicas avanzadas)



El análisis sintáctico estándar mediante parse_from_str requiere un formato exacto. Pero en proyectos reales, los formatos pueden variar (por ejemplo, registros de diferentes sistemas). Consideremos varios enfoques.



3.1. Múltiples formatos con try_parse



Use una iteración sobre formatos:



use chrono::NaiveDateTime;

fn parse_flexible(date_str: &str) -> Option<NaiveDateTime> { let formats = [ "%Y-%m-%d %H:%M:%S", "%d/%m/%Y %H:%M", "%Y%m%dT%H%M%S", "%b %d %Y %I:%M:%S%p", ];

for fmt in &formats { if let Ok(dt) = NaiveDateTime::parse_from_str(date_str, fmt) { return Some(dt); } } None}

fn main() { let dates = vec![ "2024-03-15 14:30:00", "15/03/2024 14:30", "2

Blogs

Book Recommendations