La trampa en el uso de fechas y monedas en las aplicaciones de software

La trampa en el uso de fechas y monedas en las aplicaciones de software

A lo largo de mis años en el campo de la programación, he notado una serie de desafíos que se repiten independientemente de la experiencia del desarrollador. Entre estos, el manejo adecuado de fechas y monedas destaca como un área particularmente engañosa. La razón es simple: estos campos parecen directos, pero esconden complejidades que pueden ser trampas, te explico.

Manejando fechas y horas

Las fechas son especialmente difíciles debido a las zonas horarias, los cambios por horario de verano, y los múltiples formatos de representación. Un simple error puede resultar en mostrar una fecha completamente diferente.

El poder del timestamp

Una solución poco apreciada es el 'timestamp'. Aunque parece una fecha, en realidad se almacena como un número entero. Este número representa la cantidad de segundos (o milisegundos) desde un punto específico en el tiempo, la "época Unix", que comenzó el 1 de enero de 1970.

import time
from datetime import datetime

# Convertir una fecha y hora a timestamp
fecha_actual = datetime.now()
timestamp_actual = time.mktime(fecha_actual.timetuple())

# Convertir un timestamp de regreso a una fecha y hora
fecha_convertida = datetime.fromtimestamp(timestamp_actual)

Hay que tomar en cuenta que debes utilizar UTC siempre como punto de referencia al convertir fechas a timestamp.

Este enfoque elimina problemas relacionados con zonas horarias y formatos de fecha. Además, es altamente eficiente para consultas y comparaciones, ya que facilmente te permitirá realizar operaciones como adición o substracción de fechas (ojo, no estoy diciendo que sea la única manera de hacerlo, porque también los motores de bases de datos tienen métodos para realizar algunas de estas operaciones).

Veamos ahora que pasa con los números decimales

El manejo de dinero presenta desafíos similares. A simple vista, un número decimal parece perfecto para representar cantidades. Sin embargo, los números de punto flotante a menudo introducen errores de precisión.

Deberías empezar a utilizar centavos

En lugar de trabajar con montos completos, almacenar y manipular dinero en su forma más pequeña, como centavos, puede evitar problemas de precisión.

total = 12.34
total_centavos = int(total * 100)

total_convertido = total / 100.0

Recomendaciones para el almacenamiento en bases de datos

Las bases de datos son el almacén central de información para muchas aplicaciones y, por lo tanto, es crucial que la información esté almacenada de manera óptima. Vamos a desglosar las mejores prácticas para almacenar fechas y monedas:

  • Fechas:

    • DATETIME vs TIMESTAMP: Ambos tipos son utilizados para almacenar fechas y horas. Sin embargo, hay diferencias clave. TIMESTAMP representa la cantidad de segundos desde la "época Unix" y se convierte automáticamente a la zona horaria del servidor de la base de datos. DATETIME, por otro lado, no tiene esta conversión automática. Mi recomendación es:
    • Utiliza TIMESTAMP cuando necesites realizar operaciones relacionadas con la diferencia entre fechas o cuando la aplicación se distribuye en diferentes zonas horarias. Es ideal para guardar momentos exactos, como marcas de tiempo de creación o modificación.
    • Usa DATETIME si solo estás almacenando fechas sin un significado relacionado con zonas horarias, como una fecha de nacimiento.
    • Siempre almacena las fechas en formato UTC. Convertir a la zona horaria local solo cuando se va a mostrar al usuario final.
  • Monedas:

    • FLOAT vs DECIMAL vs INTEGER: Los tipos de datos de punto flotante, como FLOAT, pueden introducir errores de precisión, lo que es inaceptable en operaciones financieras.
    • DECIMAL es un tipo de dato que puede representar números con muchos dígitos a la derecha del punto decimal sin perder precisión. Es adecuado para operaciones financieras donde la precisión es fundamental y donde los valores pueden variar ampliamente en escala.
    • INTEGER (o BIGINT para cantidades muy grandes) es perfecto si decides almacenar montos en su unidad más pequeña (por ejemplo, centavos). Esta estrategia elimina la necesidad de lidiar con decimales y mantiene la precisión.
    • Mi recomendación es:
      • Usa INTEGER o BIGINT cuando sea posible almacenar montos en unidades mínimas, garantizando la precisión.
      • En situaciones donde esto no sea posible o conveniente, DECIMAL es el camino a seguir. Evita FLOAT para operaciones financieras.

Cuando se trata de operaciones financieras, la precisión es esencial, las principales razones para preferir DECIMAL sobre FLOAT en ese contexto:

  1. Representación: FLOAT utiliza una representación binaria que, para ciertos números decimales, no es exacta, lo que lleva a problemas de redondeo.

  2. Precisión Fija: DECIMAL tiene una precisión fija, garantizando un número específico de dígitos después del punto decimal, ideal para transacciones monetarias.

  3. Errores Acumulativos: Usar FLOAT en muchas operaciones aritméticas en serie puede llevar a errores significativos, especialmente problemáticos en aplicaciones financieras.

Por lo tanto, para asegurar precisión en operaciones financieras, se recomienda usar DECIMAL o representaciones enteras como INTEGER o BIGINT (para montos en centavos). Evita usar FLOAT, ya que no garantiza la exactitud necesaria para operaciones monetarias.


Siempre intenta ser más preciso

El manejo de fechas y monedas es solo una pieza de un gran rompecabezas en el desarrollo de software. Al adoptar estas prácticas y patrones de diseño, no solo evitamos errores comunes, sino que también fortalecemos la base sobre la cual construimos nuestras soluciones. Es más que una recomendación; es una hoja de ruta hacia una programación más precisa y eficiente.

Happy coding! :D


Photo by Nick Fewings on Unsplash

Jack Fiallos

Jack Fiallos

Te gustó este artículo?