source: Dev/trunk/src/client/dojox/date/timezone.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 22.3 KB
Line 
1/******************************************************************************
2 * Dojo port of fleegix date plugin from
3 *
4 *   http://js.fleegix.org/plugins/date/date
5 *
6 * contributed to Dojo under CLA, with thanks to Matthew Eernisse (mde@fleegix.org)
7 * and Open Source Applications Foundation
8 *
9 * Credits: Ideas included from incomplete JS implementation of Olson
10 * parser, "XMLDate" by Philippe Goetz (philippe.goetz@wanadoo.fr)
11 *****************************************************************************/
12
13define(["dojo", "dojo/date", "dojo/date/locale", "dojo/_base/array", "dojo/_base/xhr"],
14        function(dojo, _dd, _ddl){
15
16        dojo.experimental("dojox.date.timezone");
17        dojo.getObject("date.timezone", true, dojox);
18
19        var cfg = dojo.config;
20        var _zoneFiles = [ "africa", "antarctica", "asia", "australasia", "backward",
21                                        "etcetera", "europe", "northamerica", "pacificnew",
22                                        "southamerica" ];
23                                       
24        // Our mins an maxes for years that we care about
25        var _minYear = 1835,
26                _maxYear = 2038;
27       
28        var _loadedZones = {},
29                _zones = {},
30                _loadedRanges = {},
31                _rules = {};
32       
33        // loadingScheme: String
34        //              One of "preloadAll", "lazyLoad" (Defaults "lazyLoad")
35        var loadingScheme = cfg.timezoneLoadingScheme || "preloadAll";
36               
37        // defaultZoneFile: String or String[]
38        //              The default file (or files) to load on startup - other files will
39        //              be lazily-loaded on-demand
40        var defaultZoneFile = cfg.defaultZoneFile ||
41                                        ((loadingScheme == "preloadAll") ? _zoneFiles : "northamerica");
42
43        // Set our olson-zoneinfo content handler
44        dojo._contentHandlers["olson-zoneinfo"] = function(xhr){
45                var str = dojo._contentHandlers["text"](xhr),
46                        s = "",
47                        lines = str.split("\n"),
48                        arr = [],
49                        chunk = "",
50                        zone = null,
51                        rule = null,
52                        ret = {zones: {}, rules: {}};
53
54                for(var i = 0; i < lines.length; i++){
55                        var l = lines[i];
56                        if(l.match(/^\s/)){
57                                l = "Zone " + zone + l;
58                        }
59                        l = l.split("#")[0];
60                        if(l.length > 3){
61                                arr = l.split(/\s+/);
62                                chunk = arr.shift();
63                                switch(chunk){
64                                        case 'Zone':
65                                                zone = arr.shift();
66                                                if(arr[0]){
67                                                        // Handle extra commas in the middle of a zone
68                                                        if(!ret.zones[zone]){ ret.zones[zone] = []; }
69                                                        ret.zones[zone].push(arr);
70                                                }
71                                                break;
72                                        case 'Rule':
73                                                rule = arr.shift();
74                                                if(!ret.rules[rule]){ ret.rules[rule] = []; }
75                                                ret.rules[rule].push(arr);
76                                                break;
77                                        case 'Link':
78                                                // No zones for these should already exist
79                                                if(ret.zones[arr[1]]){
80                                                  throw new Error('Error with Link ' + arr[1]);
81                                                }
82                                                // Create the link
83                                                ret.zones[arr[1]] = arr[0];
84                                                break;
85                                        case 'Leap':
86                                                break;
87                                        default:
88                                                // Fail silently
89                                                break;
90                                }
91                        }
92                }
93                return ret; // Object
94        };
95       
96        function loadZoneData(/* Object */ data){
97                // summary:
98                //              Loads the given data object into the zone database
99                // data: Object
100                //              The data to load - contains "zones" and "rules" parameters
101                data = data || {};
102                _zones = dojo.mixin(_zones, data.zones||{});
103                _rules = dojo.mixin(_rules, data.rules||{});
104        }
105       
106        function loadZoneFile(/* String */ fileName){
107                // summary:
108                //              Loads the given URL of the Olson zone information into the
109                //              zone database
110                //
111                // fileName: String
112                //              The zoneinfo file name to load
113               
114                // TODO: Maybe behave similar to requireLocalization - rather than
115                //              Using dojo.xhrGet?
116                _loadedZones[fileName] = true;
117                dojo.xhrGet({
118                        url: require.toUrl((cfg.timezoneFileBasePath || "dojox/date/zoneinfo") + "/" + fileName),
119                        sync: true, // Needs to be synchronous so we can return values
120                        handleAs: "olson-zoneinfo",
121                        load: loadZoneData,
122                        error: function(e){
123                                console.error("Error loading zone file:", e);
124                                throw e;
125                        }
126                });
127        }
128       
129        var monthMap = { 'jan': 0, 'feb': 1, 'mar': 2, 'apr': 3,'may': 4, 'jun': 5,
130                                'jul': 6, 'aug': 7, 'sep': 8, 'oct': 9, 'nov': 10, 'dec': 11 },
131                dayMap = {'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4,
132                                'fri': 5, 'sat': 6 },
133                regionMap = {'EST': "northamerica", 'MST': "northamerica",
134                                        'HST': "northamerica", 'EST5EDT': "northamerica",
135                                        'CST6CDT': "northamerica", 'MST7MDT': "northamerica",
136                                        'PST8PDT': "northamerica", 'America': "northamerica",
137                                        'Pacific': "australasia", 'Atlantic': "europe",
138                                        'Africa': "africa", 'Indian': "africa",
139                                        'Antarctica': "antarctica", 'Asia': "asia",
140                                        'Australia': "australasia", 'Europe': "europe",
141                                        'WET': "europe", 'CET': "europe", 'MET': "europe",
142                                        'EET': "europe"},
143                regionExceptions = {'Pacific/Honolulu':"northamerica",
144                                                        'Atlantic/Bermuda':"northamerica",
145                                                        'Atlantic/Cape_Verde':"africa",
146                                                        'Atlantic/St_Helena':"africa",
147                                                        'Indian/Kerguelen':"antarctica",
148                                                        'Indian/Chagos':"asia",
149                                                        'Indian/Maldives':"asia",
150                                                        'Indian/Christmas':"australasia",
151                                                        'Indian/Cocos':"australasia",
152                                                        'America/Danmarkshavn':"europe",
153                                                        'America/Scoresbysund':"europe",
154                                                        'America/Godthab':"europe",
155                                                        'America/Thule':"europe",
156                                                        'Asia/Yekaterinburg':"europe",
157                                                        'Asia/Omsk':"europe",
158                                                        'Asia/Novosibirsk':"europe",
159                                                        'Asia/Krasnoyarsk':"europe",
160                                                        'Asia/Irkutsk':"europe",
161                                                        'Asia/Yakutsk':"europe",
162                                                        'Asia/Vladivostok':"europe",
163                                                        'Asia/Sakhalin':"europe",
164                                                        'Asia/Magadan':"europe",
165                                                        'Asia/Kamchatka':"europe",
166                                                        'Asia/Anadyr':"europe",
167                                                        'Africa/Ceuta':"europe",
168                                                        'America/Argentina/Buenos_Aires':"southamerica",
169                                                        'America/Argentina/Cordoba':"southamerica",
170                                                        'America/Argentina/Tucuman':"southamerica",
171                                                        'America/Argentina/La_Rioja':"southamerica",
172                                                        'America/Argentina/San_Juan':"southamerica",
173                                                        'America/Argentina/Jujuy':"southamerica",
174                                                        'America/Argentina/Catamarca':"southamerica",
175                                                        'America/Argentina/Mendoza':"southamerica",
176                                                        'America/Argentina/Rio_Gallegos':"southamerica",
177                                                        'America/Argentina/Ushuaia':"southamerica",
178                                                        'America/Aruba':"southamerica",
179                                                        'America/La_Paz':"southamerica",
180                                                        'America/Noronha':"southamerica",
181                                                        'America/Belem':"southamerica",
182                                                        'America/Fortaleza':"southamerica",
183                                                        'America/Recife':"southamerica",
184                                                        'America/Araguaina':"southamerica",
185                                                        'America/Maceio':"southamerica",
186                                                        'America/Bahia':"southamerica",
187                                                        'America/Sao_Paulo':"southamerica",
188                                                        'America/Campo_Grande':"southamerica",
189                                                        'America/Cuiaba':"southamerica",
190                                                        'America/Porto_Velho':"southamerica",
191                                                        'America/Boa_Vista':"southamerica",
192                                                        'America/Manaus':"southamerica",
193                                                        'America/Eirunepe':"southamerica",
194                                                        'America/Rio_Branco':"southamerica",
195                                                        'America/Santiago':"southamerica",
196                                                        'Pacific/Easter':"southamerica",
197                                                        'America/Bogota':"southamerica",
198                                                        'America/Curacao':"southamerica",
199                                                        'America/Guayaquil':"southamerica",
200                                                        'Pacific/Galapagos':"southamerica",
201                                                        'Atlantic/Stanley':"southamerica",
202                                                        'America/Cayenne':"southamerica",
203                                                        'America/Guyana':"southamerica",
204                                                        'America/Asuncion':"southamerica",
205                                                        'America/Lima':"southamerica",
206                                                        'Atlantic/South_Georgia':"southamerica",
207                                                        'America/Paramaribo':"southamerica",
208                                                        'America/Port_of_Spain':"southamerica",
209                                                        'America/Montevideo':"southamerica",
210                                                        'America/Caracas':"southamerica"},
211                abbrExceptions = { 'US': "S", 'Chatham': "S", 'NZ': "S", 'NT_YK': "S",
212                                                        'Edm': "S", 'Salv': "S", 'Canada': "S", 'StJohns': "S",
213                                                        'TC': "S", 'Guat': "S", 'Mexico': "S", 'Haiti': "S",
214                                                        'Barb': "S", 'Belize': "S", 'CR': "S", 'Moncton': "S",
215                                                        'Swift': "S", 'Hond': "S", 'Thule': "S", 'NZAQ': "S",
216                                                        'Zion': "S", 'ROK': "S", 'PRC': "S", 'Taiwan': "S",
217                                                        'Ghana': "GMT", 'SL': "WAT", 'Chicago': "S",
218                                                        'Detroit': "S", 'Vanc': "S", 'Denver': "S",
219                                                        'Halifax': "S", 'Cuba': "S", 'Indianapolis': "S",
220                                                        'Starke': "S", 'Marengo': "S", 'Pike': "S",
221                                                        'Perry': "S", 'Vincennes': "S", 'Pulaski': "S",
222                                                        'Louisville': "S", 'CA': "S", 'Nic': "S",
223                                                        'Menominee': "S", 'Mont': "S", 'Bahamas': "S",
224                                                        'NYC': "S", 'Regina': "S", 'Resolute': "ES",
225                                                        'DR': "S", 'Toronto': "S", 'Winn': "S" };
226       
227        function invalidTZError(t) {
228                throw new Error('Timezone "' + t +
229                                '" is either incorrect, or not loaded in the timezone registry.');
230        }
231       
232        function getRegionForTimezone(/* String */ tz) {
233                // summary:
234                //              Returns the Olson region for the given timezone
235                var ret = regionExceptions[tz];
236                if(!ret){
237                        var reg = tz.split('/')[0];
238                        ret = regionMap[reg];
239                        // If there's nothing listed in the main regions for
240                        // this TZ, check the 'backward' links
241                        if(!ret){
242                                var link = _zones[tz];
243                                if(typeof link == 'string'){
244                                        return getRegionForTimezone(link); // String
245                                }else{
246                                        // Backward-compat file hasn't loaded yet, try looking in there
247                                        if (!_loadedZones.backward) {
248                                                // This is for obvious legacy zones (e.g., Iceland) that
249                                                // don't even have a prefix like "America/" that look like
250                                                // normal zones
251                                                loadZoneFile("backward");
252                                                return getRegionForTimezone(tz); // String
253                                        }else{
254                                                invalidTZError(tz);
255                                        }
256                                }
257                        }
258                }
259                return ret; // String
260        }
261       
262        function parseTimeString(/* String */ str) {
263                // summary:
264                //              Parses the given time string and returns it as an integer array
265                var pat = /(\d+)(?::0*(\d*))?(?::0*(\d*))?([su])?$/;
266                var hms = str.match(pat);
267                if(!hms){
268                        return null;
269                }
270                hms[1] = parseInt(hms[1], 10);
271                hms[2] = hms[2] ? parseInt(hms[2], 10) : 0;
272                hms[3] = hms[3] ? parseInt(hms[3], 10) : 0;
273                return hms; // int[]
274        }
275       
276        function getUTCStamp(/* int */ y, /* int */ m, /* int */ d, /* int */ h,
277                                                /* int */ mn, /* int */ s, /* int? */ off){
278                // summary:
279                //              Returns the UTC timestamp, adjusted by the given (optional) offset
280                return Date.UTC(y, m, d, h, mn, s) + ((off||0) * 60 * 1000);
281        }
282       
283        function getMonthNumber(/* String */ m){
284                // summary:
285                //              Returns the javascript month number for the given string
286                return monthMap[m.substr(0, 3).toLowerCase()];
287        }
288       
289        function getOffsetInMins(/* String */ str){
290                // summary:
291                //              Returns the offset value represented by the string, in minutes
292                var off = parseTimeString(str);
293                if(off === null){ return 0; }
294                var adj = str.indexOf('-') === 0 ? -1 : 1;
295                off = adj * (((off[1] * 60 + off[2]) *60 + off[3]) * 1000);
296                return -off/60/1000;
297        }
298
299        function _getRuleStart(/* Rule */ rule, /* int */ year, /* int */ off){
300                // summary:
301                //              Returns a date that the rule begins matching in the given year.
302                var month = getMonthNumber(rule[3]),
303                        day = rule[4],
304                        time = parseTimeString(rule[5]);
305                if(time[4] == "u"){
306                        // We are UTC - so there is no offset to use
307                        off = 0;
308                }
309               
310                var d, dtDay, incr;
311                if(isNaN(day)){
312                        if(day.substr(0, 4) == "last"){
313                                // Last day of the month at the desired time of day
314                                day = dayMap[day.substr(4,3).toLowerCase()];
315                                d = new Date(getUTCStamp(year, month + 1, 1,
316                                                                                time[1] - 24, time[2], time[3],
317                                                                                off));
318                                dtDay = _dd.add(d, "minute", -off).getUTCDay();
319                                // Set it to the final day of the correct weekday that month
320                                incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
321                                if(incr !== 0){
322                                        d = _dd.add(d, "hour", incr * 24);
323                                }
324                                return d;
325                        }else{
326                                day = dayMap[day.substr(0, 3).toLowerCase()];
327                                if(day != "undefined"){
328                                        if(rule[4].substr(3, 2) == '>='){
329                                                // The stated date of the month
330                                                d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10),
331                                                                        time[1], time[2], time[3], off));
332                                                dtDay = _dd.add(d, "minute", -off).getUTCDay();
333                                                // Set to the first correct weekday after the stated date
334                                                incr = (day < dtDay) ? (day - dtDay + 7) : (day - dtDay);
335                                                if(incr !== 0){
336                                                        d = _dd.add(d, "hour", incr * 24);
337                                                }
338                                                return d;
339                                        }else if(day.substr(3, 2) == '<='){
340                                                // The stated date of the month
341                                                d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10),
342                                                                        time[1], time[2], time[3], off));
343                                                dtDay = _dd.add(d, "minute", -off).getUTCDay();
344                                                // Set to first correct weekday before the stated date
345                                                incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
346                                                if(incr !== 0){
347                                                        d = _dd.add(d, "hour", incr * 24);
348                                                }
349                                                return d;
350                                        }
351                                }
352                        }
353                }else{
354                        // Numeric date
355                        d = new Date(getUTCStamp(year, month, parseInt(day, 10),
356                                                time[1], time[2], time[3], off));
357                        return d;
358                }
359                return null;
360        }
361
362        function _getRulesForYear(/* Zone */ zone, /* int */ year){
363                var rules = [];
364                dojo.forEach(_rules[zone[1]]||[], function(r){
365                        // Clean up rules as needed
366                        for(var i = 0; i < 2; i++){
367                                switch(r[i]){
368                                        case "min":
369                                                r[i] = _minYear;
370                                                break;
371                                        case "max":
372                                                r[i] = _maxYear;
373                                                break;
374                                        case "only":
375                                                break;
376                                        default:
377                                                r[i] = parseInt(r[i], 10);
378                                                if(isNaN(r[i])){
379                                                        throw new Error('Invalid year found on rule');
380                                                }
381                                                break;
382                                }
383                        }
384                        if(typeof r[6] == "string"){
385                                // Change our offset to be an integer
386                                r[6] = getOffsetInMins(r[6]);
387                        }
388                       
389                        // Quick-filter to grab all rules that match my year
390                        if((r[0] <= year && r[1] >= year) || // Matches my y
391                                (r[0] == year && r[1] == "only")){ // Matches my only
392                                rules.push({r: r, d: _getRuleStart(r, year, zone[0])});
393                        }
394                });
395                return rules;
396        }
397
398
399        function _loadZoneRanges(/* String */ tz, /* Object[] */ zoneList) {
400                // summary:
401                //              Loads the zone ranges for the given timezone
402               
403                var zr = _loadedRanges[tz] = [];
404                for(var i = 0; i < zoneList.length; i++){
405                        var z = zoneList[i];
406                        var r = zr[i] = [];
407                        var prevZone = null;
408                        var prevRange = null;
409                        var prevRules = [];
410                       
411                        // Set up our zone offset to not be a string anymore
412                        if(typeof z[0] == "string"){
413                                z[0] = getOffsetInMins(z[0]);
414                        }
415                       
416                        if(i === 0){
417                                // The beginning of zoneinfo time - let's not worry about
418                                // to-the-hour accuracy before Jan 1, 1835
419                                r[0] = Date.UTC(_minYear,0,1,0,0,0,0);
420                        }else{
421                                r[0] = zr[i - 1][1];
422                                prevZone = zoneList[i - 1];
423                                prevRange = zr[i - 1];
424                                prevRules = prevRange[2];
425                        }
426
427                        // Load the rules that will be going in to our zone
428                        var startYear = new Date(r[0]).getUTCFullYear();
429                        var endYear = z[3] ? parseInt(z[3], 10) : _maxYear;
430                        var rlz = [];
431                        var j;
432                        for(j = startYear; j <= endYear; j++){
433                                rlz = rlz.concat(_getRulesForYear(z, j));
434                        }
435                        rlz.sort(function(a, b){
436                                return _dd.compare(a.d, b.d);
437                        });
438                        var rl;
439                        for(j = 0, rl; (rl = rlz[j]); j++){
440                                var prevRule = j > 0 ? rlz[j - 1] : null;
441                                if(rl.r[5].indexOf("u") < 0 && rl.r[5].indexOf("s") < 0){
442                                        if(j === 0 && i > 0){
443                                                if(prevRules.length){
444                                                        // We have a previous rule - so use it
445                                                        rl.d = _dd.add(rl.d, "minute", prevRules[prevRules.length - 1].r[6]);
446                                                }else if(_dd.compare(new Date(prevRange[1]), rl.d, "date") === 0){
447                                                        // No previous rules - but our date is the same as the
448                                                        // previous zone ended on - so use that.
449                                                        rl.d = new Date(prevRange[1]);
450                                                }else{
451                                                        rl.d = _dd.add(rl.d, "minute", getOffsetInMins(prevZone[1]));
452                                                }
453                                        }else if(j > 0){
454                                                rl.d = _dd.add(rl.d, "minute", prevRule.r[6]);
455                                        }
456                                }
457                        }
458                        r[2] = rlz;
459
460                        if(!z[3]){
461                                // The end of zoneinfo time - we'll cross this bridge when we
462                                // get close to Dec 31, 2038
463                                r[1] = Date.UTC(_maxYear,11,31,23,59,59,999);
464                        }else{
465                                var year = parseInt(z[3], 10),
466                                        month = getMonthNumber(z[4]||"Jan"),
467                                        day = parseInt(z[5]||"1", 10),
468                                        time = parseTimeString(z[6]||"0");
469                                var utcStmp = r[1] = getUTCStamp(year, month, day,
470                                                                        time[1], time[2], time[3],
471                                                                        ((time[4] == "u") ? 0 : z[0]));
472                                if(isNaN(utcStmp)){
473                                        utcStmp = r[1] = _getRuleStart([0,0,0,z[4],z[5],z[6]||"0"],
474                                                                                        year, ((time[4] == "u") ? 0 : z[0])).getTime();
475                                }
476                                var matches = dojo.filter(rlz, function(rl, idx){
477                                        var o = idx > 0 ? rlz[idx - 1].r[6] * 60 * 1000 : 0;
478                                        return (rl.d.getTime() < utcStmp + o);
479                                });
480                                if(time[4] != "u" && time[4] != "s"){
481                                        if(matches.length){
482                                                r[1] += matches[matches.length - 1].r[6] * 60 * 1000;
483                                        }else{
484                                                r[1] += getOffsetInMins(z[1]) * 60 * 1000;
485                                        }
486                                }
487                        }
488                }
489        }
490       
491        function getZoneInfo(/* String */ dt, /* String */ tz) {
492                // summary:
493                //              Returns the zone entry from the zoneinfo database for the given date
494                //              and timezone
495                var t = tz;
496                var zoneList = _zones[t];
497
498                // Follow links to get to an actual zone
499                while(typeof zoneList == "string"){
500                        t = zoneList;
501                        zoneList = _zones[t];
502                }
503                if(!zoneList){
504                        // Backward-compat file hasn't loaded yet, try looking in there
505                        if(!_loadedZones.backward){
506                                // This is for backward entries like "America/Fort_Wayne" that
507                                // getRegionForTimezone *thinks* it has a region file and zone
508                                // for (e.g., America => 'northamerica'), but in reality it's a
509                                // legacy zone we need the backward file for
510                                var parsed = loadZoneFile("backward", true);
511                                return getZoneInfo(dt, tz); //Object
512                        }
513                        invalidTZError(t);
514                }
515               
516                if(!_loadedRanges[tz]){
517                        _loadZoneRanges(tz, zoneList);
518                }
519                var ranges = _loadedRanges[tz];
520                var tm = dt.getTime();
521                for(var i = 0, r; (r = ranges[i]); i++){
522                        if(tm >= r[0] && tm < r[1]){
523                                return {zone: zoneList[i], range: ranges[i], idx: i};
524                        }
525                }
526                throw new Error('No Zone found for "' + tz + '" on ' + dt);
527        }
528       
529        function getRule(/* Date */ dt, /* ZoneInfo */ zoneInfo) {
530                // summary:
531                //              Returns the latest-matching rule entry from the zoneinfo
532                //              database for the given date and zone
533               
534                var lastMatch = -1;
535                var rules = zoneInfo.range[2]||[];
536                var tsp = dt.getTime();
537                var zr = zoneInfo.range;
538                for(var i = 0, r; (r = rules[i]); i++){
539                        if(tsp >= r.d.getTime()){
540                                lastMatch = i;
541                        }
542                }
543                if(lastMatch >= 0){
544                        return rules[lastMatch].r;
545                }
546                return null;
547        }
548 
549        function getAbbreviation(/* String */ tz, /* Object */ zoneInfo, /* Object */ rule) {
550                // summary:
551                //              Returns the abbreviation for the given zone and rule
552                var res;
553                var zone = zoneInfo.zone;
554                var base = zone[2];
555                if(base.indexOf('%s') > -1){
556                        var repl;
557                        if(rule){
558                                repl = rule[7];
559                                if(repl == "-"){ repl = ""; }
560                        }else if(zone[1] in abbrExceptions){
561                                repl = abbrExceptions[zone[1]];
562                        }else{
563                                if(zoneInfo.idx > 0){
564                                        // Check if our previous zone's base is the same as our
565                                        // current in "S" (standard) mode.  If so, then use "S"
566                                        // for our replacement
567                                        var pz = _zones[tz][zoneInfo.idx - 1];
568                                        var pb = pz[2];
569                                        if(pb.indexOf('%s') < 0){
570                                                if(base.replace('%s', "S") == pb){
571                                                        repl = "S";
572                                                }else{
573                                                        repl = "";
574                                                }
575                                        }else{
576                                                repl = "";
577                                        }
578                                }else{
579                                        repl = "";
580                                }
581                        }
582                        res = base.replace('%s', repl);
583                }else if(base.indexOf("/") > -1){
584                        var bs = base.split("/");
585                        if(rule){
586                                res = bs[rule[6] === 0 ? 0 : 1];
587                        }else{
588                                res = bs[0];
589                        }
590                }else{
591                        res = base;
592                }
593                return res; // String
594        }
595       
596/*=====
597
598// TODO: none of this is AMD friendly.   It's setting global variables in dojox,and not returning anything from the module.
599// Plus, the override of dojo/date/locale's format() and _getZone() below.   This needs to be refactored.
600
601dojox.date.timezone = function(){
602        // summary:
603        //              mix-in to dojo.date to provide timezones based on
604        //              the Olson timezone data
605        // description:
606        //              mix-in to dojo.date to provide timezones based on
607        //              the Olson timezone data.
608        //              If you pass "timezone" as a parameter to your format options,
609        //              then you get the date formatted (and offset) for that timezone
610
611//TODOC
612};
613
614dojox.date.timezone.getTzInfo = function(dt, tz){
615        // summary:
616        //              Returns the timezone information for the given date and
617        //              timezone string
618        // dt: Date
619        //              The Date - a "proxyDate"
620        // tz: String
621        //              String representation of the timezone you want to get info
622        //              for date
623};
624
625dojox.date.timezone.loadZoneData = function(data){
626        // summary:
627        //              Loads the given data object into the zone database
628        // data: Object
629        //              The data to load - contains "zones" and "rules" parameters
630};
631
632dojox.date.timezone.getAllZones = function(){
633        // summary:
634        //              Returns an array of zones that have been loaded
635};
636=====*/
637        dojo.setObject("dojox.date.timezone", {
638                getTzInfo: function(/* Date */ dt, /* String */ tz){
639                        // Lazy-load any zones not yet loaded
640                        if(loadingScheme == "lazyLoad"){
641                                // Get the correct region for the zone
642                                var zoneFile = getRegionForTimezone(tz);
643                                if(!zoneFile){
644                                        throw new Error("Not a valid timezone ID.");
645                                }else{
646                                        if(!_loadedZones[zoneFile]){
647                                                // Get the file and parse it -- use synchronous XHR
648                                                loadZoneFile(zoneFile);
649                                        }
650                                }
651                        }
652                        var zoneInfo = getZoneInfo(dt, tz);
653                        var off = zoneInfo.zone[0];
654                        // See if the offset needs adjustment
655                        var rule = getRule(dt, zoneInfo);
656                        if(rule){
657                                off += rule[6];
658                        }else{
659                                if(_rules[zoneInfo.zone[1]] && zoneInfo.idx > 0){
660                                        off += getOffsetInMins(_zones[tz][zoneInfo.idx - 1][1]);
661                                }else{
662                                        off += getOffsetInMins(zoneInfo.zone[1]);
663                                }
664                        }
665
666                        var abbr = getAbbreviation(tz, zoneInfo, rule);
667                        return { tzOffset: off, tzAbbr: abbr }; // Object
668                },
669                loadZoneData: function(data){
670                        loadZoneData(data);
671                },
672                getAllZones: function(){
673                        var arr = [];
674                        for(var z in _zones){ arr.push(z); }
675                        arr.sort();
676                        return arr; // String[]
677                }
678        });
679       
680        // Now - initialize the stuff that we should have pre-loaded
681        if(typeof defaultZoneFile == "string" && defaultZoneFile){
682                defaultZoneFile = [defaultZoneFile];
683        }
684        if(dojo.isArray(defaultZoneFile)){
685                dojo.forEach(defaultZoneFile, loadZoneFile);
686        }
687       
688        // And enhance the default formatting functions
689        // If you pass "timezone" as a parameter to your format options,
690        // then you get the date formatted (and offset) for that timezone
691        var oLocaleFmt = _ddl.format,
692                oGetZone = _ddl._getZone;
693        _ddl.format = function(dateObject, options){
694                options = options||{};
695                if(options.timezone && !options._tzInfo){
696                        // Store it in our options so we can use it later
697                        options._tzInfo = dojox.date.timezone.getTzInfo(dateObject, options.timezone);
698                }
699                if(options._tzInfo){
700                        // Roll our date to display the correct time according to the
701                        // desired offset
702                        var offset = dateObject.getTimezoneOffset() - options._tzInfo.tzOffset;
703                        dateObject = new Date(dateObject.getTime() + (offset * 60 * 1000));
704                }
705                return oLocaleFmt.call(this, dateObject, options);
706        };
707        _ddl._getZone = function(dateObject, getName, options){
708                if(options._tzInfo){
709                        return getName ? options._tzInfo.tzAbbr : options._tzInfo.tzOffset;
710                }
711                return oGetZone.call(this, dateObject, getName, options);
712        };
713
714        /*=====
715        // Hide these enhancements from the doc parser because they obscure the original definition of _getZone() and
716        // format.   TODO: change above overrides to around() advice so that original definitions aren't changed.
717         _ddl.format = oLocaleFmt;
718         _ddl._getZone = oGetZone;
719        =====*/
720});
Note: See TracBrowser for help on using the repository browser.