如何克服Magento中的时区问题?


8

我使用此方法在magento后端中添加了日期和时间选择器。现在,输入时间已正确存储到我的数据库中。

问题是我的magento商店的时区设置为印度标准时间(GMT + 05:30),所以ADMIN GRID中显示的时间是输入时间值(在数据库中)+ 05:30 Hrs。

  • phpmyadmin视图:

在此处输入图片说明

数据库中的时间:上午7:15和上午7:52

  • magento管理员网格视图:

在此处输入图片说明

在管理员中的时间12:45 pm和1:22 pm

这并不困扰我,因为我在前端显示的倒数计时器采用了管理网格中显示的值。我很高兴。但是,当选择日期时间选择器中的时间时,它将显示GMT,即存储在数据库中的时间。

在此处输入图片说明 在此处输入图片说明

因此,输入时间输入的人应该输入比预期时间早5:30的时间。

Answers:


13

当您保存更新日期或创建日期时,始终使用格林尼治标准时间 Mage::getModel('core/date')->gmtDate()


嗨,@ Marius,您是否有办法在magento2的产品网格中添加gmt时间?
Naveenbos

1

因此,在将自己的扩展程序花了整整一天的时间来解决这个问题之后,我想在这里分享我的解决方案。需要注意的是,我的实体没有使用EAV系统,每个实体都有自己的平面表,每个属性都有一列。我的实体具有四个datetime属性-其中两个是通过用户输入(open_dateclose_date)填充的,其中两个是由源代码(create_dateclose_date)自动填充的。

实体的模型类

在实体的模型类中,我包括以下内容:

  1. 一种方法来定义和获取什么属性是datetime类型,并通过在店里的本地时间提供用户输入的数据进行填充。
  2. 一种仅将这些字段从GMT时间转换为商店本地时间的方法(稍后会对此进行详细介绍)。
  3. _beforeSave()方法会在保存时自动为我设置GMT中的'edit_date'和'create_date'属性(通过用户输入填充)。

源代码:

/**
 * 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()方法来知道在保存到日期数据库之前需要从商店的本地时间(用户输入的时间)更改为GMT时间的哪些属性。请注意,这只是我的save方法的部分片段:

....

$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的管理表单小部件不遵循此行为。相反,表单小部件将按原样接受datetime值,并在不自动调整时间的情况下显示它。因此,由于值存储在GMT的数据库中,因此在将数据提供给表单之前,我们必须先将用户输入的datetime属性转换为商店的本地时间。这就是我们在实体模型类中排名第二的地方。

这是我的管理表单的块类的_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时间保存到DB中。
  2. 用户输入的值从GMT转换为商店的本地时间,然后再进行编辑
  3. 管理网格一如既往地工作,在页面上呈现网格之前,先获取GMT值并转换为商店的本地时间。

希望这被证明是有一天可以帮助别人的宝贵资源。来进行前端开发的时候了,请记住,日期时间值在数据库中的GMT中!


这个答案确实很好,但是示例代码中没有函数getAdminFormData()。您可以编辑答案吗?谢谢!
Wouter

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

-1

您可以检查文件

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

并评论下一个字符串

CalendarDateObject._LOCAL_TIMZEONE_OFFSET_SECONDS
CalendarDateObject._SERVER_TIMZEONE_SECONDS

那应该告诉小部件使用浏览器设置。


-1

使用名称空间>模块> sql> module_setup> mysql4-install / upgrade-xxxphp下的mysql安装文件添加日期字段时,应使用正确的方法:

<?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这里没有权力。
Marius
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.