jueves, 6 de febrero de 2014

Ax2012, Fechas UTC y DateTimeUtil

Esta versión de Ax ha incorporado un nuevo mecanismo de validez temporal (date effectiveness) de los registros, permitiendo en las tablas añadir este mecanismo para mantener la información pasada, presente y futura, sin conflicto entre ellas.

Este nuevo mecanismo almacena las fechas en formato UTC, y hemos de tener muy presente este aspecto si no queremos llevarnos sorpresas, ya que la función validTimeState trabaja con las fechas UTC.

Ejemplo: Si estamos en España e introducimos como valor inicial de un registro 01/04/2013 10:10:10, el sistema almacenará en SQL 01/04/2013 08:10:10 (dos horas menos), aunque siempre nos mostrará la primera en formularios e informes, ya que aplica la diferencia horaria.

Los problemas pueden venir por dos vías:
  1. Si leemos la tabla directamente en SQL y no tratamos el valor de fecha, nos parecerá que el registro entró en vigor a las 08:10:10.
  2. Si accedemos vía x++ pero construimos la fecha y hora por código para la función validTimeState y no la pasamos a UTC, podemos estar leyendo una información incorrecta.
Para clarificar el problema y conocer las funciones que nos ayudarán a trabajar con fecha UTC tengo preparado el siguiente JOB:

static void GCC_ValidezTemporal(Args _args)
{
    utcDateTime             utcDatetimeUsr,utcDatetimeUTC;    
    date                    _date;
    TimeOfDay               _time;    
    int                     timezoneOffset;
    
    ;
    info(strFmt("Fecha UTC mínima: %1 (no se representa pero es 1900-01-01T00:00:00) y máxima: %2",DateTimeUtil::minValue(),DateTimeUtil::maxValue()));
    
    utcDatetimeUsr = str2datetime("01/04/2013 10:10:10",123);
    utcDatetimeUTC =  DateTimeUtil::newDateTime(DateTimeUtil::date(utcDatetimeUsr),DateTimeUtil::time(utcDatetimeUsr),DateTimeUtil::getCompanyTimeZone());
    timezoneOffset = DateTimeUtil::getTimeZoneOffset(utcDatetimeUsr,DateTimeUtil::getCompanyTimeZone());    
    info(strFmt("Fecha para el usuario: %1, Fecha UTC: %2, Offset: %3", utcDatetimeUsr,utcDatetimeUTC,timezoneOffset));
    
    utcDatetimeUsr = str2datetime("31/12/2013 10:10:10",123);
    utcDatetimeUTC =  DateTimeUtil::newDateTime(DateTimeUtil::date(utcDatetimeUsr),DateTimeUtil::time(utcDatetimeUsr),DateTimeUtil::getCompanyTimeZone());
    timezoneOffset = DateTimeUtil::getTimeZoneOffset(utcDatetimeUsr,DateTimeUtil::getCompanyTimeZone());    
    info(strFmt("Fecha para el usuario: %1, Fecha UTC: %2, Offset: %3", utcDatetimeUsr,utcDatetimeUTC,timezoneOffset));
    
    _date = mkDate(01,04,2013);
    utcDatetimeUsr = DateTimeUtil::newDateTime(_date,_time);
    info(strFmt("Fecha creada desde DMY (la que el usuario ve): %1",utcDatetimeUsr));
    utcDatetimeUsr =  DateTimeUtil::newDateTime(DateTimeUtil::date(utcDatetimeUsr),DateTimeUtil::time(utcDatetimeUsr),DateTimeUtil::getCompanyTimeZone());
    info(strFmt("Su correspondiente UTC: %1",utcDatetimeUsr));    
    utcDatetimeUsr = DateTimeUtil::applyTimeZoneOffset(utcDatetimeUsr,DateTimeUtil::getCompanyTimeZone());
    info(strFmt("Volvemos a la fecha según la ve el usuario: %1",utcDatetimeUsr));        
}

No hay comentarios:

Publicar un comentario