7

I am using Magento 1.9.1.0. I set up a catalog price rule which applies to all my products in my store with a discount of the 20 percent for just one day. The catalogrule_apply_all action is supposed to be ran every day at 1am in the mornig (0 1 * * *).

I have a problem in setting the date range of the promotion. To test it, in my development environment, I set up the from_date and the end_date with the 'today' value. After applying the rule I can't see the promotion in the frontend. I need to set up the from_date back of one day to see it working.

Now I have to schedule the promotion, which will start in 2 days, for my production environment and I am not sure about which value assign to from_date field. Should I assign the day before it should be active or should i leave the real start date?

7

Problem in this instance is on these lines

$fromTime = (int) strtotime($rule->getFromDate());
$toTime = (int) strtotime($rule->getToDate());

They are not using Magento time methods to take in to consideration timing zones and in the comparison it uses following line. (Few lines after the above lines)

$coreDate  = $this->_factory->getModel('core/date');
$timestamp = $coreDate->gmtTimestamp('Today');

If you update the first two lines to

$fromTime = (int) Mage::getModel('core/date')->gmtTimestamp(strtotime($rule->getFromDate()));
$toTime = (int) Mage::getModel('core/date')->gmtTimestamp(strtotime($rule->getToDate()));

Note that now both uses gmtTimestamp which is inline with the comparison. This should work fine. Obviously add a class override.

  • This solution has bug, it will set all products on sale, even if there are conditions set. – newbie Jun 22 '17 at 6:27
  • This doesn't work on Magento 1.9.3.3 – Fred K Nov 23 '17 at 9:48
  • please send a PULL fix request here: github.com/OpenMage/magento-lts – snh_nl Dec 4 '17 at 20:13
2

I also have the same issue but it was in Magento EE 1.14.2.1. System / Configuration / General - Locale Options settings seems to correct.

I concluded that the problem was in the file: Mage/CatalogRule/Model/Resource/Rule.php Replacing the line

$timestamp = $coreDate->gmtTimestamp('Today');

with

$timestamp = $coreDate->timestamp();

So it will be

