ZF-3381: Incorrect month definition using 'setDate' method

Description

I'm using setDate method to parse date to get unix timestamp as follows: {color:green}$date->setDate('6/1/2008', 'M/d/Y');{color} It works fine on some linux platforms but has a bug on others. If I want to parse a date with month set to one which has number of days less than 31 it adds 1 to month number. Say, if I parse '2/10/2008', '4/15/2008', '6/22/2008' it always returns timestamp with month set to 3, 5, 7 accordingly. I've got a solution for this bug. I've made a little modification to 'Zend_Date' class, '_date' method. There are three lines which set the date in three steps as follows: {color:green}$date->set($parsed['year'], Zend_Date::YEAR); $date->set($parsed['month'], Zend_Date::MONTH); $date->set($parsed['day'], Zend_Date::DAY);{color} The order of the last two lines should be changed to fix the bug as follows: {color:green}$date->set($parsed['year'], Zend_Date::YEAR);{color} {color:red}$date->set($parsed['day'], Zend_Date::DAY); $date->set($parsed['month'], Zend_Date::MONTH);{color} The first line sets date to the defined year, month 12 and day 31. The second sets date to the defined day and the last sets date to the defined month. We cannot set month before day because when we set year it sets default day number to 31. Then if we set month which has 30 days (April, June...) it switches month to the next one (May, July...) and day number to 1.

Please fix this in official release.

Comments

Where is your problem ? Can you give us a example with code which shows the problem ? What you get, what you expected, the release, php version, os and so on... Why should setting the 1.June respond in such a problem as you described ?

But: When you set 31.February you will ALWAYS get the 2 or 3rd May. This is no failure but expected behaviour and documented within the manual. I believe there is an option where you can switch off the overlapping for months.

When you set a impossible date, Zend_Date will always automatically correct this. As your change introduces problems with existing code it will not be added to trunk.

What would you expect to get returned when you set a 32.Feburary ??

PHP Version 5.2.4, Zend Framework 1.0.2 and 1.5.2 (both), Linux 2.6.24.5-g-r17 #1 SMP Exact test case is {color:red}$date = new Zend_Date(); $date->setDate('6/1/2008', 'M/d/Y'); print $date->toString('M/d/Y'); // retruns "7/1/2008" and same problem with other months which have less than 31 days{color}

I am not able to reproduce your behaviour with trunk. When you are willing to test I would recommend that you

  • install the trunk release (9600 or higher)
  • run this example:

$date = new Zend_Date();
print "\n".$date->getIso();
$date->setDate('6/1/2008', 'M/d/Y');
print "\n".$date->getIso();
  • when it fails please return the output
  • additionally run and return the output of the following:

print_r (Zend_Locale_Format::getDate('6/1/2008', array('date_format' => 'M/d/Y', 'format_type' => 'iso'));

Updated to revision 9605. The problem is still there. Here is my code:

<

pre class="literal">

<?
require_once('./Zend/Date.php');

$date = new Zend_Date();
print "\n".$date->getIso();
$date->setDate('6/1/2008', 'M/d/Y');
print "\n".$date->getIso();
print "\n\n";
print_r(Zend_Locale_Format::getDate('6/1/2008', array('date_format' => 'M/d/Y', 'format_type' => 'iso')));
?>

And here is return:

2008-06-04T08:27:02-05:00
2008-07-01T08:27:02-05:00

Array
(
    [date_format] => M/d/Y
    [locale] => 
    [month] => 6
    [day] => 1
    [year] => 2008
)

Ok... now it gets durty :-)

Date.php: line 2924: add "print "\n".$date->getIso();" below. Also below 2925, 2926, 2927 and 2928

Also output me your locale $locale from line 2924.

Output is now

2008-06-04T09:02:33-05:00
1969-12-31T18:00:00-06:00
$locale = en_US
2008-12-31T18:00:00-06:00
2008-07-01T18:00:00-05:00
2008-07-01T18:00:00-05:00
Tuesday, July 1, 2008
2008-07-01T09:02:33-05:00

Array
(
    [date_format] => M/d/Y
    [locale] => 
    [month] => 6
    [day] => 1
    [year] => 2008
)

Ok... problem found.

Please change line 2924 so it looks like this:


            $date = new self(0, self::TIMESTAMP, $locale);
            $date->setTimezone('UTC');

This should fix your problem. Please test it and give me the result.

Thanks...

Yes, this fixes the bug:

2008-06-05T04:18:35-05:00
1970-01-01T00:00:00+00:00
$locale = en_US
2008-01-01T00:00:00+00:00
2008-06-01T00:00:00+00:00
2008-06-01T00:00:00+00:00
Sunday, June 1, 2008
2008-06-01T04:18:35-05:00

Array
(
    [date_format] => M/d/Y
    [locale] => 
    [month] => 6
    [day] => 1
    [year] => 2008
)

The fix has been added with r9612

Updating for the 1.6.0 release.