Como superar o problema de fuso horário no Magento?

8

Eu usei esse método para adicionar seletor de data e hora no back-end do magento. Agora, o tempo de entrada está sendo armazenado no meu banco de dados corretamente.

O problema é que o fuso horário da minha loja magento está definido como Horário padrão da Índia (GMT + 05: 30); portanto, o horário mostrado no ADMIN GRID é o valor do tempo de entrada (que está no DataBase) + 05:30 horas.

  • Visualização phpmyadmin:

insira a descrição da imagem aqui

hora no banco de dados: 7:15 e 7:52

  • visualização da grade de administração do magento:

insira a descrição da imagem aqui

hora em admin 12:45 e 13:22

Isso não me incomoda, pois o cronômetro de contagem regressiva exibido no front-end assume o valor mostrado na grade do administrador. Eu estou feliz. Porém, ao selecionar a hora no selecionador de data e hora, ele mostra o GMT, ou seja, a hora armazenada no banco de dados.

insira a descrição da imagem aqui insira a descrição da imagem aqui

Portanto, a pessoa que inserir a entrada de tempo deve inserir um horário que seja 5:30 horas antes do horário pretendido.

Shathish
fonte

Respostas:

13

ao salvar a data atualizada ou a data criada, sempre use gmt time Mage::getModel('core/date')->gmtDate()

Frank
fonte
Oi @Marius Existe alguma maneira de adicionar tempo de GMT na grade do produto no magento2?
Naveenbos 26/10/19
1

Então, depois de passar quase um dia lutando com esse mesmo problema em minha própria extensão, pensei em compartilhar minha solução aqui. Algo a observar é que minhas entidades não estão utilizando o sistema EAV, cada entidade possui sua própria tabela plana com uma coluna para cada atributo. Minha entidade possui quatro atributos de data e hora - dois dos quais são preenchidos a partir da entrada do usuário ( open_date, close_date) e dois são preenchidos automaticamente pelo código-fonte ( create_date, close_date).

Classe de modelo da entidade

Na classe de modelo da entidade, incluí o seguinte:

  1. Uma maneira de definir e buscar quais atributos são do tipo datetime e são preenchidos por dados inseridos pelo usuário fornecidos no horário local da loja.
  2. Um método que converte apenas esses campos do horário GMT no horário local da loja (mais sobre isso posteriormente).
  3. Um método _beforeSave () que define os atributos 'edit_date' e 'create_date' (que não são preenchidos via entrada do usuário) no GMT automaticamente para mim, ao salvar.

O código fonte:

/**
 * Model's datetime attributes that are populated with user data supplied
 * in the store's local time.
 *
 * @var array
 */
protected $_dateFields = array(
    'open_date',
    'close_date',
);

/**
 * Return the model's datetime attributes that are populated with user
 * data supplied in the store's local time.
 *
 * @return array
 */
public function getDateFields()
{
    return $this->_dateFields;
}

/**
 * (non-PHPdoc)
 * @see Mage_Core_Model_Abstract::_beforeSave()
 */
protected function _beforeSave()
{
    parent::_beforeSave();

    $date = Mage::getModel('core/date')->gmtDate();
    if (!$this->getId()) {
        $this->setData('create_date', $date);
    }
    $this->setData('edit_date', $date);

    return $this;
}

O saveAction do Admin Controller da entidade

No método saveAction do meu controlador, utilizei o método getDateFields () definido na classe de modelo para saber quais atributos eu preciso alterar da hora local da loja (que foi inserida pelo usuário) para a hora GMT antes de salvar no banco de dados. Observe que este é apenas um trecho parcial do meu método de salvamento:

....

$data = $this->getRequest()->getPost()

// Convert user input time from the store's local time to GMT time
$dateFields = $model->getDateFields();
if (is_array($dateFields) && count($dateFields)) {

    $data           = $this->_filterDateTime($data, $dateFields);
    $store_timezone = new DateTimeZone(Mage::getStoreConfig('general/locale/timezone'));
    $gmt_timezone   = new DateTimeZone('Europe/London');

    foreach ($dateFields as $key) if (isset($data[$key])) {
        $dateTime = new DateTime($data[$key], $store_timezone);
        $dateTime->setTimezone($gmt_timezone);
        $data[$key] = $dateTime->format('Y-m-d H:i:s');
    }
}

$model->addData($data);

