La programación Javascript a veces tiene esas perlas incomprensibles a primera vista que hasta que no caes en éso te lleva por el camino de la amargura.
La última es mientras trabajaba con el objeto Date(). Por objeto entendemos que tiene unos atributos para guardar información y unos métodos para realizar acciones, mayoritariamente trabajos con los atributos. Puede que sea la costumbre, pero la forma de trabajar de éste en particular me ha hecho, almenos, sonreir
Pongamos que necesitamos una función para convertir una fecha de formato dd-mm-YYYY a un valor timestamp. Por suerte tenemos el objeto Date() que nos facilita enormemente el trabajo. Sólo le tenemos que dar el instante en el tiempo en formato humano y él nos lo devuelve en formato numérico
Además, es tan versátil que si no le pasamos el instante en el tiempo, el toma "ahora" como valor de entrada, así que podemos jugar a declarar el objeto y luego asignarle los valores de día, mes, ... Veamos como sería una función típica (los puristas y los "yo lo haría mejor" me perdonen):
JAVASCRIPT:
-
function getTimestamp(fecha_dd_mm_yyyy)
-
{
-
var dia_aux = parseInt(fecha_dd_mm_yyyy.substring(0, 2),10);
-
var mes_aux = parseInt(fecha_dd_mm_yyyy.substring(3, 5),10);
-
var ano_aux = parseInt(fecha_dd_mm_yyyy.substring(6, 10),10);
-
var fecha = new Date();
-
fecha.setDate(dia_aux);
-
fecha.setMonth(mes_aux-1);
-
fecha.setFullYear(ano_aux);
-
fecha.setHours(0);
-
fecha.setMinutes(0);
-
fecha.setSeconds(0);
-
fecha.setMilliseconds(0);
-
var timestamp = parseInt(fecha.getTime(),10);
-
-
return timestamp;
-
}
El flujo es fácil. Se toma la variable string de entrada y se desmembra en el día , mes y año. Luego creamos el objeto Date() y luego le asignamos los valores. Los valores que no tenemos los setamos a cero, pero se pueden omitir, caso en que el sistema cojerá los del instante actual. Luego devolvemos el timestamp y lo retornamos de vuelta. Fácil no?
Esta es una función que funciona en todos los casos... mmm... pues no. Si probamos, por ejemplo, la cadena de entrada '29-04-2007' nos encontramos que el valor de salida corresponde al 1 de abril, en vez del 29 de abril. A continuación os pongo el código para tener una prueba:
JAVASCRIPT:
-
function getTimestamp(fecha_dd_mm_yyyy)
-
{
-
var dia_aux = parseInt(fecha_dd_mm_yyyy.substring(0, 2),10);
-
var mes_aux = parseInt(fecha_dd_mm_yyyy.substring(3, 5),10);
-
var ano_aux = parseInt(fecha_dd_mm_yyyy.substring(6, 10),10);
-
var fecha = new Date();
-
fecha.setDate(dia_aux);
-
fecha.setMonth(mes_aux-1);
-
fecha.setFullYear(ano_aux);
-
fecha.setHours(0);
-
fecha.setMinutes(0);
-
fecha.setSeconds(0);
-
fecha.setMilliseconds(0);
-
var timestamp = parseInt(fecha.getTime(),10);
-
-
var pepe = new Date(timestamp);
-
alert(timestamp+', '+fecha.getTime()+', '+pepe.getDate()+'-'+(pepe.getMonth()+1)+'-'+pepe.getFullYear());
-
-
return timestamp;
-
}
Curioso, no? Pues bién, ésta ha sido mi comida de neuronas durante un par de horas... hasta que mi compañero Javi ha dado con una explicación válida.
Resulta que declarando el objeto Date() así, sin parámetros, toma el instante "ahora" como sabemos. Entonces rellena los atributos con los valores pertinentes (para que el ejemplo funcione pongamos que estamos en Febrero), pero al setar el primer valor, el día, él consulta si el día cuadra con lo que tiene ya guardado y si no recalcula la fecha que contiene. Veámoslo mejor con un ejemplo:
Hoy es 2 de Febrero del 2007. Al ejecutarse:
var fecha = new Date();
se guarda en el interior que el día es 2, el mes es 1 (recordemos que la fecha empieza por 0) y el año es 2007. Cuando setamos el día (29):
fecha.setDate(dia_aux);
tenemos que estamos intentando setar la fecha 29/2/2007, que como el 2007 no es bisiesto, se recalcula a 1/3/2007. Entonces, el resto de las instrucciones setan el resto de valores con lo que al final tenemos la fecha 1/4/2007. Si probamos la función con la fecha de entrada '30-04-2007', obtendremos el timestamp perteneciente al 2/4/2007.
Así que la solución pasa por cambiar el orden del setado de valores: primero el año, luego el mes y luego el día:/p>
JAVASCRIPT:
-
function getTimestamp(fecha_dd_mm_yyyy)
-
{
-
var dia_aux = parseInt(fecha_dd_mm_yyyy.substring(0, 2),10);
-
var mes_aux = parseInt(fecha_dd_mm_yyyy.substring(3, 5),10);
-
var ano_aux = parseInt(fecha_dd_mm_yyyy.substring(6, 10),10);
-
var fecha = new Date();
-
fecha.setFullYear(ano_aux);
-
fecha.setMonth(mes_aux-1);
-
fecha.setDate(dia_aux);
-
fecha.setHours(0);
-
fecha.setMinutes(0);
-
fecha.setSeconds(0);
-
fecha.setMilliseconds(0);
-
var timestamp = parseInt(fecha.getTime(),10);
-
-
return timestamp;
-
}
Debo decir que no es la única forma de solucionar el problema. De hecho, hay una forma bastante más elegante, que justamente es la que se debería usar...
Se trata de declarar la fecha directamente al crear al objeto. Lo que pasa es que soy nulo en recordar el orden de los parámetros y acabo usando los set's... quién iva a pensar que se recalculaban en el set...
Salud!
Escribe un Comentario