public function insertRuleData(Mage_CatalogRule_Model_Rule $rule, array $websiteIds, array $productIds = array())
{
    /** @var $write Varien_Db_Adapter_Interface */
    $write = $this->_getWriteAdapter();

    $customerGroupIds = $rule->getCustomerGroupIds();

    $fromTime = (int) strtotime($rule->getFromDate());
    $toTime = (int) strtotime($rule->getToDate());
    $toTime = $toTime ? ($toTime + self::SECONDS_IN_DAY - 1) : 0;

    /** @var Mage_Core_Model_Date $coreDate */
    $coreDate  = $this->_factory->getModel('core/date');

    // $timestamp = $coreDate->gmtTimestamp('Today');
    $timestamp = $coreDate->timestamp();

    if ($fromTime > $timestamp
        || ($toTime && $toTime < $timestamp)
    ) {
        return;
    }

Both should calculate the current timestamp. But based on my tests,

$coreDate->timestamp();
converts to the correct timezone offset (same as my server date and time settings), while I always end up with a 1 day before with
$coreDate->gmtTimestamp('Today');
Like what Jeroen said, it might be Magento bug.

  • This doesn't work on Magento 1.9.3.3 – Fred K Nov 23 '17 at 9:54
1

From Mage/CatalogRule/Model/Resource/Rule.php

/**
 * Inserts rule data into catalogrule/rule_product table
 *
 * @param Mage_CatalogRule_Model_Rule $rule
 * @param array $websiteIds
 * @param array $productIds
 */
public function insertRuleData(Mage_CatalogRule_Model_Rule $rule, array $websiteIds, array $productIds = array())
{
    /** @var $write Varien_Db_Adapter_Interface */
    $write = $this->_getWriteAdapter();

    $customerGroupIds = $rule->getCustomerGroupIds();

    $fromTime = (int) strtotime($rule->getFromDate());
    $toTime = (int) strtotime($rule->getToDate());
    $toTime = $toTime ? ($toTime + self::SECONDS_IN_DAY - 1) : 0;

    /** @var Mage_Core_Model_Date $coreDate */
    $coreDate  = $this->_factory->getModel('core/date');
    $timestamp = $coreDate->gmtTimestamp('Today');
    if ($fromTime > $timestamp
        || ($toTime && $toTime < $timestamp)
    ) {
        return;
    }

Everything looks fine so far if you put the same for from and to date. For the to date is date + seconds in a day - 1, so will be end of that day.

Maybe the core date is incorrect because of a conflicting timezone setting.

You could test with a test script and echo some data.

include('app/Mage.php');
Mage::app('admin');

echo date('Ymd His', Mage::getModel('core/date')->gmtTimestamp('today'));

Or invoke the insertRuleData manually and add some debug data in the resource file for testing.

$ruleId = 1; // Your rule id here
/** @var $rule Mage_CatalogRule_Model_Rule */
$rule = Mage::getModel('catalogrule/rule')->load($ruleId);

/** @var $resource Mage_CatalogRule_Model_Resource_Rule */
$resource = Mage::getResourceModel('catalogrule/rule');

$resource->insertRuleData($rule, array_keys(Mage::app()->getWebsites(true)));
  • 1
    I did the test as you suggested and the date returned from the method Mage::getModel('core/date')->gmtTimestamp('today') is one day back the actual day. eg.: today is the 19th but my Magento prints the 18th as the today date. It seems my problem depends on it but I can not find the way to set the correct date in my Magento store. – gianis6 Mar 19 '15 at 14:28
  • 1
    That means your locale is of by a day. System / Configuration / Locale options -> set timezone correctly – Jeroen Mar 19 '15 at 14:39
  • which timezone should I use? The server where my store is hosted has the CDT (-5) timezone while my store is supposed to operate in CET (+1). – gianis6 Mar 19 '15 at 15:49
  • Use the correct one for your store, then run the testscript again – Jeroen Mar 19 '15 at 16:04
  • I can't understand which timezone should I use. If I set the CDT timezone and I run the testscript the today date printed is '2015-03-19 05:00:00'. I need my rule to be activated/deactive at 00:00:00 CET timezone. Leaving this setting my catalog rule will be activated/deactived at 5 am UTC time? – gianis6 Mar 19 '15 at 16:17
1

special_to_date & special_from_date - not works in Rule filter. Can use only - special_price

But if exist settings in product with outdate Special price, need update Special price attributes with script like --

require_once 'app/Mage.php';
$app = Mage::app('admin');

$now = strtotime(date('Y-m-d H:i:s'));
$collection = Mage::getModel('catalog/product')->getCollection()->addAttributeToSelect(array('sku', 'special_price'))
    ->addAttributeToFilter(
        'special_to_date',
        array('to' => date('Y-m-d H:i:s', $now))
    );


foreach ($collection as $oProduct) {
    $product = '';
    $product = Mage::getModel('catalog/product')->load($oProduct->getId());
    $product->setData('special_to_date', '');
    $product->setData('special_from_date', '');
    $product->setData('special_price', '');
    $product->save();
}
1

Problem is that the function gmtTimestamp() subtract Zend_Date::TIMEZONE_SECS to return GMT timestamp from date in current timezone. When you pass a string to that function like 'Today' and your current timezone is not UTC the result will be always wrong.

To correct this, Mage/CatalogRule/Model/Resource/Rule.php line 218 change

$timestamp = $coreDate->gmtTimestamp('Today');

with

$timestamp = $coreDate->gmtTimestamp('Today +'.Mage::app()->getLocale()->date()->get(Zend_Date::TIMEZONE_SECS).' seconds');
0

I found it was better to change the time stamp to use the local time instead of using GMT for the caluations.

$timestamp = Mage::app()->getLocale()->date(null, null, null, true)->get(Zend_Date::TIMESTAMP);
0

The problem still exists in Magento 1.9.4.0. Using the solution from xelber works perfect. Just rewrite the function insertRuleData() in Mage_CatalogRule_Model_Resource_Rule

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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