troubles with DateFormatter


(Raffaele Tosti) #1

Hello everybody!

Today I would like to share our experience about an apparently strange behavior that happened while validate a date string using the DateValidator class: the preamble is that we notice as the same date string has been successfully validated on our staging server whereas it fails on production server. The differences between the two machines are the php version (5.6.30-0+deb8u1 on staging and 7.0.19-1 on production) and the ICU version and ICU Data version (respectively 52.1 for both on the staging and 57.1 for both on production) having the same intl version (1.1.0).

Debugging the code we have noticed as the line of code that changed the result was:


$parsedDate = @$formatter->parse($value, $parsePos);

present inside the


parseDateValueIntl($value, $format)

method of the DateValidator class. On the staging server the parse method return an unix timestamp whilst in production it return false. So far we noticed as disabling the strict parsing setting for the IntlDateFormatter object


$formatter->setLenient(false);

allows the correct parsing of the date string the way we want, however the awful truth is that we had to comment the setLenient() line of code in order to make it works but we would like to look for a better solution… we might need to extend the DateValidator class to fits our needs? There might be other better things to do to solve such issue?

Thanks in advance


(Raffaele Tosti) #2

Update

So far I tried to extends the yii\validators\DateValidator and yii\validators\Validator classes without success as well as declare a validator component in the config/main.php.

The only way that apparently solve this issue for me has been create a DateValidator.php class (I have putted inside @app/components folder) and modify the entry script index.php in this way: (this particular project use a basic template but I believe it can be easily adapted for the advanced template)




require(__DIR__ . '/../vendor/autoload.php');

require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');


\Yii::$classMap['yii\validators\DateValidator'] = '@app/components/DateValidator.php';


$config = yii\helpers\ArrayHelper::merge(

        require(__DIR__ . '/../config/main.php'), require(__DIR__ . '/../config/main-local.php')

);


(new yii\web\Application($config))->run();



Inside the DateValidator class I have pasted the code present in yii\validators\DateValidator of course commenting the IntlDateFormatter strict parsing setting:




//$formatter->setLenient(false);



Initially I declared the namespace for app\components\DateValidator as




namespace app\components;



but it cause me troubles every time a model attribute was validated using the ‘date’ rule, with the following error message:

[b]

Unable to find ‘yii\validators\DateValidator’ in file: /var/www/apache/plurima.snake.lappi.virt/htdocs/components/DateValidator.php. Namespace missing?

[/b]

To get a rid of this error I had to declare a "wrong" namespace for app\components\DateValidator as:




namespace yii\validators;



Now everything works fine but it seems to me like a mess rather than a good solution and I was wondering whether there would be a better way to extend and customize Yii2 Core Classes such as yii\validators\DateValidator in my case.

Cheers and hope this would be useful for somebody