El extraño bug del Calendar
Publicado en Java el 4 de March, 2010 por Lek. (7 comentarios)Cuando empezaba a programar con C y C++ recuerdo los quebraderos de cabeza para comprobar que los valores “entraban” dentro de las variables y evitar desbordamientos problemáticos. Java solucionó esto haciendo que, si el valor se pasaba del rango de la variable, se reiniciaba el contador. Es decir, que si queremos poner el valor 212 a un fichero byte (-128 a 127), Java nos muestra en realidad -44.
Esto, que en principio puede parecer un gran avance porque evita problemas de seguridad en los programas (uno de los motivos por los que en Java no se pueden manejar punteros), al final se demuestra que es un nido de bugs. Porque 212 no son -44. Y esto puede ser un auténtico problema en algo tan visible como una fecha.
El mes de marzo es un mes muy especial. Su mes anterior es de longitud variable (28 ó 29 días) y el siguiente es de 30, siendo el propio marzo de 31. Ved el siguiente código:
Calendar cal = new GregorianCalendar(); cal.set (Calendar.DAY_OF_MONTH, 30); cal.set (Calendar.MONTH, 2); System.out.println (cal.getTime ()); System.out.println (cal.getActualMaximum (Calendar.DAY_OF_MONTH)); cal.set (Calendar.MONTH, cal.get(Calendar.MONTH) -1); System.out.println (cal.getActualMaximum (Calendar.DAY_OF_MONTH));
Esencialmente, lo que hace es ponernos en 30 de marzo de este año y sacar por pantalla los siguientes datos:
- Fecha actual
- Número de días del mes de marzo
- Número de días del mes de… ¿febrero?
Java, en su excelsa sabiduría, ha decidido que en este caso que 2-1=2. Porque al restar uno al mes nos quedamos en 30 de febrero o, lo que es lo mismo, 2 de marzo. Esta chorrada (obviamente en un código más complejo) nos tuvo en el trabajo una mañana entretenidos porque el número de días de los meses siempre eran 30 ó 31, incluído un inexistente febrero.
En parte fue una suerte que estuviéramos a 30 de marzo y no en 2 de abril, en cuyo caso nos daríamos cuenta del problema casi un año después de sacar el proyecto a producción. A veces Java es realmente odioso con su “deja que la JVM piense por ti“.