SilverStripe: Please enter a valid date format
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; }
}
}