Python

Python

Tutorial Python: Módulo time

Aprende a usar el módulo time en Python para medir tiempos, crear pausas y convertir formatos temporales con ejemplos prácticos y detallados.

Aprende Python y certifícate

Medición de tiempo

El módulo time de Python proporciona funciones para trabajar con tiempo a un nivel más cercano al sistema operativo, siendo especialmente útil para medir el rendimiento de código y crear temporizadores precisos. A diferencia del módulo datetime (que se enfoca en fechas y horas en formato calendario), time está orientado a operaciones de temporización de alta precisión.

La medición de tiempo es una de las aplicaciones más comunes del módulo time, permitiéndonos evaluar cuánto tarda en ejecutarse una porción de código. Esto resulta fundamental para optimización de rendimiento y análisis de algoritmos.

Funciones principales para medición de tiempo

Python ofrece varias funciones para medir tiempo con diferentes niveles de precisión:

  • time.time(): Devuelve el tiempo en segundos desde la "época" (1 de enero de 1970) como un número de punto flotante.
  • time.perf_counter(): Proporciona el valor de un contador de rendimiento de alta resolución, ideal para medir tiempos cortos.
  • time.process_time(): Devuelve la suma del tiempo de CPU del proceso actual y sus subprocesos.
  • time.monotonic(): Retorna un valor que siempre aumenta, no afectado por ajustes del reloj del sistema.

Veamos cada una con más detalle:

Usando time.time()

Esta es la función más básica para medir tiempo, pero puede ser menos precisa para intervalos muy cortos:

import time

inicio = time.time()
# Código a medir
for i in range(1000000):
    pass
fin = time.time()

tiempo_transcurrido = fin - inicio
print(f"Tiempo de ejecución: {tiempo_transcurrido:.6f} segundos")

Usando time.perf_counter()

Esta función proporciona la mayor precisión para medir el rendimiento del código y es la recomendada para benchmarking:

import time

inicio = time.perf_counter()
# Código a medir
resultado = sum(range(10000000))
fin = time.perf_counter()

print(f"La operación tardó {fin - inicio:.6f} segundos")
print(f"Resultado: {resultado}")

Usando time.process_time()

A diferencia de las anteriores, esta función solo mide el tiempo de CPU utilizado por el proceso, excluyendo el tiempo que el sistema operativo dedica a otras tareas:

import time

inicio = time.process_time()
# Operación intensiva de CPU
[i**2 for i in range(10000000)]
fin = time.process_time()

print(f"Tiempo de CPU utilizado: {fin - inicio:.6f} segundos")

Usando time.monotonic()

Esta función es útil cuando necesitamos un tiempo que siempre avanza independientemente de los ajustes del reloj del sistema:

import time

inicio = time.monotonic()
# Código a medir
time.sleep(1.5)  # Simulamos una operación
fin = time.monotonic()

print(f"Tiempo transcurrido: {fin - inicio:.6f} segundos")

Comparación de métodos de medición

Cada método tiene sus propias características y casos de uso:

Función Precisión Afectado por ajustes del reloj Mide solo CPU Uso recomendado
time.time() Media No Intervalos largos, no críticos
time.perf_counter() Muy alta No No Benchmarking, mediciones precisas
time.process_time() Alta No Análisis de rendimiento de CPU
time.monotonic() Alta No No Mediciones que no deben retroceder

Creando un decorador para medir tiempo

Una aplicación práctica es crear un decorador que mida automáticamente el tiempo de ejecución de cualquier función:

import time
from functools import wraps

def medir_tiempo(funcion):
    @wraps(funcion)
    def wrapper(*args, **kwargs):
        inicio = time.perf_counter()
        resultado = funcion(*args, **kwargs)
        fin = time.perf_counter()
        print(f"Función {funcion.__name__} ejecutada en {fin - inicio:.6f} segundos")
        return resultado
    return wrapper

# Ejemplo de uso
@medir_tiempo
def algoritmo_ordenamiento(n):
    # Simulamos un algoritmo de ordenamiento
    lista = list(range(n))
    lista.sort(reverse=True)
    lista.sort()
    return len(lista)

# Probamos con diferentes tamaños
algoritmo_ordenamiento(10000)
algoritmo_ordenamiento(100000)
algoritmo_ordenamiento(1000000)

Midiendo bloques de código con contexto

También podemos crear un administrador de contexto para medir bloques específicos de código:

