Wie kann man das Zeitzonenproblem in Magento überwinden?

8

Ich habe diese Methode verwendet , um die Datums- und Zeitauswahl im Magento-Backend hinzuzufügen. Jetzt wird die Eingabezeit korrekt in meiner Datenbank gespeichert.

Das Problem ist, dass die Zeitzone meines Magento-Geschäfts auf die indische Standardzeit (GMT + 05: 30) eingestellt ist. Die in ADMIN GRID angezeigte Zeit ist also der Eingabezeitwert (in der Datenbank) + 05:30 Uhr.

  • phpmyadmin Ansicht:

Geben Sie hier die Bildbeschreibung ein

Zeit in der Datenbank: 7:15 Uhr und 7:52 Uhr

  • Magento Admin Grid View:

Geben Sie hier die Bildbeschreibung ein

Zeit in Admin 12:45 Uhr und 13:22 Uhr

Dies stört mich nicht, da der Countdown-Timer, den ich im Frontend anzeige, den im Admin-Raster angezeigten Wert annimmt. Ich bin froh. Bei Auswahl der Uhrzeit in der Datums- und Uhrzeitauswahl wird jedoch die GMT angezeigt, dh die in der Datenbank gespeicherte Uhrzeit.

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Daher sollte die Person, die die Zeiteingabe eingibt, eine Zeit eingeben, die 5:30 Stunden vor der beabsichtigten Zeit liegt.

Shathish
quelle

Antworten:

13

Wenn Sie das aktualisierte Datum oder das Erstellungsdatum speichern, verwenden Sie immer gmt time Mage::getModel('core/date')->gmtDate()

Frank
quelle
Hi @Marius Gibt es eine Möglichkeit, gmt time in magento2 in das Produktraster aufzunehmen?
Naveenbos
1

Nachdem ich fast einen Tag damit verbracht hatte, mit demselben Problem in meiner eigenen Erweiterung zu kämpfen, dachte ich, ich würde meine Lösung hier teilen. Zu beachten ist, dass meine Entitäten das EAV-System nicht verwenden. Jede Entität verfügt über eine eigene flache Tabelle mit einer Spalte für jedes Attribut. Meine Entität verfügt über vier Datums- / Uhrzeitattribute, von denen zwei aus Benutzereingaben ( open_date, close_date) und zwei automatisch aus dem Quellcode ( create_date, close_date) ausgefüllt werden .

Die Modellklasse der Entität

In die Modellklasse der Entität habe ich Folgendes aufgenommen:

  1. Eine Möglichkeit, zu definieren und abzurufen, welche Attribute vom Typ datetime sind und über vom Benutzer eingegebene Daten in der Ortszeit des Geschäfts ausgefüllt werden.
  2. Eine Methode, die nur diese Felder von der GMT-Zeit in die Ortszeit des Geschäfts konvertiert (dazu später mehr).
  3. Eine _beforeSave () -Methode, die die Attribute 'edit_date' und 'create_date' (die nicht über Benutzereingaben ausgefüllt werden ) in GMT für mich beim Speichern automatisch festlegt .

Der Quellcode:

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

Die saveAction des Admin Controllers der Entität

In der saveAction-Methode meines Controllers habe ich die in der Modellklasse definierte getDateFields () -Methode verwendet, um zu wissen, welche Attribute ich von der Ortszeit des Geschäfts (die vom Benutzer eingegeben wurde) zur GMT-Zeit ändern muss, bevor ich sie in der Datumsbasis speichere. Beachten Sie, dass dies nur ein Teil meiner Speichermethode ist:

....

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

....

Der Admin-Formularblock zum Bearbeiten der Entität

Im Gegensatz zum Admin-Grid-Widget von Magento, das erwartet, dass Datums- / Uhrzeitwerte aus Sammlungen in GMT bereitgestellt werden, mit der Absicht, diese Werte vor dem Anzeigen der Seite in die Ortszeit des Geschäfts zu konvertieren, folgt das Admin-Formular-Widget von Magento diesem Verhalten nicht. Stattdessen akzeptiert das Formular-Widget den Datum / Uhrzeit-Wert unverändert und zeigt ihn an, ohne die Zeit automatisch anzupassen. Da die Werte in GMT in der Datenbank gespeichert sind, müssen wir zuerst die vom Benutzer eingegebenen datetime-Attribute in die Ortszeit des Geschäfts konvertieren, bevor wir diese Daten an das Formular senden. Hier kommt unsere Nummer 2 in der Modellklasse von The Entity ins Spiel.

