source: Dev/branches/rest-dojo-ui/client/dojox/date/hebrew/locale.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 16.1 KB
Line 
1define(["dojo/main", "dojo/date", "dojo/i18n", "dojo/regexp", "dojo/string", "./Date", "./numerals", "dojo/i18n!dojo/cldr/nls/hebrew"],
2        function(dojo, dd, i18n, regexp, string, hebrewDate, numerals){
3
4        dojo.getObject("date.hebrew.locale", true, dojox);
5        dojo.experimental("dojox.date.hebrew.locale");
6
7        //Load the bundles containing localization information for
8        // names and formats
9        dojo.requireLocalization("dojo.cldr", "hebrew");
10
11        // Format a pattern without literals
12        function formatPattern(dateObject, bundle, locale, fullYear,  pattern){
13
14                return pattern.replace(/([a-z])\1*/ig, function(match){
15                        var s, pad;
16                        var c = match.charAt(0);
17                        var l = match.length;
18                        var widthList = ["abbr", "wide", "narrow"];
19                       
20                        switch(c){
21                                case 'y':
22                                        if(locale.match(/^he(?:-.+)?$/)){
23                                                s = numerals.getYearHebrewLetters(dateObject.getFullYear());
24                                        }else{
25                                                s = String(dateObject.getFullYear());
26                                        }
27                                        break;
28                                case 'M':
29                                        var m = dateObject.getMonth();
30                                        if(l<3){
31                                                if(!dateObject.isLeapYear(dateObject.getFullYear()) && m>5){m--;}
32                                                if(locale.match(/^he(?:-.+)?$/)){
33                                                        s = numerals.getMonthHebrewLetters(m);
34                                                }else{
35                                                        s = m+1; pad = true;
36                                                }
37                                        }else{
38                                                var monthNames = dojox.date.hebrew.locale.getNames('months',widthList[l-3], 'format', locale, dateObject);
39                                                s = monthNames[m];
40                                        }
41                                        break;
42                                case 'd':
43                                        if(locale.match(/^he(?:-.+)?$/)){
44                                                s =  dateObject.getDateLocalized(locale);
45                                        }else{
46                                                s = dateObject.getDate(); pad = true;
47                                        }
48                                        break;
49                                case 'E':
50                                        var d = dateObject.getDay();
51                                        if(l<3){
52                                                s = d+1; pad = true;
53                                        }else{
54                                                var propD = ["days", "format", widthList[l-3]].join("-");
55                                                s = bundle[propD][d];
56                                        }
57                                        break;
58                                case 'a':
59                                        var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';
60                                        s = bundle['dayPeriods-format-wide-' + timePeriod];
61                                        break;
62                                case 'h':
63                                case 'H':
64                                case 'K':
65                                case 'k':
66                                        var h = dateObject.getHours();
67                                        // strange choices in the date format make it impossible to write this succinctly
68                                        switch (c){
69                                                case 'h': // 1-12
70                                                        s = (h % 12) || 12;
71                                                        break;
72                                                case 'H': // 0-23
73                                                        s = h;
74                                                        break;
75                                                case 'K': // 0-11
76                                                        s = (h % 12);
77                                                        break;
78                                                case 'k': // 1-24
79                                                        s = h || 24;
80                                                        break;
81                                        }
82                                        pad = true;
83                                        break;
84                                case 'm':
85                                        s = dateObject.getMinutes(); pad = true;
86                                        break;
87                                case 's':
88                                        s = dateObject.getSeconds(); pad = true;
89                                        break;
90                                case 'S':
91                                        s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
92                                        break;
93                                case 'z':
94                                        s = "";
95                                        break;
96                                default:
97                                        throw new Error("dojox.date.hebrew.locale.formatPattern: invalid pattern char: "+pattern);
98                        }
99                        if(pad){ s = string.pad(s, l); }
100                        return s;
101                });
102        }
103       
104        dojox.date.hebrew.locale.format = function(/*hebrew.Date*/dateObject, /*object?*/options){
105                // based on and similar to dojo.date.locale.format
106                //summary:
107                //              Format a Date object as a String, using  settings.
108                //
109                // description:
110                //              Create a string from a hebrew.Date object using a known pattern.
111                //              By default, this method formats both date and time from dateObject.
112                //              Default formatting lengths is 'short'
113                //
114                // dateObject:
115                //              the date and/or time to be formatted.  If a time only is formatted,
116                //              the values in the year, month, and day fields are irrelevant.  The
117                //              opposite is true when formatting only dates.
118
119                options = options || {};
120
121                var locale = i18n.normalizeLocale(options.locale);
122                var formatLength = options.formatLength || 'short';
123                var bundle = dojox.date.hebrew.locale._getHebrewBundle(locale);
124                var str = [];
125
126                var sauce = dojo.hitch(this, formatPattern, dateObject, bundle, locale, options.fullYear);
127                if(options.selector == "year"){
128                        var year = dateObject.getFullYear();
129                        return locale.match(/^he(?:-.+)?$/) ?
130                                numerals.getYearHebrewLetters(year) : year;
131                }
132                if(options.selector != "time"){
133                        var datePattern = options.datePattern || bundle["dateFormat-"+formatLength];
134                        if(datePattern){str.push(_processPattern(datePattern, sauce));}
135                }
136                if(options.selector != "date"){
137                        var timePattern = options.timePattern || bundle["timeFormat-"+formatLength];
138                        if(timePattern){str.push(_processPattern(timePattern, sauce));}
139                }
140                var result = str.join(" "); //TODO: use locale-specific pattern to assemble date + time
141
142                return result; // String
143        };
144
145        dojox.date.hebrew.locale.regexp = function(/*object?*/options){
146                //      based on and similar to dojo.date.locale.regexp
147                // summary:
148                //              Builds the regular needed to parse a hebrew.Date
149
150                return dojox.date.hebrew.locale._parseInfo(options).regexp; // String
151        };
152
153        dojox.date.hebrew.locale._parseInfo = function(/*oblect?*/options){
154        /* based on and similar to dojo.date.locale._parseInfo */
155
156                options = options || {};
157                var locale = i18n.normalizeLocale(options.locale);
158                var bundle = dojox.date.hebrew.locale._getHebrewBundle(locale);
159
160                var formatLength = options.formatLength || 'short';
161                var datePattern = options.datePattern || bundle["dateFormat-" + formatLength];
162                var timePattern = options.timePattern || bundle["timeFormat-" + formatLength];
163
164                var pattern;
165                if(options.selector == 'date'){
166                        pattern = datePattern;
167                }else if(options.selector == 'time'){
168                        pattern = timePattern;
169                }else{
170                        pattern = (timePattern === undefined) ? datePattern : datePattern + ' ' + timePattern; //hebrew resource file does not contain time patterns - a bug?
171                }
172
173                var tokens = [];
174       
175                var re = _processPattern(pattern, dojo.hitch(this, _buildDateTimeRE, tokens, bundle, options));
176                return {regexp: re, tokens: tokens, bundle: bundle};
177        };
178
179        dojox.date.hebrew.locale.parse = function(/*String*/value, /*Object?*/options){
180                        // based on and similar to dojo.date.locale.parse
181                        // summary: This function parse string date value according to options
182                        // example:
183                        // |            var dateHebrew = dojox.date.hebrew.locale.parse('11/10/5740', {datePattern:'dd/MM/yy', selector:'date'});
184                        // |            in Hebrew locale string for parsing contains Hebrew Numerals
185                        // |
186                        // |  options = {datePattern:'dd MMMM yy', selector:'date'};
187                        // |
188                        // |   y - year
189                        // |   M, MM  - short month
190                        // |  MMM, MMMM - long month
191                        // |  d - date
192                        // |  a - am, pm
193                        // |   E, EE, EEE, EEEE  - week day
194                        // |
195                        // |    h, H, k, K, m, s, S,  -  time format
196               
197                value =  value.replace(/[\u200E\u200F\u202A-\u202E]/g, ""); //remove special chars
198
199                if(!options){options={};}
200                var info = dojox.date.hebrew.locale._parseInfo(options);
201       
202                var tokens = info.tokens, bundle = info.bundle;
203                var re = new RegExp("^" + info.regexp + "$");
204       
205                var match = re.exec(value);
206
207                var locale = i18n.normalizeLocale(options.locale);
208
209                if(!match){
210                        console.debug("dojox.date.hebrew.locale.parse: value  "+value+" doesn't match pattern   " + re);
211                        return null;
212                } // null
213       
214                var date, date1;
215       
216                //var result = [1970,0,1,0,0,0,0]; //
217                var result = [5730,3,23,0,0,0,0];  // hebrew date for [1970,0,1,0,0,0,0] used in gregorian locale
218                var amPm = "";
219                var mLength = 0;
220                var widthList = ["abbr", "wide", "narrow"];
221                var valid = dojo.every(match, function(v, i){
222                        if(!i){return true;}
223                        var token=tokens[i-1];
224                        var l=token.length;
225                        switch(token.charAt(0)){
226                                case 'y':
227                                        if(locale.match(/^he(?:-.+)?$/)){
228                                                result[0] = numerals.parseYearHebrewLetters(v);
229                                        }else{
230                                                result[0] = Number(v);
231                                        }
232                                        break;
233                                case 'M':
234                                        //if  it is short format, month is one letter or two letter with "geresh"
235                                        if(l>2){
236                                                //we do not know here if the year is leap or not
237                                                var months = dojox.date.hebrew.locale.getNames('months', widthList[l-3], 'format', locale, new hebrewDate(5769, 1, 1)),
238                                                        leapmonths = dojox.date.hebrew.locale.getNames('months', widthList[l-3], 'format', locale, new hebrewDate(5768, 1, 1));
239                                                if(!options.strict){
240                                                        //Tolerate abbreviating period in month part
241                                                        //Case-insensitive comparison
242                                                        v = v.replace(".","").toLowerCase();
243                                                        months = dojo.map(months, function(s){ return s ? s.replace(".","").toLowerCase() : s; } );
244                                                        leapmonths = dojo.map(leapmonths, function(s){ return s ? s.replace(".","").toLowerCase() : s; } );
245                                                }
246                                                var monthName = v;
247                                                v = dojo.indexOf(months, monthName);
248                                                if(v == -1){
249                                                        v = dojo.indexOf(leapmonths, monthName);
250                                                        if(v == -1){
251                                                                //console.debug("dojox.date.hebrew.locale.parse: Could not parse month name:  second   " + v +"'.");
252                                                                return false;
253                                                        }
254                                                }
255                                                mLength = l;
256                                        }else{
257                                                if(locale.match(/^he(?:-.+)?$/)){
258                                                        v = numerals.parseMonthHebrewLetters(v);
259                                                }else{
260                                                        v--;
261                                                }
262                                        }
263                                        result[1] = Number(v);
264                                        break;
265                                case 'D':
266                                        result[1] = 0;
267                                        // fallthrough...
268                                case 'd':
269                                        if(locale.match(/^he(?:-.+)?$/)){
270                                                result[2] = numerals.parseDayHebrewLetters(v);
271                                        }else{
272                                                result[2] = Number(v);
273                                        }
274                                        break;
275                                case 'a': //am/pm
276                                        var am = options.am || bundle['dayPeriods-format-wide-am'],
277                                                pm = options.pm || bundle['dayPeriods-format-wide-pm'];
278                                        if(!options.strict){
279                                                var period = /\./g;
280                                                v = v.replace(period,'').toLowerCase();
281                                                am = am.replace(period,'').toLowerCase();
282                                                pm = pm.replace(period,'').toLowerCase();
283                                        }
284                                        if(options.strict && v != am && v != pm){
285                                                return false;
286                                        }
287
288                                        // we might not have seen the hours field yet, so store the state and apply hour change later
289                                        amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
290                                        break;
291                                case 'K': //hour (1-24)
292                                        if(v == 24){ v = 0; }
293                                        // fallthrough...
294                                case 'h': //hour (1-12)
295                                case 'H': //hour (0-23)
296                                case 'k': //hour (0-11)
297                                        //in the 12-hour case, adjusting for am/pm requires the 'a' part
298                                        //which could come before or after the hour, so we will adjust later
299                                        result[3] = Number(v);
300                                        break;
301                                case 'm': //minutes
302                                        result[4] = Number(v);
303                                        break;
304                                case 's': //seconds
305                                        result[5] = Number(v);
306                                        break;
307                                case 'S': //milliseconds
308                                        result[6] = Number(v);
309                        }
310                        return true;
311                });
312
313                var hours = +result[3];
314                if(amPm === 'p' && hours < 12){
315                        result[3] = hours + 12; //e.g., 3pm -> 15
316                }else if(amPm === 'a' && hours == 12){
317                        result[3] = 0; //12am -> 0
318                }
319                var dateObject = new hebrewDate(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // hebrew.Date
320                //for non leap year, the index of the short month start from adar should be increased by 1
321                if(mLength < 3 && result[1] >= 5 && !dateObject.isLeapYear(dateObject.getFullYear())){
322                        dateObject.setMonth(result[1]+1);
323                }
324                return dateObject; // hebrew.Date
325        };
326
327
328        function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
329                //summary: Process a pattern with literals in it
330
331                // Break up on single quotes, treat every other one as a literal, except '' which becomes '
332                var identity = function(x){return x;};
333                applyPattern = applyPattern || identity;
334                applyLiteral = applyLiteral || identity;
335                applyAll = applyAll || identity;
336
337                //split on single quotes (which escape literals in date format strings)
338                //but preserve escaped single quotes (e.g., o''clock)
339                var chunks = pattern.match(/(''|[^'])+/g);
340                var literal = pattern.charAt(0) == "'";
341
342                dojo.forEach(chunks, function(chunk, i){
343                        if(!chunk){
344                                chunks[i]='';
345                        }else{
346                                chunks[i]=(literal ? applyLiteral : applyPattern)(chunk);
347                                literal = !literal;
348                        }
349                });
350                return applyAll(chunks.join(''));
351        }
352
353        function _buildDateTimeRE  (tokens, bundle, options, pattern){
354                        // based on and similar to dojo.date.locale._buildDateTimeRE
355                        //
356       
357                pattern = regexp.escapeString(pattern);
358                var locale = i18n.normalizeLocale(options.locale);
359       
360                return pattern.replace(/([a-z])\1*/ig, function(match){
361
362                                // Build a simple regexp.  Avoid captures, which would ruin the tokens list
363                                var s;
364                                var c = match.charAt(0);
365                                var l = match.length;
366                                var p2 = '', p3 = '';
367                                if(options.strict){
368                                        if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
369                                        if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
370                                }else{
371                                        p2 = '0?'; p3 = '0{0,2}';
372                                }
373                                switch(c){
374                                        case 'y':
375                                                s = '\\S+';
376                                                break;
377                                        case 'M':
378                                                if(locale.match('^he(?:-.+)?$')){
379                                                        s = (l>2) ? '\\S+ ?\\S+' : '\\S{1,4}';
380                                                }else{
381                                                        s = (l>2) ?  '\\S+ ?\\S+' : p2+'[1-9]|1[0-2]';
382                                                }
383                                                break;
384                                        case 'd':
385                                                if(locale.match('^he(?:-.+)?$')){
386                                                        s = '\\S[\'\"\'\u05F3]{1,2}\\S?';
387                                                }else{
388                                                        s = '[12]\\d|'+p2+'[1-9]|30';
389                                                }
390                                                break;
391                                        case 'E':
392                                                if(locale.match('^he(?:-.+)?$')){
393                                                        s = (l>3) ? '\\S+ ?\\S+' : '\\S';
394                                                }else{
395                                                        s = '\\S+';
396                                                }
397                                                break;
398                                        case 'h': //hour (1-12)
399                                                s = p2+'[1-9]|1[0-2]';
400                                                break;
401                                        case 'k': //hour (0-11)
402                                                s = p2+'\\d|1[01]';
403                                                break;
404                                        case 'H': //hour (0-23)
405                                                s = p2+'\\d|1\\d|2[0-3]';
406                                                break;
407                                        case 'K': //hour (1-24)
408                                                s = p2+'[1-9]|1\\d|2[0-4]';
409                                                break;
410                                        case 'm':
411                                        case 's':
412                                                s = p2+'\\d|[0-5]\\d';
413                                                break;
414                                        case 'S':
415                                                s = '\\d{'+l+'}';
416                                                break;
417                                        case 'a':
418                                                var am = options.am || bundle['dayPeriods-format-wide-am'],
419                                                        pm = options.pm || bundle['dayPeriods-format-wide-pm'];
420                                                if(options.strict){
421                                                        s = am + '|' + pm;
422                                                }else{
423                                                        s = am + '|' + pm;
424                                                        if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
425                                                        if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
426                                                }
427                                                break;
428                                        default:
429                                                s = ".*";
430                                }
431                                if(tokens){ tokens.push(match); }
432                                return "(" + s + ")"; // add capture
433                        }).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE. */
434        }
435
436        var _customFormats = [];
437        dojox.date.hebrew.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){
438                // summary:
439                //              Add a reference to a bundle containing localized custom formats to be
440                //              used by date/time formatting and parsing routines.
441                //
442                // description:
443                //              The user may add custom localized formats where the bundle has properties following the
444                //              same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
445                //              The pattern string should match the format used by the CLDR.
446                //              See dojo.date.locale.format() for details.
447                //              The resources must be loaded by dojo.requireLocalization() prior to use
448
449                _customFormats.push({pkg:packageName,name:bundleName});
450        };
451
452        dojox.date.hebrew.locale._getHebrewBundle = function(/*String*/locale){
453                var hebrew = {};
454                dojo.forEach(_customFormats, function(desc){
455                        var bundle = i18n.getLocalization(desc.pkg, desc.name, locale);
456                        hebrew = dojo.mixin(hebrew, bundle);
457                }, this);
458                return hebrew; /*Object*/
459        };
460
461        dojox.date.hebrew.locale.addCustomFormats("dojo.cldr","hebrew");
462
463        dojox.date.hebrew.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale, /*dojox.date.hebrew.Date?*/date){
464                // summary:
465                //              Used to get localized strings from dojo.cldr for day or month names.
466                //
467                // item:
468                //      'months' || 'days'
469                // type:
470                //      'wide' || 'narrow' || 'abbr' (e.g. "Monday", "Mon", or "M" respectively, in English)
471                // use:
472                //      'standAlone' || 'format' (default)
473                // locale:
474                //      override locale used to find the names
475                // date:
476                //      required for item=months to determine leap month name
477                //
478                // using  var monthNames = dojox.date.hebrew.locale.getNames('months', 'wide', 'format', 'he', new hebrewDate(5768, 2, 12));
479
480                var label,
481                        lookup = dojox.date.hebrew.locale._getHebrewBundle(locale),
482                        props = [item, context, type];
483                if(context == 'standAlone'){
484                        var key = props.join('-');
485                        label = lookup[key];
486                        // Fall back to 'format' flavor of name
487                        if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr
488                }
489                props[1] = 'format';
490       
491                // return by copy so changes won't be made accidentally to the in-memory model
492                var result = (label || lookup[props.join('-')]).concat();
493
494                if(item == "months"){
495                        if(date.isLeapYear(date.getFullYear())){
496                                // Adar I (6th position in the array) will be used.
497                                // Substitute the leap month Adar II for the regular Adar (7th position)
498                                props.push("leap");
499                                result[6] = lookup[props.join('-')];
500                        }else{
501                                // Remove Adar I but leave an empty position in the array
502                                delete result[5];
503                        }
504                }
505
506                return result; /*Array*/
507        };
508
509        return dojox.date.hebrew.locale;
510});
Note: See TracBrowser for help on using the repository browser.