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
vsTIMESTAMP
: 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
vsDECIMAL
vsINTEGER
: Los tipos de datos de punto flotante, comoFLOAT
, 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
(oBIGINT
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
oBIGINT
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. EvitaFLOAT
para operaciones financieras.
- Usa
Cuando se trata de operaciones financieras, la precisión es esencial, las principales razones para preferir
DECIMAL
sobreFLOAT
en ese contexto:
Representación:
FLOAT
utiliza una representación binaria que, para ciertos números decimales, no es exacta, lo que lleva a problemas de redondeo.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.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 comoINTEGER
oBIGINT
(para montos en centavos). Evita usarFLOAT
, 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