Hier ist ein TEIL der _prepareForm () -Methode der Blockklasse meines Administratorformulars (die Mage_Adminhtml_Block_Widget_Form erweitert). Ich habe den größten Teil meiner Funktion weggelassen und versucht, nur das absolute Minimum einzubeziehen, das für diese Frage relevant ist, und trotzdem eine gültige Klassenmethode bereitzustellen:

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

Das meiste davon folgt jedem anderen Formular-Widget für Magento. Das Wichtigste, was hier zu beachten ist, ist jedoch, dass $form->setValues($model->getData())wir nicht anrufen , sondern anrufen $form->setValues($model->getAdminFormData()). Wenn wir meinen Code aus dem ersten Segment dieser Antwort überprüfen, konvertiert diese Methode alle vom Benutzer eingegebenen Datums- / Uhrzeitattribute von GMT in die Ortszeit des Geschäfts.

Endresultat:

  1. Alle Werte werden in GMT-Zeit in der DB gespeichert.
  2. Vom Benutzer eingegebene Werte werden von GMT in die Ortszeit des Speichers konvertiert, bevor das Formular bearbeitet wird
  3. Das Admin-Raster funktioniert wie immer, nimmt GMT-Werte auf und konvertiert in die Ortszeit des Geschäfts, bevor das Raster auf der Seite gerendert wird.

Ich hoffe, dies ist eine wertvolle Ressource, um eines Tages jemand anderem da draußen zu helfen. Wenn Sie an der Front-End-Entwicklung arbeiten, denken Sie daran, dass die Datums- / Uhrzeitwerte in der Datenbank in GMT angegeben sind!

Darren Felton
quelle
Diese Antwort ist wirklich gut, aber die Funktion getAdminFormData () befindet sich nicht in Ihrem Beispielcode. Könnten Sie die Antwort bearbeiten? Vielen Dank!
Wouter
@Wouter Guter Fang. Entschuldigung, "getAdminFormData ()" war eine benutzerdefinierte Methode, die zu diesem Zeitpunkt nur auf meine Erweiterung angewendet wurde. Ich denke, wenn ich mich richtig erinnere, musste ich einige der Daten nur für die Administrationsformulare verarbeiten. Für die meisten $form->setValues($model->getData())sollten Szenarien einfach reichen.
Darren Felton
Hallo. Danke für die gute Antwort! Darüber hinaus kann Funktion getAdminFormData()diese Form in der Modellklasse habenpublic 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

Sie können die Datei überprüfen

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

Und kommentiere die nächsten Saiten

CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS
CalendarDateObject._SERVER_TIMZEONE_SECONDS

Das sollte das Widget anweisen, Browsereinstellungen zu verwenden.

vovikha
quelle
-1

Sie sollten die richtige Methode verwenden, wenn Sie ein Datumsfeld mithilfe der MySQL-Setup-Datei unter Namespace> Modul> SQL> Modul-Setup> MySQL-Installation / Upgrade-xxxphp hinzufügen :

<?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
quelle
1
Nähte wie diese haben nichts mit der Frage zu tun.
Marius
Wenn Sie Magento kennen, wissen Sie, dass das obige Skript das richtige HTML und JS für den Datepicker im Backend generiert. Siehe andere Beispiele [ forum.emthemes.com/…
Richard Feraro
Genau ... aber die Frage hat nichts zu mit einem Datetime - Attribut auf die Produktentität Hinzufügen ... oder vielleicht haben Sie recht , und ich muss einige Magento (weitere wink wink )
Marius
Das obige Problem wird durch das ungültige Anzeigeformat des Datumsauswahlgeräts verursacht, da es mit einem anderen Versatz angezeigt wird. Durch Hinzufügen des folgenden Codes gemäß dem obigen Skript wird sichergestellt, dass die Anzeige des Datepickers mit der auf der Magento-Website / dem Magento-Store festgelegten Zeitzone synchronisiert ist. 'backend' => 'eav/entity_attribute_backend_datetime', // this fixes your issue
Richard Feraro
Ich kann damit nicht streiten, aber wo in der Frage sehen Sie, dass dies mit Produkten zusammenhängt? Ich wette, dass dies eine benutzerdefinierte Entität (Non EAV) ist. Hat addAttributehier also keine Macht.
Marius