SilverStripe: Please enter a valid date format
Contents
Problem
After having changed the default locale in SilverStripe to `nl_NL', using this command in _config.php:
i18n::set_default_locale('nl_NL');
submitting Date fields will yield an error:
Please enter a valid date format (d MMM yyyy).
Environment
- SilverStripe-2.4.5, SilverStripe-3
Solution
The solution is to add a set_date_format to mysite/_config.php:
i18n::set_default_locale('nl_NL'); Translatable::set_default_locale('nl_NL'); // Use only numbers to satisfy Zend_Locale_Format::_parseDate() i18n::set_date_format('dd-MM-yyyy');
In short, this is because there seems to be a problem with Zend_Locale_Format::_parseDate() matching full month names only... and the Javascript datepicker uses Zend_Locale_Format::_parseDate() to validate dates.
For SilverStripe-3, overwriting the date validation method makes the validation work:
jQuery(document).ready(function() { jQuery.validator.methods['date'] = function(value, element) { try { jQuery.datepicker.parseDate('dd-mm-yy', value); return true; } catch (e) { return false; } } }
Caveat: jQuery date validation can only cope with dd/mm/yy
The jQuery date validation uses JavaScripts built-in Date to test if the date is valid, as can be seen in this excerpt from jquery.validate.js:
// http://docs.jquery.com/Plugins/Validation/Methods/date date: function(value, element) { return this.optional(element) || !/Invalid|NaN/.test(new Date(value)); },
Javascript's built-in Date, however, can only cope with the format `dd/mm/yy'. The workaround is to disable the jQuery date validation:
--- userforms/code/editor/EditableDateField.php.orig 2012-05-18 14:45:07.000000000 +0200 +++ userforms/code/editor/EditableDateField.php 2012-05-18 14:48:20.000000000 +0200 @@ -73,8 +73,11 @@ * @return Array */ public function getValidation() { + // Disabled because jQuery date validation can only validate format dd/mm/yy + // See: http://docs.jquery.com/Plugins/Validation/Methods/date + // -- FVu, Fri May 18 14:46:34 CEST 2012 return array( - 'date' => true + 'date' => false ); }
Rationale
If you put only this in mysite/_config.php:
i18n::set_default_locale('nl_NL');
the call stack will become:
DateField::__construct()
i18n::get_date_format()
Zend_Locale_Format::getDateFormat('nl_NL)
Zend_Locate_Data::getContent('nl_NL', 'date')
Zend_Locate_Data::getContent() defaults to use dateformat "gregorian/medium" and so will retrieve
/ldml/dates/calendars/calendar[@type='gregorian']/dateFormats/dateFormatLength[@type='medium']/dateFormat/pattern
from the file:
sapphire/thirdparty/Zend/Locale/Data/nl.xml
which is set to 'd MMM yyyy'.
"MMM" denotes charaters, i.e. "Oct", "Nov", "Dec".
Zend_Locale_Format::_parseDate(), however, does a non-matching search on full month names ("October", "November", "December") and a subsequent split on numbers (\d+):
preg_match_all('/\d+/u', $number, $splitted);
So e.g. "15 Dec 2012" gets splitted to:
[0] => 15 [1] => 2012
"2012" will be read as the "MMM" month and Zend will die because month > 12.
Journal
2012-05-18
Changed `mm' (minutes) to `MM' (months):
-i18n::set_date_format('dd/mm/yyyy'); +i18n::set_date_format('dd/MM/yyyy');
See also: http://framework.zend.com/manual/en/zend.date.constants.html
Changed slash `/' to hyphen `-' now that I know how to workaround the jQuery date validation.
-i18n::set_date_format('dd/MM/yyyy'); +i18n::set_date_format('dd-MM-yyyy');
2013-08-01
Still error, now with SilverStripe-3. Adding this somewhere seems to work:
jQuery(document).ready(function() { jQuery.validator.methods['date'] = function(value, element) { try { jQuery.datepicker.parseDate('dd-mm-yy', value); return true; } catch (e) { return false; } } }