Как преодолеть проблему с часовым поясом в Magento?

8

Я использовал этот метод , чтобы добавить указатель даты и времени в бэкэнд magento. Теперь время ввода правильно сохраняется в моей базе данных.

Проблема в том, что часовой пояс моего магазина magento установлен на стандартное индийское время (GMT + 05: 30), поэтому время, указанное в СЕТКЕ ADMIN, представляет собой входное значение времени (которое находится в базе данных) + 05:30 часов.

  • phpmyadmin view:

введите описание изображения здесь

время в базе данных: 7:15 и 7:52

  • Вид сетки в админке magento:

введите описание изображения здесь

время в админ 12:45 и 13:22

Это не беспокоит меня, так как таймер обратного отсчета, который я отображаю во внешнем интерфейсе, принимает значение, указанное в сетке администратора Я счастлив. Но при выборе времени в датчике время показывает время по Гринвичу, то есть время, сохраненное в базе данных.

введите описание изображения здесь введите описание изображения здесь

Таким образом, человек, который вводит ввод времени, должен ввести время, которое на 5:30 часов раньше запланированного времени.

Shathish
источник

Ответы:

13

при сохранении обновленной даты или созданной даты всегда используйте время gmt Mage::getModel('core/date')->gmtDate()

Фрэнк
источник
Привет @Marius Есть ли способ добавить время в сетке продуктов в magento2?
Навинбос
1

Поэтому, потратив почти день на борьбу с этой же проблемой в своем собственном дополнении, я решил поделиться своим решением здесь. Следует отметить, что мои объекты не используют систему EAV, у каждого объекта есть своя собственная плоская таблица со столбцом для каждого атрибута. Моя сущность имеет четыре атрибута datetime - два из которых заполняются из пользовательского ввода ( open_date, close_date), а два из них автоматически заполняются исходным кодом ( create_date, close_date).

Модель класса сущности

В класс модели объекта я включил следующее:

  1. Способ определить и выбрать, какие атрибуты относятся к типу datetime и заполняются с помощью введенных пользователем данных, предоставляемых по местному времени магазина.
  2. Метод, который преобразует только эти поля из времени по Гринвичу в местное время магазина (подробнее об этом позже).
  3. Метод _beforeSave (), который устанавливает для меня атрибуты 'edit_date' и 'create_date' (которые не заполняются через пользовательский ввод) в GMT автоматически при сохранении.

Исходный код:

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

SaveAction административного контроллера сущности

В методе saveAction моего контроллера я использовал метод getDateFields (), определенный в классе модели, чтобы узнать, какие атрибуты мне нужно изменить с локального времени магазина (которое было введено пользователем) на время по Гринвичу до сохранения в базе данных. Обратите внимание, что это только частичный фрагмент моего метода сохранения:

....

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

....

Блок административной формы для редактирования сущности

В отличие от виджета сетки администратора Magento, который ожидает, что значения времени и даты из коллекций будут предоставлены в GMT, с намерением преобразовать эти значения в местное время магазина до отображения страницы, виджет формы администратора Magento не соответствует этому поведению. Вместо этого виджет формы будет принимать значение даты и времени как есть и отображать его без автоматической настройки времени. Поэтому, поскольку значения хранятся в базе данных в GMT, мы должны сначала преобразовать введенные пользователем атрибуты datetime в местное время магазина, прежде чем предоставлять эти данные в форму. Вот тут-то и вступает в игру наш второй номер в классе моделей Entity .

Вот часть метода _prepareForm () класса блока моей формы администратора (который расширяет Mage_Adminhtml_Block_Widget_Form). Я опустил большую часть своей функции, пытаясь включить только тот минимум, который имеет отношение к этому вопросу, и по-прежнему предоставлять правильный метод класса:

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

Большая часть этого следует за любым другим виджетом формы для Magento. Однако, одна ключевая вещь, которую важно здесь отметить, это то, что вместо того, чтобы звонить, $form->setValues($model->getData())мы звоним $form->setValues($model->getAdminFormData()). Что, если мы рассмотрим мой код из первого сегмента этого ответа, этот метод берет преобразование всех атрибутов даты и времени, которые вводятся пользователем, из GMT в местное время магазина.

Конечный результат:

  1. Все значения сохраняются в БД по времени GMT.
  2. Введенные пользователем значения преобразуются из GMT в местное время магазина, прежде чем дать его для редактирования формы
  3. Сетка администратора работает как всегда, принимая значения по Гринвичу и конвертируя в местное время магазина до отображения сетки на странице.

Надеюсь, что это окажется ценным ресурсом, чтобы помочь кому-то еще там когда-нибудь. Настало время, когда вы работаете над интерфейсной разработкой, имейте в виду, что значения datetime находятся в GMT в БД!

Даррен Фелтон
источник
Этот ответ действительно хорош, но функция getAdminFormData () отсутствует в вашем примере кода. Не могли бы вы отредактировать ответ? Спасибо!
Wouter
@ Ваутер Хороший улов. Извините, getAdminFormData () был пользовательским методом, который в то время применялся только к моему расширению. Я думаю, что если я правильно помню, мне нужно было обработать некоторые данные только для административных форм. Для большинства всех сценариев просто $form->setValues($model->getData())должно быть.
Даррен Фелтон
Привет. Спасибо за хороший ответ! Кроме того, функция getAdminFormData()может иметь эту форму в модельном классеpublic 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(); }
Дмитрий Зар
-1

Вы можете проверить файл

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

И комментируйте следующие строки

CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS
CalendarDateObject._SERVER_TIMZEONE_SECONDS

Это должно сказать виджету использовать настройки браузера.

vovikha
источник
-1

Вы должны использовать правильный метод при добавлении поля даты, используя установочный файл mysql в 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();
Ричард Фераро
источник
1
Такие швы не имеют ничего общего с вопросом.
Мариус
Если вы знаете Magento, вы должны знать, что приведенный выше скрипт генерирует надлежащие HTML и JS для средства выбора даты в бэкэнде. Смотрите другие примеры [ forum.emthemes.com/…
Ричард Фераро
Точно ... но вопрос не имеет ничего общего с добавлением атрибута datetime к сущности продукта ... или, может быть, вы правы, и я должен выучить немного Magento ( подмигнул )
Marius
Вышеприведенная проблема вызвана неправильным форматом отображения средства выбора даты, поскольку оно показывает его с использованием другого смещения. Добавление приведенного ниже кода в соответствии с приведенным выше сценарием гарантирует, что отображение указателя даты синхронизируется с любым часовым поясом, установленным на веб-сайте / магазине Magento. 'backend' => 'eav/entity_attribute_backend_datetime', // this fixes your issue
Ричард Фераро
Я не могу с этим поспорить, но где в этом вопросе вы видите, что это связано с продуктами? Держу пари, что это пользовательская (не EAV) сущность. Так addAttributeчто здесь нет сил.
Мариус