20  Gestión del tiempo

En programación, trabajar con el tiempo puede implicar necesidades diferentes. En ocasiones solo necesitamos ordenar sucesos según el orden en que se producen; en otras, medir cuánto tiempo transcurre entre dos acontecimientos o conocer la fecha y hora en que ocurre un evento.

Estas necesidades dan lugar a tres conceptos que conviene distinguir:

Rust proporciona tipos y funciones para trabajar con estas dos últimas necesidades en el módulo std::time. La primera puede resolverse mediante mecanismos sencillos, como un contador, dependiendo de las necesidades del programa.

20.1 Hora lógica

En ocasiones, un programa necesita establecer el orden en que se producen ciertos sucesos, pero no necesita conocer la hora real ni medir el tiempo transcurrido entre ellos. En estos casos podemos utilizar una hora lógica, representada mediante un contador que se incrementa cada vez que se registra un nuevo suceso. Por ejemplo, podemos asignar un número consecutivo a cada elemento que se introduce en una cola:

let mut reloj: u64 = 0;

reloj += 1;
let suceso1 = reloj;

reloj += 1;
let suceso2 = reloj;

En este ejemplo, suceso1 vale 1 y suceso2 vale 2. Estos valores permiten establecer que el primer suceso se registró antes que el segundo, pero no indican cuánto tiempo ha transcurrido entre ambos.

Las horas lógicas pueden utilizarse, por ejemplo, para ordenar los mensajes recibidos, numerar las operaciones de un proceso o registrar el orden de inserción de elementos en una cola.

La principal ventaja de este mecanismo es su sencillez: no depende del reloj del sistema y no requiere medir el tiempo físico. Sin embargo, el contador solo permite ordenar los sucesos que registra; no proporciona información sobre su duración ni sobre la fecha en que ocurrieron.

20.2 Medición de intervalos temporales

Cuando necesitamos medir cuánto tiempo transcurre entre dos instantes, Rust proporciona el tipo Instant, definido en el módulo std::time. Podemos utilizarlo, por ejemplo, para medir cuánto tarda un algoritmo en ejecutarse, controlar tiempos de espera o calcular cuánto tiempo lleva un elemento en una cola.

El siguiente ejemplo mide el tiempo que tarda en ejecutarse un bucle de un millón de iteraciones. Para ello, obtenemos un instante inicial antes del bucle y calculamos el tiempo transcurrido al finalizar.

use std::time::Instant;

fn main() {
    let inicio = Instant::now();

    let mut suma: u64 = 0;
    for i in 0..1_000_000 {
        suma += i;
    }

    let intervalo = inicio.elapsed();

    // Error: Instant no implementa Display, por lo que no admite el formato {}
    // println!("Instante inicial: {}", inicio);

    println!("Instante inicial: {:?}", inicio);

    println!("Tiempo transcurrido:");
    println!("Nanosegundos: {}", intervalo.as_nanos());
    println!("Microsegundos: {}", intervalo.as_micros());
    println!("Milisegundos: {}", intervalo.as_millis());
    println!("Segundos: {}", intervalo.as_secs_f64());
    println!("Suma: {}", suma);
}

La función Instant::now() obtiene el instante inicial. Su representación interna depende del sistema y, cuando se muestra con {:?}, produce un valor que no se corresponde con la fecha y hora del reloj de pared, que es la que normalmente usamos las personas.

El método elapsed() devuelve el tiempo transcurrido desde ese instante, representado mediante un valor de tipo Duration. Podemos obtener esta duración en nanosegundos, microsegundos, milisegundos o segundos mediante los métodos as_nanos(), as_micros(), as_millis() y as_secs_f64(), respectivamente.

  • El método as_secs() devuelve los segundos como un entero de tipo u64, descartando la fracción de segundo. Si necesitamos conservarla, podemos utilizar as_secs_f64(), que devuelve un número en coma flotante de tipo f64. También existe as_secs_f32(), que devuelve un f32, de menor precisión.

  • No existen métodos específicos para obtener la duración en minutos, horas o días, pero podemos calcularla fácilmente a partir de los segundos, dividiendo por 60, 3600 o 86400, respectivamente.

También podemos obtener directamente la diferencia entre dos valores de tipo Instant mediante una resta. El resultado es igualmente un Duration.

Instant utiliza un reloj monotónico, adecuado para medir intervalos porque no retrocede como consecuencia de los ajustes del reloj del sistema. No obstante, no proporciona una hora absoluta que podamos guardar y utilizar como fecha de un evento.

20.3 Hora del reloj de pared (SystemTime)

Cuando necesitamos conocer la fecha y hora en que se produce un suceso, Rust proporciona el tipo SystemTime, definido en el módulo std::time.

Sin embargo, SystemTime no dispone de métodos para convertir directamente un instante en una fecha y hora legibles. Para ello podemos utilizar bibliotecas externas, como chrono, que permite obtener la hora local y formatearla de distintas maneras. El siguiente ejemplo muestra la fecha y hora actuales en un formato habitual y en formato ISO 8601:

use chrono::Local;

fn main() {
    let ahora = Local::now();

    println!("Fecha y hora: {}", ahora.format("%Y-%m-%d %H:%M:%S"));
    println!("Formato ISO 8601: {}", ahora.to_rfc3339());
}

Este ejemplo utiliza una biblioteca externa, por lo que debemos ejecutarlo en un proyecto local en lugar de utilizar nuestro Rust Playground habitual, configurado para los ejemplos de la biblioteca estándar.

El resultado será similar al siguiente:

Fecha y hora: 2026-10-13 22:01:03
Formato ISO 8601: 2026-10-13T22:01:03.291221996+02:00

Para incorporar la biblioteca chrono al proyecto, ejecutamos el siguiente comando desde su directorio:

cargo add chrono

Cargo añadirá la dependencia al fichero Cargo.toml y descargará la biblioteca cuando sea necesario compilar el proyecto.

Si no disponemos del subcomando cargo add, podemos añadir manualmente la siguiente sección al fichero Cargo.toml:

[dependencies]
chrono = "0.4"

20.4 Resumen

En Rust podemos trabajar con el tiempo de distintas maneras, según las necesidades del programa:

  • Hora lógica: podemos utilizar un contador para ordenar sucesos sin necesidad de medir el tiempo real.
  • Medición de intervalos: el tipo Instant, del módulo std::time, permite medir el tiempo transcurrido entre dos instantes. El resultado se representa mediante un valor de tipo Duration.
  • Hora del reloj de pared: el tipo SystemTime, también del módulo std::time, permite obtener un instante del reloj del sistema. Para convertirlo en una fecha y hora legibles podemos utilizar bibliotecas externas, como chrono.

Es importante distinguir entre ordenar sucesos, medir cuánto tiempo transcurre y conocer la fecha y hora en que ocurre un evento. Cada necesidad requiere un enfoque diferente.