Categories
bug work

ZF1 still can’t parse dates right

I was running into some date validation problems between jQuery datepicker and ZF1. My client wanted one date picker to use a “January 01, 2000” format, and the others a “01/02/2000” format. Seems simple enough.

Zf1_Dates

So I went digging into Zend_Validate_Date. It winds up checking Zend_Date::isDate, so I figured that would be a good place to see what the valid formats were to describe my form.

        $long = new ZendX_JQuery_Form_Element_DatePicker('LONGDATE');
        $long->setLabel('Long Date')
            ->setRequired(false)
            ->setOptions(array('jQueryParams'=>array(
                 'dateFormat'=>'MM dd, yy',
                 'changeYear'=>'1',
                 'defaultDate'=>'January 01, '.date('Y'))))
            ->addValidator(new Zend_Validate_Date('MMMM dd, yyyy'));

        $compact = new ZendX_JQuery_Form_Element_DatePicker('COMPACT');
        $compact->setLabel('Compact Date')
            ->setRequired(false)
            ->setOptions(array('jQueryParams'=>array(
                 'changeYear'=>'1',
                 'defaultDate'=>'01/01/'.date('Y'))))
            ->addValidator(new Zend_Validate_Date('MM/dd/yyyy'));

As you can see, jQuery uses a different formatting system than Zend_Date but that is okay.

Whenever I tried to save the form, the $long element would error out that ‘January 01, 2013’ was not in a valid ‘MMMM dd, yyyy’ format. That didn’t make sense.

Turns out that other have had similar problems. If fact, there is even a few bug reports on the subject. The problem goes from Zend_Validate_Date to Zend_Date to Zend_Locale_Format, at which point I got tired. Alas, even if it does work in ZF2, I can’t migrate this massive codebase fast enough.

I wanted to see how deep the rabbit hole went but there were too many gnomes. If you want to see how odd things get, try this out for kicks:

$dateTests = array(
    'January 12, 2012',      'Jan 12, 2012',
    'Feb 23, 1975',          'December 33, 3344',
    '01/02/2012',            '01-02-2012',
    '20120102',              '2012',
    '13012012',              '122903',
);
$formatsTest = array(
    'G','GG','GGG','GGGG','GGGGG',
    'y','yy','yyy','yyyy','yyyyy',
    'Y','YY','YYY','YYYY','YYYYY',
    'M','MM','MMM','MMMM','MMMMM',
    'w','ww',
    'd','dd',
    'D','DD','DDD',
    'E','EE','EEE','EEEE','EEEEE',
    'e','ee',
    'a',
    'h','hh',
    'H','HH',
    'm','mm',
    's','ss',
    'S',
    'z','zz','zzz','zzzz',
    'Z','ZZ','ZZZ','ZZZZ',
    'A',
    'b7',
    'MMMM dd, yyyy',
    'MMMM/dd/yyyy',
    'dd-MM-yyyy'
); ?>
<table>
    <thead><tr><th>ZVD Format</th><th>Test Date</th><th>Valid?</th><th>IsDate?</th><th>Errors</th></tr></thead>
    <tbody>
<?php
foreach ($formatsTest as $f){
    $v = new Zend_Validate_Date($f);
    foreach ($dateTests as $d){
        $valid = $v->isValid($d);
        $isDate = Zend_Date::isDate($d, $f, 'en');
        $fail='';
        if (count($v->getErrors())>0){
            $fail = array_shift($v->getErrors());
        }?>
        <tr style="<?php if (!$valid) {?>background:#daa;<?php }
                         if (!$isDate){?>color:#500;<?php } ?>">
            <td><?php echo $f; ?></td>
            <td><?php echo $d; ?></td>
            <td><?php echo ($valid?"Y":'N')?></td>
            <td><?php echo ($isDate?"Y":"N")?></td>
            <td><?php echo $fail; ?></td>
        </tr>
        <?php
    }
}
?>
</tbody></table>