Magento: el problema de las fechas

2016-08-03 - Categorías: Magento / PHP
Magento el problema de las fechas

Hola de nuevo. Esta semana he seguido avanzando sobre todo esto de Magento. Creando unos trabajos de cron, después de haber probado las tareas cron a ejecutar mediante scripts externos a Magento. Me he encontrado con que las fechas no me funcionaban como yo esperaba dando malos resultados.

Probando probando, llegué a la conclusión de que tratando las fechas mediante cadenas de caracteres podía aplicarles las modificaciones que necesitaba.

El origen del problema

Magento internamente trabaja los objetos poniéndoles una fecha de creación de acuerdo con la fecha GMT, el tiempo medio de Greenwich. Es casi sinónimo del UTC, tiempo universal coordinado, a las finales resulta en lo mismo.

Vamos a probar con los pedidos. Tenemos un pedido que se guarda en la BD con el tiempo GMT. Mediante script lo comprobamos:

$ordersCollection = Mage::getModel('sales/order')->getCollection();
$lastOrder = $ordersCollection->getLastItem();
echo 'Fecha del último pedido ('.$lastOrder->getIncrementId().'): '.$lastOrder->getCreatedAt().$nline;

Con esto podemos tener un resultado como el siguiente:

Fecha del último pedido (P00032358): 2016-07-28 12:23:54

Sin embargo si vamos al backend de Magento y vemos la fecha que figura en el pedido resulta que pone 28/7/2016 14:23:54. Esto es normal, internamente Magento le pone la fecha GMT a todo, para luego en la visualización de dichas fechas ponerle la hora concreta según lo que hayamos configurado en el panel de control. Esto nos puede llevar a confusión a no ser que trabajemos en la hora GMT y entonces las fechas que vemos son las que realmente tenemos guardadas en la base de datos. En mi caso tengo configurada la hora de Madrid:

Magento timezone configuration

Que supone que todo el rato, cada vez que se pinta una hora GMT en Magento, lo que pinta es la hora guardada sumándole 2 horas.

El problema

El problema  viene  en el momento en que quieres filtrar entre fechas, teniendo en cuenta las horas y minutos. Cuando quieres precisar tienes que tener en cuenta que debes de filtrar teniendo en cuenta que la hora del sistema, o tu hora local, no son las fechas y horas que valen de verdad. No son las mismas fechas las que se guardan en la base de datos y las que ves.

En mi caso este desfase de 2 horas con la hora de la timezone Europe/Madrid me estaba complicando mucho el problema para filtrar los pedidos de los que habían pasado 15 minutos.

La solución

La solución definitiva es trabajar con la hora GMT para enviar a filtrar. En este caso para trabajar las fechas usando lo siguiente debería de funcionar para todos los casos:

$magentoDate = Mage::getModel('core/date')->gmtDate();
$startDate = date('Y-m-d H:i:s', strtotime($magentoDate.' -1 day'));
$endDate = date('Y-m-d H:i:s', strtotime($magentoDate.' -15 minutes'));

echo 'Fecha del core de Magento: '.$magentoDate.$nline;
echo 'Fecha inicial: '.$startDate.$nline;
echo 'Fecha final: '.$endDate.$nline;

Aquí lo que se hace es obtener la cadena de tiempo del core de Magento, en formato estándar y con la hora GMT. A partir de aquí, con la función strtotime se hace una operación de modificación sobre dicha fecha. A la vez se convierte la fecha modificada para convertirla al formato de Magento fecha-hora, que es estándar precisamente:

Y-m-d H:i:s

Que es: año-mes-dia hora:minutos:segundos

Para el caso de los pedidos, tenemos que con el siguiente código pedimos los pedidos desde hace 1 día hasta hace 15 minutos:

$ordersCollection = Mage::getModel('sales/order')->getCollection()
    ->addFieldToFilter('created_at', array(
        'from' => $startDate,
        'to' => $endDate,
    ));
echo 'Total de pedidos: '.$ordersCollection->count().$nline

Si lo que queremos son los productos entre dichas fechas sería así:

$productCollection = Mage::getModel('catalog/product')->getCollection()
    ->addFieldToFilter('created_at', array(
        'from' => $startDate,
        'to' => $endDate,
    ));
echo 'Total de productos: '.$productCollection->count().$nline;

Con los clientes creados entre fechas:

$customerCollection = Mage::getModel('customer/customer')->getCollection()
    ->addFieldToFilter('created_at', array(
        'from' => $startDate,
        'to' => $endDate,
    ));
echo 'Total de clientes: '.$customerCollection->count().$nline;

De igual forma podemos consultar cualquier objeto de Magento que tenga fechas preparandolas así. En estos casos, hemos consultado el atributo created_at.

Preparando la fecha manualmente

Para terminar, sólo queda cómo preparar una fecha precisa, manualmente. Por ejemplo, si queremos consultar todos los pedidos del año, podemos preparar las fechas desde y hasta simplemente así:

$startDate = '2016-01-01 00:00:00';
$endDate = '2016-12-31 23:59:59';

Sí, lo sé, no es más que una cadena, que por lo menos, en Magento 1.9.2.4 podemos pasarle al from y to del filtro de las colecciones. No olvides tener en cuenta que siempre las fechas a filtrar serán fechas en GMT, no las fechas con horas de tu configuración. En mi caso de la zona horaria Europe/Madrid, tendré que mover 2 horas la franja horaria de inicio y final, restándole 2 horas para que coincida con las fechas que yo veo tanto en back-end como en front-end.

$startDate = '2015-12-31 22:00:00';
$endDate = '2016-12-31 21:59:59';

Espero que sirva.

Un saludo.

4 respuestas a “Magento: el problema de las fechas”

  1. Yeison dice:

    Hola tengo mismo problema con la versión 2.2.6 sabes de alguna solución?

    • Jnj dice:

      Hola Yeison!

      En Magento 2 la solución debería ser seguir la misma idea. Hay que tener en cuenta las horas de diferencia GMT con la zona horaria en donde tengas configurado Magento. Por ejemplo, para el caso de Perú hay 5 horas de diferencia con la hora GMT a día de hoy. Un código de consulta de pedidos para sacar todos los pedidos de hoy puede ser el siguiente:

      $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
      $ordersCollection = $this->_objectManager->get(‘Magento\Sales\Model\Order’)->getCollection()
      ->addAttributeToFilter(‘created_at’, array(
      ‘from’ => ‘2019/09/18 5:00:00’,
      ‘to’ => ‘2019/09/19 4:59:59’,
      ));

      Con las funciones de fecha de PHP no debería de ser muy complicado calcular las fechas que necesites. Con las funciones del post, donde se usa el strtotime te puede ahorrar muchos quebraderos de cabeza porque simplemente le dices que sume o reste..

      $startDate = date(‘Y-m-d H:i:s’, strtotime($magentoDate.’ -1 day’));

      Las cadenas de fecha de la forma ‘2019-09-19 4:59:59’ no las he probado, pero quizá se puede usando:

      $startDate = date(‘Y/m/d H:i:s’, strtotime($magentoDate.’ -1 hour’));

      Espero haberte podido ayudar.. Un saludo!

  2. Daren Morie dice:

    Saved as a favorite!, I like your website!

Responder a Jnj Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

© 2024 JnjSite.com - MIT license

Sitio hecho con WordPress, diseño y programación del tema por Jnj.