SilverStripe: Please enter a valid date format

From FVue
Jump to: navigation, search

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; }
    }
}

Comments

blog comments powered by Disqus

Personal tools
Google