source: Dev/branches/rest-dojo-ui/client/dojo/date/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: 21.1 KB
Line 
1define([
2        "../_base/kernel",
3        "../_base/lang",
4        "../_base/array",
5        "../date",
6        "../cldr/supplemental",
7        "../regexp",
8        "../string",
9        "../i18n!../cldr/nls/gregorian"
10], function(dojo, lang, array, date, cldr, regexp, string, gregorian) {
11        // module:
12        //              dojo/date/locale
13        // summary:
14        //              This modules defines dojo.date.locale, localization methods for Date.
15
16lang.getObject("date.locale", true, dojo);
17
18// Localization methods for Date.   Honor local customs using locale-dependent dojo.cldr data.
19
20// Load the bundles containing localization information for
21// names and formats
22
23//NOTE: Everything in this module assumes Gregorian calendars.
24// Other calendars will be implemented in separate modules.
25
26        // Format a pattern without literals
27        function formatPattern(dateObject, bundle, options, pattern){
28                return pattern.replace(/([a-z])\1*/ig, function(match){
29                        var s, pad,
30                                c = match.charAt(0),
31                                l = match.length,
32                                widthList = ["abbr", "wide", "narrow"];
33                        switch(c){
34                                case 'G':
35                                        s = bundle[(l < 4) ? "eraAbbr" : "eraNames"][dateObject.getFullYear() < 0 ? 0 : 1];
36                                        break;
37                                case 'y':
38                                        s = dateObject.getFullYear();
39                                        switch(l){
40                                                case 1:
41                                                        break;
42                                                case 2:
43                                                        if(!options.fullYear){
44                                                                s = String(s); s = s.substr(s.length - 2);
45                                                                break;
46                                                        }
47                                                        // fallthrough
48                                                default:
49                                                        pad = true;
50                                        }
51                                        break;
52                                case 'Q':
53                                case 'q':
54                                        s = Math.ceil((dateObject.getMonth()+1)/3);
55//                                      switch(l){
56//                                              case 1: case 2:
57                                                        pad = true;
58//                                                      break;
59//                                              case 3: case 4: // unimplemented
60//                                      }
61                                        break;
62                                case 'M':
63                                        var m = dateObject.getMonth();
64                                        if(l<3){
65                                                s = m+1; pad = true;
66                                        }else{
67                                                var propM = ["months", "format", widthList[l-3]].join("-");
68                                                s = bundle[propM][m];
69                                        }
70                                        break;
71                                case 'w':
72                                        var firstDay = 0;
73                                        s = dojo.date.locale._getWeekOfYear(dateObject, firstDay); pad = true;
74                                        break;
75                                case 'd':
76                                        s = dateObject.getDate(); pad = true;
77                                        break;
78                                case 'D':
79                                        s = dojo.date.locale._getDayOfYear(dateObject); pad = true;
80                                        break;
81                                case 'E':
82                                        var d = dateObject.getDay();
83                                        if(l<3){
84                                                s = d+1; pad = true;
85                                        }else{
86                                                var propD = ["days", "format", widthList[l-3]].join("-");
87                                                s = bundle[propD][d];
88                                        }
89                                        break;
90                                case 'a':
91                                        var timePeriod = (dateObject.getHours() < 12) ? 'am' : 'pm';
92                                        s = options[timePeriod] || bundle['dayPeriods-format-wide-' + timePeriod];
93                                        break;
94                                case 'h':
95                                case 'H':
96                                case 'K':
97                                case 'k':
98                                        var h = dateObject.getHours();
99                                        // strange choices in the date format make it impossible to write this succinctly
100                                        switch (c){
101                                                case 'h': // 1-12
102                                                        s = (h % 12) || 12;
103                                                        break;
104                                                case 'H': // 0-23
105                                                        s = h;
106                                                        break;
107                                                case 'K': // 0-11
108                                                        s = (h % 12);
109                                                        break;
110                                                case 'k': // 1-24
111                                                        s = h || 24;
112                                                        break;
113                                        }
114                                        pad = true;
115                                        break;
116                                case 'm':
117                                        s = dateObject.getMinutes(); pad = true;
118                                        break;
119                                case 's':
120                                        s = dateObject.getSeconds(); pad = true;
121                                        break;
122                                case 'S':
123                                        s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); pad = true;
124                                        break;
125                                case 'v': // FIXME: don't know what this is. seems to be same as z?
126                                case 'z':
127                                        // We only have one timezone to offer; the one from the browser
128                                        s = dojo.date.locale._getZone(dateObject, true, options);
129                                        if(s){break;}
130                                        l=4;
131                                        // fallthrough... use GMT if tz not available
132                                case 'Z':
133                                        var offset = dojo.date.locale._getZone(dateObject, false, options);
134                                        var tz = [
135                                                (offset<=0 ? "+" : "-"),
136                                                string.pad(Math.floor(Math.abs(offset)/60), 2),
137                                                string.pad(Math.abs(offset)% 60, 2)
138                                        ];
139                                        if(l==4){
140                                                tz.splice(0, 0, "GMT");
141                                                tz.splice(3, 0, ":");
142                                        }
143                                        s = tz.join("");
144                                        break;
145//                              case 'Y': case 'u': case 'W': case 'F': case 'g': case 'A': case 'e':
146//                                      console.log(match+" modifier unimplemented");
147                                default:
148                                        throw new Error("dojo.date.locale.format: invalid pattern char: "+pattern);
149                        }
150                        if(pad){ s = string.pad(s, l); }
151                        return s;
152                });
153        }
154
155/*=====
156        dojo.date.locale.__FormatOptions = function(){
157        //      selector: String
158        //              choice of 'time','date' (default: date and time)
159        //      formatLength: String
160        //              choice of long, short, medium or full (plus any custom additions).  Defaults to 'short'
161        //      datePattern:String
162        //              override pattern with this string
163        //      timePattern:String
164        //              override pattern with this string
165        //      am: String
166        //              override strings for am in times
167        //      pm: String
168        //              override strings for pm in times
169        //      locale: String
170        //              override the locale used to determine formatting rules
171        //      fullYear: Boolean
172        //              (format only) use 4 digit years whenever 2 digit years are called for
173        //      strict: Boolean
174        //              (parse only) strict parsing, off by default
175                this.selector = selector;
176                this.formatLength = formatLength;
177                this.datePattern = datePattern;
178                this.timePattern = timePattern;
179                this.am = am;
180                this.pm = pm;
181                this.locale = locale;
182                this.fullYear = fullYear;
183                this.strict = strict;
184        }
185=====*/
186
187dojo.date.locale._getZone = function(/*Date*/dateObject, /*boolean*/getName, /*dojo.date.locale.__FormatOptions?*/options){
188        // summary:
189        //              Returns the zone (or offset) for the given date and options.  This
190        //              is broken out into a separate function so that it can be overridden
191        //              by timezone-aware code.
192        //
193        // dateObject:
194        //              the date and/or time being formatted.
195        //
196        // getName:
197        //              Whether to return the timezone string (if true), or the offset (if false)
198        //
199        // options:
200        //              The options being used for formatting
201        if(getName){
202                return date.getTimezoneName(dateObject);
203        }else{
204                return dateObject.getTimezoneOffset();
205        }
206};
207
208
209dojo.date.locale.format = function(/*Date*/dateObject, /*dojo.date.locale.__FormatOptions?*/options){
210        // summary:
211        //              Format a Date object as a String, using locale-specific settings.
212        //
213        // description:
214        //              Create a string from a Date object using a known localized pattern.
215        //              By default, this method formats both date and time from dateObject.
216        //              Formatting patterns are chosen appropriate to the locale.  Different
217        //              formatting lengths may be chosen, with "full" used by default.
218        //              Custom patterns may be used or registered with translations using
219        //              the dojo.date.locale.addCustomFormats method.
220        //              Formatting patterns are implemented using [the syntax described at
221        //              unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
222        //
223        // dateObject:
224        //              the date and/or time to be formatted.  If a time only is formatted,
225        //              the values in the year, month, and day fields are irrelevant.  The
226        //              opposite is true when formatting only dates.
227
228        options = options || {};
229
230        var locale = dojo.i18n.normalizeLocale(options.locale),
231                formatLength = options.formatLength || 'short',
232                bundle = dojo.date.locale._getGregorianBundle(locale),
233                str = [],
234                sauce = lang.hitch(this, formatPattern, dateObject, bundle, options);
235        if(options.selector == "year"){
236                return _processPattern(bundle["dateFormatItem-yyyy"] || "yyyy", sauce);
237        }
238        var pattern;
239        if(options.selector != "date"){
240                pattern = options.timePattern || bundle["timeFormat-"+formatLength];
241                if(pattern){str.push(_processPattern(pattern, sauce));}
242        }
243        if(options.selector != "time"){
244                pattern = options.datePattern || bundle["dateFormat-"+formatLength];
245                if(pattern){str.push(_processPattern(pattern, sauce));}
246        }
247
248        return str.length == 1 ? str[0] : bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
249                function(match, key){ return str[key]; }); // String
250};
251
252dojo.date.locale.regexp = function(/*dojo.date.locale.__FormatOptions?*/options){
253        // summary:
254        //              Builds the regular needed to parse a localized date
255
256        return dojo.date.locale._parseInfo(options).regexp; // String
257};
258
259dojo.date.locale._parseInfo = function(/*dojo.date.locale.__FormatOptions?*/options){
260        options = options || {};
261        var locale = dojo.i18n.normalizeLocale(options.locale),
262                bundle = dojo.date.locale._getGregorianBundle(locale),
263                formatLength = options.formatLength || 'short',
264                datePattern = options.datePattern || bundle["dateFormat-" + formatLength],
265                timePattern = options.timePattern || bundle["timeFormat-" + formatLength],
266                pattern;
267        if(options.selector == 'date'){
268                pattern = datePattern;
269        }else if(options.selector == 'time'){
270                pattern = timePattern;
271        }else{
272                pattern = bundle["dateTimeFormat-"+formatLength].replace(/\{(\d+)\}/g,
273                        function(match, key){ return [timePattern, datePattern][key]; });
274        }
275
276        var tokens = [],
277                re = _processPattern(pattern, lang.hitch(this, _buildDateTimeRE, tokens, bundle, options));
278        return {regexp: re, tokens: tokens, bundle: bundle};
279};
280
281dojo.date.locale.parse = function(/*String*/value, /*dojo.date.locale.__FormatOptions?*/options){
282        // summary:
283        //              Convert a properly formatted string to a primitive Date object,
284        //              using locale-specific settings.
285        //
286        // description:
287        //              Create a Date object from a string using a known localized pattern.
288        //              By default, this method parses looking for both date and time in the string.
289        //              Formatting patterns are chosen appropriate to the locale.  Different
290        //              formatting lengths may be chosen, with "full" used by default.
291        //              Custom patterns may be used or registered with translations using
292        //              the dojo.date.locale.addCustomFormats method.
293        //
294        //              Formatting patterns are implemented using [the syntax described at
295        //              unicode.org](http://www.unicode.org/reports/tr35/tr35-4.html#Date_Format_Patterns)
296        //              When two digit years are used, a century is chosen according to a sliding
297        //              window of 80 years before and 20 years after present year, for both `yy` and `yyyy` patterns.
298        //              year < 100CE requires strict mode.
299        //
300        // value:
301        //              A string representation of a date
302
303        // remove non-printing bidi control chars from input and pattern
304        var controlChars = /[\u200E\u200F\u202A\u202E]/g,
305                info = dojo.date.locale._parseInfo(options),
306                tokens = info.tokens, bundle = info.bundle,
307                re = new RegExp("^" + info.regexp.replace(controlChars, "") + "$",
308                        info.strict ? "" : "i"),
309                match = re.exec(value && value.replace(controlChars, ""));
310
311        if(!match){ return null; } // null
312
313        var widthList = ['abbr', 'wide', 'narrow'],
314                result = [1970,0,1,0,0,0,0], // will get converted to a Date at the end
315                amPm = "",
316                valid = dojo.every(match, function(v, i){
317                if(!i){return true;}
318                var token=tokens[i-1];
319                var l=token.length;
320                switch(token.charAt(0)){
321                        case 'y':
322                                if(l != 2 && options.strict){
323                                        //interpret year literally, so '5' would be 5 A.D.
324                                        result[0] = v;
325                                }else{
326                                        if(v<100){
327                                                v = Number(v);
328                                                //choose century to apply, according to a sliding window
329                                                //of 80 years before and 20 years after present year
330                                                var year = '' + new Date().getFullYear(),
331                                                        century = year.substring(0, 2) * 100,
332                                                        cutoff = Math.min(Number(year.substring(2, 4)) + 20, 99);
333                                                result[0] = (v < cutoff) ? century + v : century - 100 + v;
334                                        }else{
335                                                //we expected 2 digits and got more...
336                                                if(options.strict){
337                                                        return false;
338                                                }
339                                                //interpret literally, so '150' would be 150 A.D.
340                                                //also tolerate '1950', if 'yyyy' input passed to 'yy' format
341                                                result[0] = v;
342                                        }
343                                }
344                                break;
345                        case 'M':
346                                if(l>2){
347                                        var months = bundle['months-format-' + widthList[l-3]].concat();
348                                        if(!options.strict){
349                                                //Tolerate abbreviating period in month part
350                                                //Case-insensitive comparison
351                                                v = v.replace(".","").toLowerCase();
352                                                months = dojo.map(months, function(s){ return s.replace(".","").toLowerCase(); } );
353                                        }
354                                        v = dojo.indexOf(months, v);
355                                        if(v == -1){
356//                                              console.log("dojo.date.locale.parse: Could not parse month name: '" + v + "'.");
357                                                return false;
358                                        }
359                                }else{
360                                        v--;
361                                }
362                                result[1] = v;
363                                break;
364                        case 'E':
365                        case 'e':
366                                var days = bundle['days-format-' + widthList[l-3]].concat();
367                                if(!options.strict){
368                                        //Case-insensitive comparison
369                                        v = v.toLowerCase();
370                                        days = dojo.map(days, function(d){return d.toLowerCase();});
371                                }
372                                v = dojo.indexOf(days, v);
373                                if(v == -1){
374//                                      console.log("dojo.date.locale.parse: Could not parse weekday name: '" + v + "'.");
375                                        return false;
376                                }
377
378                                //TODO: not sure what to actually do with this input,
379                                //in terms of setting something on the Date obj...?
380                                //without more context, can't affect the actual date
381                                //TODO: just validate?
382                                break;
383                        case 'D':
384                                result[1] = 0;
385                                // fallthrough...
386                        case 'd':
387                                result[2] = v;
388                                break;
389                        case 'a': //am/pm
390                                var am = options.am || bundle['dayPeriods-format-wide-am'],
391                                        pm = options.pm || bundle['dayPeriods-format-wide-pm'];
392                                if(!options.strict){
393                                        var period = /\./g;
394                                        v = v.replace(period,'').toLowerCase();
395                                        am = am.replace(period,'').toLowerCase();
396                                        pm = pm.replace(period,'').toLowerCase();
397                                }
398                                if(options.strict && v != am && v != pm){
399//                                      console.log("dojo.date.locale.parse: Could not parse am/pm part.");
400                                        return false;
401                                }
402
403                                // we might not have seen the hours field yet, so store the state and apply hour change later
404                                amPm = (v == pm) ? 'p' : (v == am) ? 'a' : '';
405                                break;
406                        case 'K': //hour (1-24)
407                                if(v == 24){ v = 0; }
408                                // fallthrough...
409                        case 'h': //hour (1-12)
410                        case 'H': //hour (0-23)
411                        case 'k': //hour (0-11)
412                                //TODO: strict bounds checking, padding
413                                if(v > 23){
414//                                      console.log("dojo.date.locale.parse: Illegal hours value");
415                                        return false;
416                                }
417
418                                //in the 12-hour case, adjusting for am/pm requires the 'a' part
419                                //which could come before or after the hour, so we will adjust later
420                                result[3] = v;
421                                break;
422                        case 'm': //minutes
423                                result[4] = v;
424                                break;
425                        case 's': //seconds
426                                result[5] = v;
427                                break;
428                        case 'S': //milliseconds
429                                result[6] = v;
430//                              break;
431//                      case 'w':
432//TODO                          var firstDay = 0;
433//                      default:
434//TODO: throw?
435//                              console.log("dojo.date.locale.parse: unsupported pattern char=" + token.charAt(0));
436                }
437                return true;
438        });
439
440        var hours = +result[3];
441        if(amPm === 'p' && hours < 12){
442                result[3] = hours + 12; //e.g., 3pm -> 15
443        }else if(amPm === 'a' && hours == 12){
444                result[3] = 0; //12am -> 0
445        }
446
447        //TODO: implement a getWeekday() method in order to test
448        //validity of input strings containing 'EEE' or 'EEEE'...
449
450        var dateObject = new Date(result[0], result[1], result[2], result[3], result[4], result[5], result[6]); // Date
451        if(options.strict){
452                dateObject.setFullYear(result[0]);
453        }
454
455        // Check for overflow.  The Date() constructor normalizes things like April 32nd...
456        //TODO: why isn't this done for times as well?
457        var allTokens = tokens.join(""),
458                dateToken = allTokens.indexOf('d') != -1,
459                monthToken = allTokens.indexOf('M') != -1;
460
461        if(!valid ||
462                (monthToken && dateObject.getMonth() > result[1]) ||
463                (dateToken && dateObject.getDate() > result[2])){
464                return null;
465        }
466
467        // Check for underflow, due to DST shifts.  See #9366
468        // This assumes a 1 hour dst shift correction at midnight
469        // We could compare the timezone offset after the shift and add the difference instead.
470        if((monthToken && dateObject.getMonth() < result[1]) ||
471                (dateToken && dateObject.getDate() < result[2])){
472                dateObject = date.add(dateObject, "hour", 1);
473        }
474
475        return dateObject; // Date
476};
477
478function _processPattern(pattern, applyPattern, applyLiteral, applyAll){
479        //summary: Process a pattern with literals in it
480
481        // Break up on single quotes, treat every other one as a literal, except '' which becomes '
482        var identity = function(x){return x;};
483        applyPattern = applyPattern || identity;
484        applyLiteral = applyLiteral || identity;
485        applyAll = applyAll || identity;
486
487        //split on single quotes (which escape literals in date format strings)
488        //but preserve escaped single quotes (e.g., o''clock)
489        var chunks = pattern.match(/(''|[^'])+/g),
490                literal = pattern.charAt(0) == "'";
491
492        dojo.forEach(chunks, function(chunk, i){
493                if(!chunk){
494                        chunks[i]='';
495                }else{
496                        chunks[i]=(literal ? applyLiteral : applyPattern)(chunk.replace(/''/g, "'"));
497                        literal = !literal;
498                }
499        });
500        return applyAll(chunks.join(''));
501}
502
503function _buildDateTimeRE(tokens, bundle, options, pattern){
504        pattern = regexp.escapeString(pattern);
505        if(!options.strict){ pattern = pattern.replace(" a", " ?a"); } // kludge to tolerate no space before am/pm
506        return pattern.replace(/([a-z])\1*/ig, function(match){
507                // Build a simple regexp.  Avoid captures, which would ruin the tokens list
508                var s,
509                        c = match.charAt(0),
510                        l = match.length,
511                        p2 = '', p3 = '';
512                if(options.strict){
513                        if(l > 1){ p2 = '0' + '{'+(l-1)+'}'; }
514                        if(l > 2){ p3 = '0' + '{'+(l-2)+'}'; }
515                }else{
516                        p2 = '0?'; p3 = '0{0,2}';
517                }
518                switch(c){
519                        case 'y':
520                                s = '\\d{2,4}';
521                                break;
522                        case 'M':
523                                s = (l>2) ? '\\S+?' : '1[0-2]|'+p2+'[1-9]';
524                                break;
525                        case 'D':
526                                s = '[12][0-9][0-9]|3[0-5][0-9]|36[0-6]|'+p2+'[1-9][0-9]|'+p3+'[1-9]';
527                                break;
528                        case 'd':
529                                s = '3[01]|[12]\\d|'+p2+'[1-9]';
530                                break;
531                        case 'w':
532                                s = '[1-4][0-9]|5[0-3]|'+p2+'[1-9]';
533                                break;
534                        case 'E':
535                                s = '\\S+';
536                                break;
537                        case 'h': //hour (1-12)
538                                s = '1[0-2]|'+p2+'[1-9]';
539                                break;
540                        case 'k': //hour (0-11)
541                                s = '1[01]|'+p2+'\\d';
542                                break;
543                        case 'H': //hour (0-23)
544                                s = '1\\d|2[0-3]|'+p2+'\\d';
545                                break;
546                        case 'K': //hour (1-24)
547                                s = '1\\d|2[0-4]|'+p2+'[1-9]';
548                                break;
549                        case 'm':
550                        case 's':
551                                s = '[0-5]\\d';
552                                break;
553                        case 'S':
554                                s = '\\d{'+l+'}';
555                                break;
556                        case 'a':
557                                var am = options.am || bundle['dayPeriods-format-wide-am'],
558                                        pm = options.pm || bundle['dayPeriods-format-wide-pm'];
559                                        s = am + '|' + pm;
560                                if(!options.strict){
561                                        if(am != am.toLowerCase()){ s += '|' + am.toLowerCase(); }
562                                        if(pm != pm.toLowerCase()){ s += '|' + pm.toLowerCase(); }
563                                        if(s.indexOf('.') != -1){ s += '|' + s.replace(/\./g, ""); }
564                                }
565                                s = s.replace(/\./g, "\\.");
566                                break;
567                        default:
568                        // case 'v':
569                        // case 'z':
570                        // case 'Z':
571                                s = ".*";
572//                              console.log("parse of date format, pattern=" + pattern);
573                }
574
575                if(tokens){ tokens.push(match); }
576
577                return "(" + s + ")"; // add capture
578        }).replace(/[\xa0 ]/g, "[\\s\\xa0]"); // normalize whitespace.  Need explicit handling of \xa0 for IE.
579}
580
581var _customFormats = [];
582dojo.date.locale.addCustomFormats = function(/*String*/packageName, /*String*/bundleName){
583        // summary:
584        //              Add a reference to a bundle containing localized custom formats to be
585        //              used by date/time formatting and parsing routines.
586        //
587        // description:
588        //              The user may add custom localized formats where the bundle has properties following the
589        //              same naming convention used by dojo.cldr: `dateFormat-xxxx` / `timeFormat-xxxx`
590        //              The pattern string should match the format used by the CLDR.
591        //              See dojo.date.locale.format() for details.
592        //              The resources must be loaded by dojo.requireLocalization() prior to use
593
594        _customFormats.push({pkg:packageName,name:bundleName});
595};
596
597dojo.date.locale._getGregorianBundle = function(/*String*/locale){
598        var gregorian = {};
599        dojo.forEach(_customFormats, function(desc){
600                var bundle = dojo.i18n.getLocalization(desc.pkg, desc.name, locale);
601                gregorian = lang.mixin(gregorian, bundle);
602        }, this);
603        return gregorian; /*Object*/
604};
605
606dojo.date.locale.addCustomFormats("dojo.cldr","gregorian");
607
608dojo.date.locale.getNames = function(/*String*/item, /*String*/type, /*String?*/context, /*String?*/locale){
609        // summary:
610        //              Used to get localized strings from dojo.cldr for day or month names.
611        //
612        // item:
613        //      'months' || 'days'
614        // type:
615        //      'wide' || 'abbr' || 'narrow' (e.g. "Monday", "Mon", or "M" respectively, in English)
616        // context:
617        //      'standAlone' || 'format' (default)
618        // locale:
619        //      override locale used to find the names
620
621        var label,
622                lookup = dojo.date.locale._getGregorianBundle(locale),
623                props = [item, context, type];
624        if(context == 'standAlone'){
625                var key = props.join('-');
626                label = lookup[key];
627                // Fall back to 'format' flavor of name
628                if(label[0] == 1){ label = undefined; } // kludge, in the absence of real aliasing support in dojo.cldr
629        }
630        props[1] = 'format';
631
632        // return by copy so changes won't be made accidentally to the in-memory model
633        return (label || lookup[props.join('-')]).concat(); /*Array*/
634};
635
636dojo.date.locale.isWeekend = function(/*Date?*/dateObject, /*String?*/locale){
637        // summary:
638        //      Determines if the date falls on a weekend, according to local custom.
639
640        var weekend = cldr.getWeekend(locale),
641                day = (dateObject || new Date()).getDay();
642        if(weekend.end < weekend.start){
643                weekend.end += 7;
644                if(day < weekend.start){ day += 7; }
645        }
646        return day >= weekend.start && day <= weekend.end; // Boolean
647};
648
649// These are used only by format and strftime.  Do they need to be public?  Which module should they go in?
650
651dojo.date.locale._getDayOfYear = function(/*Date*/dateObject){
652        // summary: gets the day of the year as represented by dateObject
653        return date.difference(new Date(dateObject.getFullYear(), 0, 1, dateObject.getHours()), dateObject) + 1; // Number
654};
655
656dojo.date.locale._getWeekOfYear = function(/*Date*/dateObject, /*Number*/firstDayOfWeek){
657        if(arguments.length == 1){ firstDayOfWeek = 0; } // Sunday
658
659        var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1).getDay(),
660                adj = (firstDayOfYear - firstDayOfWeek + 7) % 7,
661                week = Math.floor((dojo.date.locale._getDayOfYear(dateObject) + adj - 1) / 7);
662
663        // if year starts on the specified day, start counting weeks at 1
664        if(firstDayOfYear == firstDayOfWeek){ week++; }
665
666        return week; // Number
667};
668
669return dojo.date.locale;
670});
Note: See TracBrowser for help on using the repository browser.