3

I'm getting very confused here. I made a module which has an adminhtml form which contains a date field. I'm adding it like this:

    $quotaFieldset->addField(
        'quota_expiry',
        'date',
        [
          'name' => 'quota_expiry',
          'label' => __('Quota Expiry Date'),
          'title' => __('Quota Expiry Date'),
          'required' => false,
          'date_format' => $this->_localeDate->getDateFormat(),
          'input_format' => \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT,
          'time' => false,
          'disabled' => false
        ]
    );

So far this has worked well. But now I have deployed my application to another server, and suddenly (I know this from debug logs) the string returned from $this->_localeDate->getDateFormat() is now "dd/MM/y" instead of "M/d/yy" like on my development machine.

Because of that, when I use the popup calendar to select a date, it would fill in "29/04/2016" which then gives following exception when I save the model:

DateTime::__construct(): Failed to parse time string (29/04/2016) at position 0 (2): Unexpected character
#0 .../lib/internal/Magento/Framework/Stdlib/DateTime.php(55): DateTime->__construct('29/04/2016')
#1 .../lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php(2671): Magento\Framework\Stdlib\DateTime->formatDate('29/04/2016', true)
#2 .../lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php(2896): Magento\Framework\DB\Adapter\Pdo\Mysql->formatDate('29/04/2016')
#3 .../lib/internal/Magento/Framework/Model/ResourceModel/AbstractResource.php(184): Magento\Framework\DB\Adapter\Pdo\Mysql->prepareColumnValue(Array, '29/04/2016')
....

Where do I need to fix this? The locale settings in the Magento config are the same for all my store views (but then again, adminhtml is a different kind of store view and cannot be assigned a locale to my knowledge...?).

Or would this be lower, like the OS locale? But my environment is running in Docker containers and therefore it should be exactly the same, regardless if they run on my local or on the server.

I don't know what to do. Please help.

Edit: I have made some progress. I discovered that the admin store view locale can be set for every admin user in their settings, and one of mine was set to en_US while the other was en_GB.

But the question remains: how do I handle this correctly? I don't want my code to break when the admin user changes their locale.

1 Answer 1

5

Answering my own question now that I solved it.

I was missing a date filter to convert the localized date to an internal date before saving my model. I found this when looking at Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog\Save which also does this.

In my controller which saves the provided values to my model (I'm omitting a lot of other stuff for clarity):

/**
 * Date filter instance
 *
 * @var \Magento\Framework\Stdlib\DateTime\Filter\Date
 */
protected $_dateFilter;

/**
 * @param \Magento\Backend\App\Action\Context $context
 * @param \Magento\Framework\Registry $coreRegistry
 * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter
 * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
 * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
 * @param .....\Model\ProviderFactory $providerFactory
 */
public function __construct(
    \Magento\Backend\App\Action\Context $context,
    \Magento\Framework\Registry $coreRegistry,
    \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter,
    \Magento\Framework\View\Result\PageFactory $resultPageFactory,
    \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
    .....\Model\ProviderFactory $providerFactory
) {
    $this->_coreRegistry = $coreRegistry;
    $this->_dateFilter = $dateFilter;
    $this->resultPageFactory = $resultPageFactory;
    $this->providerFactory = $providerFactory;
    $this->resultForwardFactory = $resultForwardFactory;
    parent::__construct($context);
}

/**
 * Save action
 *
 * @return \Magento\Framework\Controller\ResultInterface
 */
public function execute()
{
    $data = $this->getRequest()->getPostValue();

    /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
    $resultRedirect = $this->resultRedirectFactory->create();

    if ($data)
    {
        // make sure the date is converted to internal format
        $inputFilter = new \Zend_Filter_Input(
            ['quota_expiry' => $this->_dateFilter],
            [],
            $data
        );
        $data = $inputFilter->getUnescaped();

        /** @var ....\Model\Provider $model */
        $model = $this->_initProvider();

        $model->setData($data);

        try {
            $model->save();
            .......
        } catch (\RuntimeException $e) {
            .......
        }
    }

    return $resultRedirect->setPath('*/*/');
}
1
  • Many thanks, works like a charm
    – Badong
    Oct 8, 2020 at 10:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.