try {
    $model->save();

....

O bloco de formulário do administrador para editar a entidade

Ao contrário do widget de grade administrativa do Magento, que espera que os valores de data e hora das coleções sejam fornecidos no GMT, com a intenção de converter esses valores no horário local da loja antes de exibir a página, o widget de formulário administrativo do Magento não segue esse comportamento. Em vez disso, o widget de formulário aceitará o valor de data e hora como está e o exibirá sem ajustar automaticamente a hora. Portanto, como os valores são armazenados no banco de dados no GMT, primeiro devemos converter nossos atributos de data e hora inseridos pelo usuário no horário local da loja antes de fornecer esses dados ao formulário. É aqui que o nosso número 2 da classe Modelo da entidade entra em jogo.

Aqui está uma parte do método _prepareForm () da classe de bloco do meu formulário de administrador (que estende Mage_Adminhtml_Block_Widget_Form). Omiti a maioria da minha função, tentando incluir apenas o mínimo necessário para essa questão e ainda assim fornecer um método de classe válido:

protected function _prepareForm()
{
    $form           = new Varien_Data_Form();
    $model          = Mage::registry('YOUR_MODEL_CLASS');
    $date_format    = Mage::app()->getLocale()->getDateTimeFormat(Mage_Core_Model_Locale::FORMAT_TYPE_MEDIUM);
    $time_zone      = $this->__('Time Zone: %s', Mage::getStoreConfig('general/locale/timezone'));
    $calendar_img   = $this->getSkinUrl('images/grid-cal.gif');

    $fieldset = $form->addFieldset('base_fieldset', array('legend'=> $this->__('General Information')));

    $fieldset->addField('open_date', 'datetime', array(
        'name'     => 'open_date',
        'label'    => $this->__('Open Date'),
        'title'    => $this->__('Open Date'),
        'time'     => 'true',
        'image'    => $calendar_img,
        'format'   => $date_format,
        'style'    => 'width:160px',
        'required' => true,
        'note'     => $time_zone
    ));

    $fieldset->addField('close_date', 'datetime', array(
        'name'     => 'close_date',
        'label'    => $this->__('Close Date'),
        'title'    => $this->__('Close Date'),
        'time'     => 'true',
        'image'    => $calendar_img,
        'format'   => $date_format,
        'style'    => 'width:160px',
        'required' => true,
        'note'     => $time_zone
    ));

    if ($model->getId()) {
        $form->setValues($model->getAdminFormData());
    }

    $this->setForm($form);

    return parent::_prepareForm();
}

A maior parte disso segue qualquer outro widget de formulário para o Magento. No entanto, a principal coisa que é importante observar aqui é que, em vez de ligar $form->setValues($model->getData()), chamamos $form->setValues($model->getAdminFormData()). Que, se revisarmos meu código do primeiro segmento desta resposta, esse método leva a converter todos os atributos de data e hora, inseridos pelo usuário, de GMT para o horário local da loja.

Resultado final:

  1. Todos os valores salvos no DB no horário GMT.
  2. Os valores inseridos pelo usuário são convertidos de GMT para a hora local da loja, antes de serem editados para o formulário
  3. A grade do administrador funciona como sempre, recebendo valores GMT e convertendo para o horário local da loja antes de renderizar a grade na página.

Espero que isso seja um recurso valioso para ajudar alguém por aí algum dia. Na hora de trabalhar no desenvolvimento de front-end, lembre-se de que os valores de data e hora estão em GMT no DB!

Darren Felton
fonte
Esta resposta é realmente boa, mas a função getAdminFormData () não está no seu código de exemplo. Você pode editar a resposta? Obrigado!
Wouter
@ Wouter Boa captura. Desculpe, "getAdminFormData ()" era um método personalizado que se aplicava apenas à minha extensão no momento. Acho que, se me lembro corretamente, precisava processar alguns dados apenas para os formulários de administração. Para a maioria dos cenários, basta $form->setValues($model->getData())fazer.
Darren Felton
Olá. Obrigado pela boa resposta! Além disso, a função getAdminFormData()pode ter este formato na classe de modelopublic function getAdminFormData() { $dateAr = $this->getDateFields(); foreach ($dateAr as $date) { $loc_date = Mage::getModel('core/date')->date('Y-m-d H:i:s',($this->getData($date))); $this->setData($date,$loc_date); } return $this->getData(); }
ZMage 6/17/17
-1

Você pode verificar o arquivo

app/design/adminhtml/default/default/template/page/js/calendar.phtml

E comente as próximas strings

CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS
CalendarDateObject._SERVER_TIMZEONE_SECONDS

Isso deve informar ao widget para usar as configurações do navegador.

vovikha
fonte
-1

Você deve usar o método apropriado ao adicionar um campo de data usando o arquivo de configuração do mysql em Namespace> Módulo> sql> module_setup> mysql4-install / upgrade-xxxphp :

<?php
$installer = $this;
$installer->startSetup();

$installer->addAttribute(
    'catalog_product',
    'custom_datetime',
    array(
        'label'         => 'Custom DateTime', // modify this
        'required'      => false,
        'type'          => 'datetime',
        'input'         => 'date',
        'backend'       => 'eav/entity_attribute_backend_datetime', // this fixes your issue
        'global'        => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
        'visible_on_front' => 1,
        'position'      => 1,
        'time'          => true,
        'group'         => 'General', // modify this
        'sort_order'    => 23,  // modify this
    )
);

$installer->endSetup();
Richard Feraro
fonte
11
Costuras como essa não têm nada a ver com a questão.
Marius
Se você conhece o Magento, deve saber que o script acima gera o HTML e JS adequados para o datepicker no back-end. Veja outros exemplos [ forum.emthemes.com/…
Richard Feraro
Exatamente ... mas a questão não tem nada a ver com a adição de um atributo datetime à entidade do produto ... ou talvez você esteja certo e eu tenho que aprender um pouco sobre Magento ( wink wink )
Marius
O problema acima é causado pelo formato de exibição inválido do datepicker, porque mostra um deslocamento diferente. A adição do código abaixo, conforme o script acima, garantirá que a exibição do datepicker esteja sincronizada com o fuso horário definido no site / loja Magento. 'backend' => 'eav/entity_attribute_backend_datetime', // this fixes your issue
Richard Feraro
Não posso argumentar com isso, mas onde você vê que isso está relacionado a produtos? Minha aposta é que essa é uma entidade personalizada (não EAV). Então addAttributenão tem poder aqui.
Marius