Comment surmonter le problème de fuseau horaire dans Magento?

8

J'ai utilisé cette méthode pour ajouter un sélecteur de date et d'heure dans le backend de magento. Maintenant, le temps d'entrée est stocké correctement dans ma base de données.

Le problème est que le fuseau horaire de ma boutique magento est réglé sur l'heure standard indienne (GMT + 05: 30), donc l'heure affichée dans ADMIN GRID, est la valeur de l'heure d'entrée (qui est dans DataBase) + 05:30 heures.

  • vue phpmyadmin:

entrez la description de l'image ici

heure dans la base de données: 7h15 et 7h52

  • vue de la grille d'administration de magento:

entrez la description de l'image ici

heure en admin 12h45 et 13h22

Cela ne me dérange pas car le compte à rebours que j'affiche sur le frontend prend la valeur indiquée dans la grille d'administration. Je suis heureux. Mais lors de la sélection de l'heure dans le sélecteur d'heure de date, il affiche le GMT, c'est-à-dire l'heure stockée dans la base de données.

entrez la description de l'image ici entrez la description de l'image ici

Ainsi, la personne qui saisit l'entrée de temps doit entrer une heure qui est de 5h30 à l'avance par rapport à l'heure prévue.

Shathish
la source

Réponses:

13

lorsque vous enregistrez la date de mise à jour ou la date de création, utilisez toujours l'heure gmt Mage::getModel('core/date')->gmtDate()

Franc
la source
Salut @Marius Existe-t-il un moyen d'ajouter du temps GMT dans la grille des produits dans magento2?
Naveenbos
1

Donc, après avoir passé près d'une journée à lutter contre ce même problème dans ma propre extension, j'ai pensé partager ma solution ici. Quelque chose à noter est que mes entités n'utilisent pas le système EAV, chaque entité a sa propre table plate avec une colonne pour chaque attribut. Mon entité possède quatre attributs datetime, dont deux sont remplis à partir de l'entrée utilisateur ( open_date, close_date) et deux sont remplis automatiquement par le code source ( create_date, close_date).

Classe modèle de l'entité

Dans la classe de modèle de l'entité, j'ai inclus les éléments suivants:

  1. Un moyen de définir et de récupérer les attributs de type datetime et remplis via des données saisies par l'utilisateur fournies dans l'heure locale du magasin.
  2. Une méthode qui convertit uniquement ces champs de l'heure GMT à l'heure locale du magasin (plus d'informations à ce sujet plus tard).
  3. Une méthode _beforeSave () qui définit automatiquement pour moi les attributs 'edit_date' et 'create_date' (qui ne sont pas renseignés via les entrées utilisateur) dans GMT.

Le code source:

/**
 * 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;
}

L'action saveAction du contrôleur d'administration de l'entité

Dans la méthode saveAction de mon contrôleur, j'ai utilisé la méthode getDateFields () définie dans la classe de modèle pour savoir quels attributs je dois changer de l'heure locale du magasin (qui a été entrée par l'utilisateur) à l'heure GMT avant de l'enregistrer dans la base de données. Notez que ce n'est qu'un extrait partiel de ma méthode de sauvegarde:

....

$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();

....

Le bloc de formulaire d'administration pour modifier l'entité

Contrairement au widget de la grille d'administration de Magento, qui attend que les valeurs datetime des collections soient fournies dans GMT, avec l'intention de convertir ces valeurs en heure locale du magasin avant d'afficher la page, le widget de formulaire d'administration de Magento ne suit pas ce comportement. Au lieu de cela, le widget de formulaire acceptera la valeur datetime telle quelle et l'affichera sans ajuster automatiquement l'heure. Par conséquent, étant donné que les valeurs sont stockées dans la base de données au format GMT, nous devons d'abord convertir les attributs datetime entrés par l'utilisateur en heure locale du magasin avant de fournir ces données au formulaire. C'est là que notre n ° 2 sur la classe modèle de l'entité entre en jeu.

Voici une partie de la méthode _prepareForm () de la classe de bloc de mon formulaire d'administration (qui étend Mage_Adminhtml_Block_Widget_Form). J'ai omis la majorité de ma fonction, essayant d'inclure uniquement le strict minimum qui est pertinent pour cette question, et toujours fournir une méthode de classe valide:

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();
}

La plupart de ceci suit n'importe quel autre widget de formulaire pour Magento. Cependant, la chose clé qu'il est important de noter ici est que plutôt que d'appeler, $form->setValues($model->getData())nous appelons $form->setValues($model->getAdminFormData()). Ce qui, si nous examinons mon code du premier segment de cette réponse, cette méthode prend de convertir tous les attributs datetime, qui sont entrés par l'utilisateur, de GMT à l'heure locale du magasin.

Résultat final:

  1. Toutes les valeurs enregistrées dans DB en temps GMT.
  2. Les valeurs saisies par l'utilisateur sont converties de GMT en heure locale du magasin, avant de le donner pour modifier le formulaire
  3. La grille d'administration fonctionne comme elle l'a toujours fait, en prenant les valeurs GMT et en les convertissant à l'heure locale du magasin avant de rendre la grille sur la page.

J'espère que cela s'avérera une ressource précieuse pour aider quelqu'un d'autre un jour. Lorsque vous travaillez sur le développement frontal, n'oubliez pas que les valeurs datetime sont en GMT dans la base de données!

Darren Felton
la source
Cette réponse est vraiment bonne, mais la fonction getAdminFormData () n'est pas dans votre exemple de code. Pourriez-vous modifier la réponse? Merci!
Wouter
@Wouter Bonne prise. Désolé, "getAdminFormData ()" était une méthode personnalisée qui ne s'appliquait qu'à mon extension à l'époque. Je pense que si je me souviens bien, je devais traiter certaines données uniquement pour les formulaires d'administration. Pour la plupart, tous les scénarios $form->setValues($model->getData())devraient faire l'affaire.
Darren Felton
Bonjour. Merci pour la bonne réponse! De plus, la fonction getAdminFormData()peut avoir cette forme dans la classe de modèlepublic 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
-1

Vous pouvez vérifier le fichier

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

Et commenter les chaînes suivantes

CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS
CalendarDateObject._SERVER_TIMZEONE_SECONDS

Cela devrait indiquer au widget d'utiliser les paramètres du navigateur.

vovikha
la source
-1

Vous devez utiliser la méthode appropriée lors de l'ajout d'un champ de date à l'aide du fichier de configuration mysql sous Namespace> Module> 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
la source
1
Des coutures comme celle-ci n'ont rien à voir avec la question.
Marius
Si vous connaissez Magento, vous savez que le script ci-dessus génère le code HTML et JS approprié pour le sélecteur de date dans le backend. Voir d'autres exemples [ forum.emthemes.com/…
Richard Feraro
Exactement ... mais la question n'a rien à voir avec l'ajout d'un attribut datetime à l'entité produit ... ou peut-être avez-vous raison et je dois apprendre un peu Magento ( clin d'oeil clin d'oeil )
Marius
Le problème ci-dessus est dû au format d'affichage non valide du sélecteur de dates car il le montre en utilisant un décalage différent. L'ajout du code ci-dessous conformément au script ci-dessus garantira que l'affichage du sélecteur de date est synchronisé avec le fuseau horaire défini sur le site Web / magasin Magento. 'backend' => 'eav/entity_attribute_backend_datetime', // this fixes your issue
Richard Feraro
Je ne peux pas contester cela, mais où dans la question voyez-vous que cela est lié aux produits? Je parie que c'est une entité personnalisée (non EAV). N'a donc addAttributeaucun pouvoir ici.
Marius