import time
from contextlib import contextmanager

@contextmanager
def temporizador(nombre="Operación"):
    inicio = time.perf_counter()
    try:
        yield
    finally:
        fin = time.perf_counter()
        print(f"{nombre} completada en {fin - inicio:.6f} segundos")

# Ejemplo de uso
with temporizador("Cálculo de primos"):
    # Encontrar números primos hasta 100000
    primos = []
    for num in range(2, 100000):
        es_primo = all(num % i != 0 for i in range(2, int(num**0.5) + 1))
        if es_primo:
            primos.append(num)
    print(f"Se encontraron {len(primos)} números primos")

Comparando rendimiento de algoritmos

Una aplicación común de la medición de tiempo es comparar diferentes implementaciones de un mismo algoritmo:

import time

def fibonacci_recursivo(n):
    if n <= 1:
        return n
    return fibonacci_recursivo(n-1) + fibonacci_recursivo(n-2)

def fibonacci_iterativo(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

# Comparamos rendimiento
n = 30

inicio = time.perf_counter()
resultado1 = fibonacci_recursivo(n)
tiempo1 = time.perf_counter() - inicio

inicio = time.perf_counter()
resultado2 = fibonacci_iterativo(n)
tiempo2 = time.perf_counter() - inicio

print(f"Fibonacci recursivo: {tiempo1:.6f} segundos")
print(f"Fibonacci iterativo: {tiempo2:.6f} segundos")
print(f"La versión iterativa es {tiempo1/tiempo2:.1f} veces más rápida")

Consideraciones importantes

Al medir tiempos de ejecución, ten en cuenta estos factores:

  • Variabilidad: Las mediciones pueden variar según la carga del sistema. Para resultados más confiables, realiza múltiples mediciones.
  • Precisión: Para operaciones muy rápidas (microsegundos), considera ejecutar la operación miles de veces y dividir el tiempo total.
  • Overhead: La propia medición introduce un pequeño overhead que puede ser significativo para operaciones muy rápidas.
  • Optimizaciones del intérprete: El intérprete de Python puede optimizar código en ejecuciones repetidas, afectando las mediciones.
import time
import statistics

def medir_operacion_rapida():
    tiempos = []
    for _ in range(100):
        inicio = time.perf_counter()
        # Operación muy rápida
        sum(range(1000))
        fin = time.perf_counter()
        tiempos.append(fin - inicio)
    
    return {
        "min": min(tiempos),
        "max": max(tiempos),
        "promedio": statistics.mean(tiempos),
        "mediana": statistics.median(tiempos)
    }

estadisticas = medir_operacion_rapida()
print(f"Estadísticas de tiempo (segundos):")
for clave, valor in estadisticas.items():
    print(f"  {clave}: {valor:.9f}")

La medición precisa del tiempo de ejecución es una herramienta fundamental para la optimización de código y el análisis de rendimiento, permitiéndonos identificar cuellos de botella y validar mejoras en nuestros algoritmos.

Pausas y esperas

El módulo time de Python no solo permite medir el tiempo de ejecución, sino que también ofrece funciones para introducir pausas controladas en nuestros programas. Estas pausas son fundamentales para muchas aplicaciones prácticas como la limitación de tasas de solicitudes, simulaciones, animaciones o simplemente para dar tiempo a que otros procesos completen sus tareas.

La capacidad de pausar la ejecución de un programa de manera precisa es una herramienta esencial en el desarrollo de software, especialmente en aplicaciones que interactúan con recursos externos o que necesitan sincronización temporal.

Función sleep() básica

La función principal para introducir pausas es time.sleep(), que suspende la ejecución del programa durante un número específico de segundos:

import time

print("Inicio del programa")
time.sleep(2)  # Pausa la ejecución durante 2 segundos
print("Mensaje después de 2 segundos")

Esta función acepta valores de punto flotante, lo que permite pausas de fracciones de segundo:

import time

print("Contando con pausas de medio segundo:")
for i in range(5):
    print(i + 1)
    time.sleep(0.5)  # Pausa de 500 milisegundos
print("¡Conteo finalizado!")

Creando temporizadores y contadores regresivos

Podemos combinar sleep() con otras funciones para crear temporizadores simples:

import time

def temporizador(segundos):
    """Temporizador simple que muestra una cuenta regresiva."""
    print(f"Temporizador iniciado: {segundos} segundos")
    
    for restante in range(segundos, 0, -1):
        print(f"Tiempo restante: {restante} segundos")
        time.sleep(1)
    
    print("¡Tiempo terminado!")

# Ejemplo de uso
temporizador(5)

Limitación de tasas (Rate limiting)

Una aplicación práctica común es la limitación de tasas para evitar sobrecargar servicios externos:

import time
import random

def obtener_datos_api(id_recurso):
    # Simulación de llamada a API
    print(f"Obteniendo datos para recurso {id_recurso}...")
    time.sleep(0.3)  # Simulamos tiempo de respuesta
    return {"id": id_recurso, "valor": random.randint(1, 100)}

def procesar_recursos_con_limite(lista_ids, solicitudes_por_segundo=2):
    """Procesa recursos respetando un límite de solicitudes por segundo."""
    intervalo = 1.0 / solicitudes_por_segundo
    resultados = []
    
    for id_recurso in lista_ids:
        inicio = time.perf_counter()
        
        # Realizar la solicitud
        datos = obtener_datos_api(id_recurso)
        resultados.append(datos)
        
        # Calcular tiempo a esperar para mantener la tasa deseada
        tiempo_proceso = time.perf_counter() - inicio
        tiempo_espera = max(0, intervalo - tiempo_proceso)
        
        if tiempo_espera > 0:
            time.sleep(tiempo_espera)
    
    return resultados

# Ejemplo: procesar 10 recursos a 2 solicitudes por segundo
ids_recursos = list(range(1, 11))
resultados = procesar_recursos_con_limite(ids_recursos)
print(f"Procesados {len(resultados)} recursos")

Implementando retroceso exponencial

El retroceso exponencial es una técnica que incrementa progresivamente el tiempo de espera entre reintentos, útil para manejar errores transitorios:

import time
import random

def operacion_con_posible_fallo():
    """Simula una operación que puede fallar aleatoriamente."""
    if random.random() < 0.7:  # 70% de probabilidad de fallo
        raise Exception("Error temporal en la operación")
    return "Operación exitosa"

def ejecutar_con_reintentos(max_intentos=5, retraso_inicial=1):
    """Ejecuta una operación con reintentos y retroceso exponencial."""
    intentos = 0
    retraso = retraso_inicial
    
    while intentos < max_intentos:
        try:
            resultado = operacion_con_posible_fallo()
            print(f"Éxito en el intento {intentos + 1}")
            return resultado
        except Exception as e:
            intentos += 1
            if intentos == max_intentos:
                print(f"Fallaron todos los intentos ({max_intentos})")
                raise
            
            print(f"Intento {intentos} falló: {e}")
            print(f"Esperando {retraso:.2f} segundos antes del siguiente intento...")
            time.sleep(retraso)
            
            # Incremento exponencial del tiempo de espera
            retraso *= 2
            # Añadimos un pequeño factor aleatorio para evitar sincronización
            retraso *= (0.9 + 0.2 * random.random())

# Ejemplo de uso
try:
    resultado = ejecutar_con_reintentos()
    print(f"Resultado final: {resultado}")
except Exception as e:
    print(f"Error final: {e}")

Implementando un throttle para funciones

Podemos crear un decorador que limite la frecuencia con la que se puede llamar a una función:

import time
from functools import wraps

def throttle(intervalo_segundos):
    """
    Decorador que limita la frecuencia de llamadas a una función.
    Si se llama antes del intervalo, espera el tiempo restante.
    """
    def decorador(funcion):
        ultima_llamada = 0
        
        @wraps(funcion)
        def wrapper(*args, **kwargs):
            nonlocal ultima_llamada
            tiempo_actual = time.monotonic()
            tiempo_transcurrido = tiempo_actual - ultima_llamada
            
            # Si no ha pasado suficiente tiempo, esperamos
            if tiempo_transcurrido < intervalo_segundos:
                tiempo_espera = intervalo_segundos - tiempo_transcurrido
                time.sleep(tiempo_espera)
            
            # Actualizamos el tiempo de la última llamada
            ultima_llamada = time.monotonic()
            return funcion(*args, **kwargs)
        
        return wrapper
    
    return decorador

# Ejemplo: función que no puede llamarse más de una vez cada 2 segundos
@throttle(2)
def funcion_costosa(parametro):
    print(f"Ejecutando operación costosa con {parametro}")
    return f"Resultado para {parametro}"

# Probamos llamadas consecutivas
for i in range(3):
    print(f"Llamada {i+1} iniciada en {time.strftime('%H:%M:%S')}")
    resultado = funcion_costosa(f"parámetro {i+1}")
    print(f"Llamada {i+1} completada en {time.strftime('%H:%M:%S')}")

Simulando operaciones asíncronas

Aunque Python tiene soporte para programación asíncrona con asyncio, podemos simular comportamientos asíncronos básicos con time.sleep():

import time
import threading

def tarea_larga(nombre, duracion):
    print(f"Iniciando tarea: {nombre}")
    time.sleep(duracion)  # Simulamos procesamiento
    print(f"Tarea completada: {nombre} (duración: {duracion}s)")
    return f"Resultado de {nombre}"

# Ejecutar tareas en paralelo usando hilos
def ejecutar_tareas_paralelas():
    tareas = [
        ("Tarea A", 3),
        ("Tarea B", 1),
        ("Tarea C", 2),
    ]
    
    hilos = []
    for nombre, duracion in tareas:
        hilo = threading.Thread(target=tarea_larga, args=(nombre, duracion))
        hilos.append(hilo)
        hilo.start()
    
    # Esperar a que todos los hilos terminen
    for hilo in hilos:
        hilo.join()
    
    print("Todas las tareas completadas")

# Ejecutamos las tareas en paralelo
ejecutar_tareas_paralelas()

Consideraciones sobre precisión

Es importante entender que time.sleep() no garantiza una precisión perfecta, especialmente para intervalos muy cortos:

import time
import statistics

def probar_precision_sleep():
    duraciones_reales = []
    duracion_objetivo = 0.01  # 10 milisegundos
    
    for _ in range(20):
        inicio = time.perf_counter()
        time.sleep(duracion_objetivo)
        fin = time.perf_counter()
        duracion_real = fin - inicio
        duraciones_reales.append(duracion_real)
    
    promedio = statistics.mean(duraciones_reales)
    desviacion = statistics.stdev(duraciones_reales)
    
    print(f"Duración objetivo: {duracion_objetivo * 1000:.2f} ms")
    print(f"Duración promedio: {promedio * 1000:.2f} ms")
    print(f"Desviación estándar: {desviacion * 1000:.2f} ms")
    print(f"Mínimo: {min(duraciones_reales) * 1000:.2f} ms")
    print(f"Máximo: {max(duraciones_reales) * 1000:.2f} ms")

probar_precision_sleep()

La precisión de sleep() puede verse afectada por:

  • Resolución del temporizador del sistema operativo
  • Carga del sistema y programación de tareas
  • Prioridad del proceso de Python
  • Virtualización (en entornos virtualizados o contenedores)

Alternativas para casos especiales

En situaciones donde necesitamos mayor precisión o comportamientos específicos:

  • Para esperas ocupadas (sin ceder el control al sistema operativo):
import time

def espera_ocupada(segundos):
    """Realiza una espera ocupada (sin ceder el control al SO)."""
    tiempo_final = time.perf_counter() + segundos
    
    while time.perf_counter() < tiempo_final:
        pass  # Bucle vacío que consume CPU

print("Iniciando espera ocupada de 1 segundo...")
espera_ocupada(1)
print("Espera ocupada finalizada")
  • Para esperas con comprobación periódica:
import time

def esperar_hasta_condicion(condicion_func, timeout=10, intervalo=0.1):
    """Espera hasta que una condición sea verdadera o se agote el tiempo."""
    inicio = time.monotonic()
    
    while time.monotonic() - inicio < timeout:
        if condicion_func():
            return True
        time.sleep(intervalo)
    
    return False

# Ejemplo: esperar a que un valor alcance cierto umbral
valor = 0

def incrementar_valor():
    global valor
    valor += 1
    print(f"Valor actual: {valor}")
    return valor >= 5

# Simulamos un proceso que incrementa el valor cada 0.3 segundos
def proceso_incremento():
    global valor
    while valor < 10:
        time.sleep(0.3)
        valor += 1
        print(f"Proceso: incrementado valor a {valor}")

# Iniciamos el proceso en un hilo
import threading
hilo = threading.Thread(target=proceso_incremento)
hilo.daemon = True
hilo.start()

# Esperamos a que el valor llegue a 5
resultado = esperar_hasta_condicion(
    lambda: valor >= 5,
    timeout=5,
    intervalo=0.2
)

print(f"Condición cumplida: {resultado}, valor final: {valor}")

Las pausas y esperas son herramientas fundamentales en la programación con Python, permitiéndonos controlar el flujo temporal de nuestras aplicaciones, desde simples retardos hasta sofisticados mecanismos de control de tasas y sincronización.

Conversión entre formatos de tiempo

El módulo time de Python proporciona diversas funciones para convertir entre diferentes representaciones de tiempo, permitiéndonos transformar marcas de tiempo (timestamps) en cadenas legibles por humanos y viceversa. Estas conversiones son esenciales cuando necesitamos presentar información temporal al usuario o cuando trabajamos con diferentes sistemas que utilizan distintos formatos de tiempo.

A diferencia del módulo datetime, que se centra en manipulaciones de fechas a alto nivel, time trabaja con representaciones más cercanas al sistema operativo, ofreciendo mayor rendimiento para ciertas operaciones.

Representaciones de tiempo en Python

Python maneja principalmente tres tipos de representaciones temporales a través del módulo time:

  • Epoch time (timestamp): Segundos transcurridos desde el 1 de enero de 1970 (época Unix).
  • Tiempo estructurado: Una tupla de 9 elementos que contiene año, mes, día, hora, minuto, segundo, día de la semana, día del año y bandera de horario de verano.
  • Cadenas de texto formateadas: Representaciones legibles de fechas y horas.

Conversión de timestamp a tiempo estructurado

La función time.localtime() convierte un timestamp en una estructura de tiempo local, mientras que time.gmtime() lo convierte a tiempo UTC:

import time

# Obtener el timestamp actual
timestamp_actual = time.time()
print(f"Timestamp actual: {timestamp_actual}")

# Convertir a tiempo estructurado local
tiempo_local = time.localtime(timestamp_actual)
print(f"Tiempo estructurado local: {tiempo_local}")

# Convertir a tiempo UTC (Greenwich Mean Time)
tiempo_utc = time.gmtime(timestamp_actual)
print(f"Tiempo estructurado UTC: {tiempo_utc}")

El resultado de estas funciones es un objeto struct_time, que contiene los siguientes atributos:

import time

timestamp = time.time()
t = time.localtime(timestamp)

# Accediendo a los componentes individuales
print(f"Año: {t.tm_year}")
print(f"Mes: {t.tm_mon}")
print(f"Día: {t.tm_mday}")
print(f"Hora: {t.tm_hour}")
print(f"Minuto: {t.tm_min}")
print(f"Segundo: {t.tm_sec}")
print(f"Día de la semana: {t.tm_wday}")  # 0 es lunes, 6 es domingo
print(f"Día del año: {t.tm_yday}")       # 1-366
print(f"Horario de verano: {t.tm_isdst}")  # 1 si está en horario de verano

Conversión de tiempo estructurado a timestamp

Para realizar la conversión inversa, utilizamos time.mktime():

import time

# Crear un tiempo estructurado (31 de diciembre de 2023, 23:59:59)
tiempo_struct = time.struct_time((2023, 12, 31, 23, 59, 59, 6, 365, 0))

# Convertir a timestamp
timestamp = time.mktime(tiempo_struct)
print(f"Timestamp: {timestamp}")

# Verificar la conversión
print(f"Fecha convertida: {time.ctime(timestamp)}")

Formateo de tiempo a cadenas de texto

Python ofrece varias funciones para convertir tiempos a cadenas legibles:

Usando time.ctime()

La forma más simple de obtener una representación de texto:

import time

timestamp = time.time()
cadena_tiempo = time.ctime(timestamp)
print(f"Tiempo actual: {cadena_tiempo}")

Usando time.strftime()

Para un control más preciso sobre el formato, utilizamos strftime() (string format time):

import time

ahora = time.localtime()

# Diferentes formatos de fecha y hora
formato_fecha = time.strftime("%d/%m/%Y", ahora)
formato_hora = time.strftime("%H:%M:%S", ahora)
formato_completo = time.strftime("%A, %d de %B de %Y - %H:%M:%S", ahora)

print(f"Fecha: {formato_fecha}")
print(f"Hora: {formato_hora}")
print(f"Formato completo: {formato_completo}")

Los códigos de formato más comunes para strftime() son:

  • %d: Día del mes (01-31)
  • %m: Mes (01-12)
  • %Y: Año con cuatro dígitos
  • %y: Año con dos dígitos
  • %H: Hora en formato 24h (00-23)
  • %I: Hora en formato 12h (01-12)
  • %M: Minutos (00-59)
  • %S: Segundos (00-59)
  • %A: Nombre completo del día de la semana
  • %a: Nombre abreviado del día de la semana
  • %B: Nombre completo del mes
  • %b: Nombre abreviado del mes
  • %p: AM/PM
  • %Z: Zona horaria

Conversión de cadenas de texto a tiempo estructurado

Para convertir una cadena de texto a una estructura de tiempo, usamos time.strptime() (string parse time):

import time

# Cadena de texto que representa una fecha y hora
fecha_texto = "21/09/2023 15:30:45"

# Convertir a tiempo estructurado especificando el formato
tiempo_struct = time.strptime(fecha_texto, "%d/%m/%Y %H:%M:%S")
print(f"Tiempo estructurado: {tiempo_struct}")

# Convertir a timestamp
timestamp = time.mktime(tiempo_struct)
print(f"Timestamp: {timestamp}")

Trabajando con zonas horarias

El módulo time tiene funcionalidades básicas para trabajar con zonas horarias:

import time

# Obtener la zona horaria local
zona_local = time.tzname
print(f"Zona horaria local: {zona_local}")

# Verificar si estamos en horario de verano
es_horario_verano = time.localtime().tm_isdst
print(f"¿Estamos en horario de verano? {'Sí' if es_horario_verano else 'No'}")

# Diferencia en segundos entre hora local y UTC
diferencia_utc = time.timezone
print(f"Diferencia con UTC (segundos): {diferencia_utc}")
print(f"Diferencia con UTC (horas): {diferencia_utc / 3600}")

Aplicaciones prácticas

Convertir timestamps de logs a formato legible

import time

# Simulación de timestamps de un archivo de log
log_timestamps = [1632215460, 1632215520, 1632215580, 1632215640]

print("Registro de eventos:")
for ts in log_timestamps:
    # Convertir a formato legible
    fecha_hora = time.strftime("%d-%m-%Y %H:%M:%S", time.localtime(ts))
    print(f"[{fecha_hora}] Evento registrado")

Calcular diferencias de tiempo entre zonas horarias

import time

def convertir_a_zona_horaria(timestamp, horas_diferencia):
    """Convierte un timestamp a una zona horaria con diferencia en horas."""
    # Convertir a tiempo estructurado UTC
    tiempo_utc = time.gmtime(timestamp)
    
    # Crear una cadena con el tiempo UTC
    tiempo_str = time.strftime("%Y-%m-%d %H:%M:%S", tiempo_utc)
    
    # Parsear de nuevo a tiempo estructurado
    tiempo_struct = time.strptime(tiempo_str, "%Y-%m-%d %H:%M:%S")
    
    # Convertir a timestamp y ajustar por la diferencia horaria
    nuevo_timestamp = time.mktime(tiempo_struct) + (horas_diferencia * 3600)
    
    return nuevo_timestamp

# Timestamp actual
ahora = time.time()

# Mostrar la hora actual en diferentes zonas horarias
print(f"Hora local: {time.strftime('%H:%M:%S', time.localtime(ahora))}")

# Nueva York (UTC-5 o UTC-4 en horario de verano)
ny_time = convertir_a_zona_horaria(ahora, -5)
print(f"Hora en Nueva York: {time.strftime('%H:%M:%S', time.localtime(ny_time))}")

# Tokio (UTC+9)
tokio_time = convertir_a_zona_horaria(ahora, 9)
print(f"Hora en Tokio: {time.strftime('%H:%M:%S', time.localtime(tokio_time))}")

Crear un formateador de fechas personalizado

import time

def formatear_fecha(timestamp, formato="completo", locale="es"):
    """
    Formatea un timestamp en diferentes estilos según el locale.
    
    Formatos disponibles:
    - corto: DD/MM/YYYY
    - medio: DD de Mes, YYYY
    - completo: Día, DD de Mes de YYYY a las HH:MM
    """
    tiempo = time.localtime(timestamp)
    
    # Nombres de días y meses en español
    if locale == "es":
        dias = ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"]
        meses = ["enero", "febrero", "marzo", "abril", "mayo", "junio", 
                "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"]
    else:  # inglés por defecto
        dias = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
        meses = ["January", "February", "March", "April", "May", "June", 
                "July", "August", "September", "October", "November", "December"]
    
    dia_semana = dias[tiempo.tm_wday]
    mes = meses[tiempo.tm_mon - 1]
    
    if formato == "corto":
        return time.strftime("%d/%m/%Y", tiempo)
    elif formato == "medio":
        return f"{tiempo.tm_mday} de {mes}, {tiempo.tm_year}"
    else:  # completo
        return f"{dia_semana}, {tiempo.tm_mday} de {mes} de {tiempo.tm_year} a las {tiempo.tm_hour}:{tiempo.tm_min:02d}"

# Probar con el timestamp actual
ahora = time.time()

print("Formatos en español:")
print(f"Corto: {formatear_fecha(ahora, 'corto')}")
print(f"Medio: {formatear_fecha(ahora, 'medio')}")
print(f"Completo: {formatear_fecha(ahora, 'completo')}")

print("\nFormatos en inglés:")
print(f"Corto: {formatear_fecha(ahora, 'corto', 'en')}")
print(f"Medio: {formatear_fecha(ahora, 'medio', 'en')}")
print(f"Completo: {formatear_fecha(ahora, 'completo', 'en')}")

Convertir entre formatos de tiempo ISO 8601 y timestamp

import time
import re

def iso8601_a_timestamp(iso_string):
    """Convierte una cadena ISO 8601 (YYYY-MM-DDTHH:MM:SS) a timestamp."""
    # Extraer componentes con expresión regular
    pattern = r"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})"
    match = re.match(pattern, iso_string)
    
    if not match:
        raise ValueError("Formato ISO 8601 inválido")
    
    # Crear tiempo estructurado
    year, month, day, hour, minute, second = map(int, match.groups())
    tiempo_struct = time.struct_time((year, month, day, hour, minute, second, 0, 0, -1))
    
    # Convertir a timestamp
    return time.mktime(tiempo_struct)

def timestamp_a_iso8601(timestamp):
    """Convierte un timestamp a formato ISO 8601."""
    return time.strftime("%Y-%m-%dT%H:%M:%S", time.localtime(timestamp))

# Ejemplos de uso
iso_fecha = "2023-09-21T15:30:00"
print(f"ISO 8601: {iso_fecha}")

# Convertir a timestamp
ts = iso8601_a_timestamp(iso_fecha)
print(f"Timestamp: {ts}")

# Convertir de nuevo a ISO 8601
iso_reconvertido = timestamp_a_iso8601(ts)
print(f"ISO 8601 reconvertido: {iso_reconvertido}")

Consideraciones importantes

Al trabajar con conversiones de tiempo, ten en cuenta:

  • Localización: Las funciones localtime() y strftime() dependen de la configuración regional del sistema.
  • Año 2038: En sistemas de 32 bits, los timestamps tienen un límite (problema del año 2038).
  • Precisión: Los timestamps en time tienen precisión de segundos; para mayor precisión, considera usar datetime.
  • Zonas horarias: Para manejo avanzado de zonas horarias, el módulo datetime junto con pytz ofrece más funcionalidades.
import time

# Demostración del formato de 12 horas vs 24 horas
ahora = time.localtime()

formato_12h = time.strftime("%I:%M:%S %p", ahora)  # 12 horas con AM/PM
formato_24h = time.strftime("%H:%M:%S", ahora)     # 24 horas

print(f"Formato 12 horas: {formato_12h}")
print(f"Formato 24 horas: {formato_24h}")

# Demostración de formatos internacionales
formato_us = time.strftime("%m/%d/%Y", ahora)      # MM/DD/YYYY (EE.UU.)
formato_eu = time.strftime("%d/%m/%Y", ahora)      # DD/MM/YYYY (Europa)
formato_iso = time.strftime("%Y-%m-%d", ahora)     # YYYY-MM-DD (ISO)

print(f"Formato EE.UU.: {formato_us}")
print(f"Formato europeo: {formato_eu}")
print(f"Formato ISO: {formato_iso}")

El dominio de las conversiones entre formatos de tiempo es fundamental para desarrollar aplicaciones que manejen datos temporales de manera efectiva, ya sea para presentación al usuario, almacenamiento en bases de datos o comunicación entre sistemas con diferentes convenciones de formato.

Aprende Python online

Otras lecciones de Python

Accede a todas las lecciones de Python y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.

Accede GRATIS a Python y certifícate

Ejercicios de programación de Python

Evalúa tus conocimientos de esta lección Módulo time con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.