miércoles, 29 de diciembre de 2010

Fechas con un día menos en Flex y Java usando BlazeDS

   Cuando trabajamos con fechas en entornos con Flex y Java debemos tener cuidado de un curioso efecto, al cargar una fecha correcta en Java en Flex puede verse con un día menos.

   Este efecto se debe a como son transferidas las fechas entre un servidor Java y un cliente Flex, para ello se serializa la fecha en UTC, es decir sin información de la zona horaria. La conversión a la hora local se realiza a nivel del protocolo de forma automática, por lo tanto si el servidor no conoce la zona horaria del cliente no podrá transformarla adecuadamente. Dependiendo de la aplicación puede ser deseable almacenar/recuperar los datos en la zona horaria del cliente que los guarda, pero en la mayoría de los casos no lo es.

La solución (tal como se indica en el CookBook de Flex) consiste en forzar que la fecha se intercambie sin la información de la zona horaria. Para ello modificaremos los métodos accesores (getters y setters) de las fechas tanto del objeto java, como en el objeto en actionscript de forma que intercambiemos la fecha como el numero de milisegundos desde 1970 menos la cantidad añadida por la zona horaria (para que la trate como en GMT+0). Los objetos quedarían  así:
Java
package com.fraguaDigital;
 
import java.io.Serializable;
import java.util.Date;
import java.util.TimeZone;
 
public class MiClase implements Serializable {

    // ... Otros atributos ...
 
 private Date _fecha;
 public Date getFecha() {
  Date newDate = new Date(_fecha.getTime() - TimeZone.getDefault().getOffset(_fecha.getTime()));
  return newDate;
 }
 public void setFecha(Date value) {
  Date newDate = new Date(value.getTime() + TimeZone.getDefault().getOffset(value.getTime()));
  this._fecha = newDate;
 }
}

ActionScript (Flex)
package com.fraguaDigital
{
 [RemoteClass(alias="com.fraguaDigital.MiClase")]
 public class MiClase
 {
     // ... Otros atributos ...
  
  public var _fecha:Date;
  public function set fecha(value:Date):void {
   var newDate:Date = new Date(value.valueOf() - value.timezoneOffset);
   this._fecha = newDate;
  }
  
  public function get fecha():Date {
   var newDate:Date = new Date(_fecha.valueOf() + _fecha.timezoneOffset);
   return newDate;
  }
 }
}

Con esto ya las fechas llegarán correctamente al cliente.