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