summaryrefslogtreecommitdiff
path: root/js/dojo/dojox/date/timezone.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/dojo/dojox/date/timezone.js')
-rw-r--r--js/dojo/dojox/date/timezone.js720
1 files changed, 720 insertions, 0 deletions
diff --git a/js/dojo/dojox/date/timezone.js b/js/dojo/dojox/date/timezone.js
new file mode 100644
index 0000000..cfbd113
--- /dev/null
+++ b/js/dojo/dojox/date/timezone.js
@@ -0,0 +1,720 @@
+//>>built
+/******************************************************************************
+ * Dojo port of fleegix date plugin from
+ *
+ * http://js.fleegix.org/plugins/date/date
+ *
+ * contributed to Dojo under CLA, with thanks to Matthew Eernisse (mde@fleegix.org)
+ * and Open Source Applications Foundation
+ *
+ * Credits: Ideas included from incomplete JS implementation of Olson
+ * parser, "XMLDate" by Philippe Goetz (philippe.goetz@wanadoo.fr)
+ *****************************************************************************/
+
+define("dojox/date/timezone", ["dojo", "dojo/date", "dojo/date/locale", "dojo/_base/array", "dojo/_base/xhr"],
+ function(dojo, _dd, _ddl){
+
+ dojo.experimental("dojox.date.timezone");
+ dojo.getObject("date.timezone", true, dojox);
+
+ var cfg = dojo.config;
+ var _zoneFiles = [ "africa", "antarctica", "asia", "australasia", "backward",
+ "etcetera", "europe", "northamerica", "pacificnew",
+ "southamerica" ];
+
+ // Our mins an maxes for years that we care about
+ var _minYear = 1835,
+ _maxYear = 2038;
+
+ var _loadedZones = {},
+ _zones = {},
+ _loadedRanges = {},
+ _rules = {};
+
+ // timezoneFileBasePath: String
+ // A different location to pull zone files from
+ var timezoneFileBasePath = cfg.timezoneFileBasePath ||
+ dojo.moduleUrl("dojox.date", "zoneinfo");
+
+ // loadingScheme: String
+ // One of "preloadAll", "lazyLoad" (Defaults "lazyLoad")
+ var loadingScheme = cfg.timezoneLoadingScheme || "preloadAll";
+
+ // defaultZoneFile: String or String[]
+ // The default file (or files) to load on startup - other files will
+ // be lazily-loaded on-demand
+ var defaultZoneFile = cfg.defaultZoneFile ||
+ ((loadingScheme == "preloadAll") ? _zoneFiles : "northamerica");
+
+ // Set our olson-zoneinfo content handler
+ dojo._contentHandlers["olson-zoneinfo"] = function(xhr){
+ var str = dojo._contentHandlers["text"](xhr),
+ s = "",
+ lines = str.split("\n"),
+ arr = [],
+ chunk = "",
+ zone = null,
+ rule = null,
+ ret = {zones: {}, rules: {}};
+
+ for(var i = 0; i < lines.length; i++){
+ var l = lines[i];
+ if(l.match(/^\s/)){
+ l = "Zone " + zone + l;
+ }
+ l = l.split("#")[0];
+ if(l.length > 3){
+ arr = l.split(/\s+/);
+ chunk = arr.shift();
+ switch(chunk){
+ case 'Zone':
+ zone = arr.shift();
+ if(arr[0]){
+ // Handle extra commas in the middle of a zone
+ if(!ret.zones[zone]){ ret.zones[zone] = []; }
+ ret.zones[zone].push(arr);
+ }
+ break;
+ case 'Rule':
+ rule = arr.shift();
+ if(!ret.rules[rule]){ ret.rules[rule] = []; }
+ ret.rules[rule].push(arr);
+ break;
+ case 'Link':
+ // No zones for these should already exist
+ if(ret.zones[arr[1]]){
+ throw new Error('Error with Link ' + arr[1]);
+ }
+ // Create the link
+ ret.zones[arr[1]] = arr[0];
+ break;
+ case 'Leap':
+ break;
+ default:
+ // Fail silently
+ break;
+ }
+ }
+ }
+ return ret; // Object
+ };
+
+ function loadZoneData(/* Object */ data){
+ // summary:
+ // Loads the given data object into the zone database
+ //
+ // data: Object
+ // The data to load - contains "zones" and "rules" parameters
+ data = data || {};
+ _zones = dojo.mixin(_zones, data.zones||{});
+ _rules = dojo.mixin(_rules, data.rules||{});
+ }
+
+ function loadZoneFile(/* String */ fileName){
+ // summary:
+ // Loads the given URL of the Olson zone information into the
+ // zone database
+ //
+ // fileName: String
+ // The zoneinfo file name to load
+
+ // TODO: Maybe behave similar to requireLocalization - rather than
+ // Using dojo.xhrGet?
+ _loadedZones[fileName] = true;
+ dojo.xhrGet({
+ url: timezoneFileBasePath + "/" + fileName,
+ sync: true, // Needs to be synchronous so we can return values
+ handleAs: "olson-zoneinfo",
+ load: loadZoneData,
+ error: function(e){
+ console.error("Error loading zone file:", e);
+ throw e;
+ }
+ });
+ }
+
+ var monthMap = { 'jan': 0, 'feb': 1, 'mar': 2, 'apr': 3,'may': 4, 'jun': 5,
+ 'jul': 6, 'aug': 7, 'sep': 8, 'oct': 9, 'nov': 10, 'dec': 11 },
+ dayMap = {'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4,
+ 'fri': 5, 'sat': 6 },
+ regionMap = {'EST': "northamerica", 'MST': "northamerica",
+ 'HST': "northamerica", 'EST5EDT': "northamerica",
+ 'CST6CDT': "northamerica", 'MST7MDT': "northamerica",
+ 'PST8PDT': "northamerica", 'America': "northamerica",
+ 'Pacific': "australasia", 'Atlantic': "europe",
+ 'Africa': "africa", 'Indian': "africa",
+ 'Antarctica': "antarctica", 'Asia': "asia",
+ 'Australia': "australasia", 'Europe': "europe",
+ 'WET': "europe", 'CET': "europe", 'MET': "europe",
+ 'EET': "europe"},
+ regionExceptions = {'Pacific/Honolulu':"northamerica",
+ 'Atlantic/Bermuda':"northamerica",
+ 'Atlantic/Cape_Verde':"africa",
+ 'Atlantic/St_Helena':"africa",
+ 'Indian/Kerguelen':"antarctica",
+ 'Indian/Chagos':"asia",
+ 'Indian/Maldives':"asia",
+ 'Indian/Christmas':"australasia",
+ 'Indian/Cocos':"australasia",
+ 'America/Danmarkshavn':"europe",
+ 'America/Scoresbysund':"europe",
+ 'America/Godthab':"europe",
+ 'America/Thule':"europe",
+ 'Asia/Yekaterinburg':"europe",
+ 'Asia/Omsk':"europe",
+ 'Asia/Novosibirsk':"europe",
+ 'Asia/Krasnoyarsk':"europe",
+ 'Asia/Irkutsk':"europe",
+ 'Asia/Yakutsk':"europe",
+ 'Asia/Vladivostok':"europe",
+ 'Asia/Sakhalin':"europe",
+ 'Asia/Magadan':"europe",
+ 'Asia/Kamchatka':"europe",
+ 'Asia/Anadyr':"europe",
+ 'Africa/Ceuta':"europe",
+ 'America/Argentina/Buenos_Aires':"southamerica",
+ 'America/Argentina/Cordoba':"southamerica",
+ 'America/Argentina/Tucuman':"southamerica",
+ 'America/Argentina/La_Rioja':"southamerica",
+ 'America/Argentina/San_Juan':"southamerica",
+ 'America/Argentina/Jujuy':"southamerica",
+ 'America/Argentina/Catamarca':"southamerica",
+ 'America/Argentina/Mendoza':"southamerica",
+ 'America/Argentina/Rio_Gallegos':"southamerica",
+ 'America/Argentina/Ushuaia':"southamerica",
+ 'America/Aruba':"southamerica",
+ 'America/La_Paz':"southamerica",
+ 'America/Noronha':"southamerica",
+ 'America/Belem':"southamerica",
+ 'America/Fortaleza':"southamerica",
+ 'America/Recife':"southamerica",
+ 'America/Araguaina':"southamerica",
+ 'America/Maceio':"southamerica",
+ 'America/Bahia':"southamerica",
+ 'America/Sao_Paulo':"southamerica",
+ 'America/Campo_Grande':"southamerica",
+ 'America/Cuiaba':"southamerica",
+ 'America/Porto_Velho':"southamerica",
+ 'America/Boa_Vista':"southamerica",
+ 'America/Manaus':"southamerica",
+ 'America/Eirunepe':"southamerica",
+ 'America/Rio_Branco':"southamerica",
+ 'America/Santiago':"southamerica",
+ 'Pacific/Easter':"southamerica",
+ 'America/Bogota':"southamerica",
+ 'America/Curacao':"southamerica",
+ 'America/Guayaquil':"southamerica",
+ 'Pacific/Galapagos':"southamerica",
+ 'Atlantic/Stanley':"southamerica",
+ 'America/Cayenne':"southamerica",
+ 'America/Guyana':"southamerica",
+ 'America/Asuncion':"southamerica",
+ 'America/Lima':"southamerica",
+ 'Atlantic/South_Georgia':"southamerica",
+ 'America/Paramaribo':"southamerica",
+ 'America/Port_of_Spain':"southamerica",
+ 'America/Montevideo':"southamerica",
+ 'America/Caracas':"southamerica"},
+ abbrExceptions = { 'US': "S", 'Chatham': "S", 'NZ': "S", 'NT_YK': "S",
+ 'Edm': "S", 'Salv': "S", 'Canada': "S", 'StJohns': "S",
+ 'TC': "S", 'Guat': "S", 'Mexico': "S", 'Haiti': "S",
+ 'Barb': "S", 'Belize': "S", 'CR': "S", 'Moncton': "S",
+ 'Swift': "S", 'Hond': "S", 'Thule': "S", 'NZAQ': "S",
+ 'Zion': "S", 'ROK': "S", 'PRC': "S", 'Taiwan': "S",
+ 'Ghana': "GMT", 'SL': "WAT", 'Chicago': "S",
+ 'Detroit': "S", 'Vanc': "S", 'Denver': "S",
+ 'Halifax': "S", 'Cuba': "S", 'Indianapolis': "S",
+ 'Starke': "S", 'Marengo': "S", 'Pike': "S",
+ 'Perry': "S", 'Vincennes': "S", 'Pulaski': "S",
+ 'Louisville': "S", 'CA': "S", 'Nic': "S",
+ 'Menominee': "S", 'Mont': "S", 'Bahamas': "S",
+ 'NYC': "S", 'Regina': "S", 'Resolute': "ES",
+ 'DR': "S", 'Toronto': "S", 'Winn': "S" };
+
+ function invalidTZError(t) {
+ throw new Error('Timezone "' + t +
+ '" is either incorrect, or not loaded in the timezone registry.');
+ }
+
+ function getRegionForTimezone(/* String */ tz) {
+ // summary:
+ // Returns the Olson region for the given timezone
+ var ret = regionExceptions[tz];
+ if(!ret){
+ var reg = tz.split('/')[0];
+ ret = regionMap[reg];
+ // If there's nothing listed in the main regions for
+ // this TZ, check the 'backward' links
+ if(!ret){
+ var link = _zones[tz];
+ if(typeof link == 'string'){
+ return getRegionForTimezone(link); // String
+ }else{
+ // Backward-compat file hasn't loaded yet, try looking in there
+ if (!_loadedZones.backward) {
+ // This is for obvious legacy zones (e.g., Iceland) that
+ // don't even have a prefix like "America/" that look like
+ // normal zones
+ loadZoneFile("backward");
+ return getRegionForTimezone(tz); // String
+ }else{
+ invalidTZError(tz);
+ }
+ }
+ }
+ }
+ return ret; // String
+ }
+
+ function parseTimeString(/* String */ str) {
+ // summary:
+ // Parses the given time string and returns it as an integer array
+ var pat = /(\d+)(?::0*(\d*))?(?::0*(\d*))?([su])?$/;
+ var hms = str.match(pat);
+ if(!hms){
+ return null;
+ }
+ hms[1] = parseInt(hms[1], 10);
+ hms[2] = hms[2] ? parseInt(hms[2], 10) : 0;
+ hms[3] = hms[3] ? parseInt(hms[3], 10) : 0;
+ return hms; // int[]
+ }
+
+ function getUTCStamp(/* int */ y, /* int */ m, /* int */ d, /* int */ h,
+ /* int */ mn, /* int */ s, /* int? */ off){
+ // summary:
+ // Returns the UTC timestamp, adjusted by the given (optional) offset
+ return Date.UTC(y, m, d, h, mn, s) + ((off||0) * 60 * 1000);
+ }
+
+ function getMonthNumber(/* String */ m){
+ // summary:
+ // Returns the javascript month number for the given string
+ return monthMap[m.substr(0, 3).toLowerCase()];
+ }
+
+ function getOffsetInMins(/* String */ str){
+ // summary:
+ // Returns the offset value represented by the string, in minutes
+ var off = parseTimeString(str);
+ if(off === null){ return 0; }
+ var adj = str.indexOf('-') === 0 ? -1 : 1;
+ off = adj * (((off[1] * 60 + off[2]) *60 + off[3]) * 1000);
+ return -off/60/1000;
+ }
+
+ function _getRuleStart(/* Rule */ rule, /* int */ year, /* int */ off){
+ // summary:
+ // Returns a date that the rule begins matching in the given year.
+ var month = getMonthNumber(rule[3]),
+ day = rule[4],
+ time = parseTimeString(rule[5]);
+ if(time[4] == "u"){
+ // We are UTC - so there is no offset to use
+ off = 0;
+ }
+
+ var d, dtDay, incr;
+ if(isNaN(day)){
+ if(day.substr(0, 4) == "last"){
+ // Last day of the month at the desired time of day
+ day = dayMap[day.substr(4,3).toLowerCase()];
+ d = new Date(getUTCStamp(year, month + 1, 1,
+ time[1] - 24, time[2], time[3],
+ off));
+ dtDay = _dd.add(d, "minute", -off).getUTCDay();
+ // Set it to the final day of the correct weekday that month
+ incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
+ if(incr !== 0){
+ d = _dd.add(d, "hour", incr * 24);
+ }
+ return d;
+ }else{
+ day = dayMap[day.substr(0, 3).toLowerCase()];
+ if(day != "undefined"){
+ if(rule[4].substr(3, 2) == '>='){
+ // The stated date of the month
+ d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10),
+ time[1], time[2], time[3], off));
+ dtDay = _dd.add(d, "minute", -off).getUTCDay();
+ // Set to the first correct weekday after the stated date
+ incr = (day < dtDay) ? (day - dtDay + 7) : (day - dtDay);
+ if(incr !== 0){
+ d = _dd.add(d, "hour", incr * 24);
+ }
+ return d;
+ }else if(day.substr(3, 2) == '<='){
+ // The stated date of the month
+ d = new Date(getUTCStamp(year, month, parseInt(rule[4].substr(5), 10),
+ time[1], time[2], time[3], off));
+ dtDay = _dd.add(d, "minute", -off).getUTCDay();
+ // Set to first correct weekday before the stated date
+ incr = (day > dtDay) ? (day - dtDay - 7) : (day - dtDay);
+ if(incr !== 0){
+ d = _dd.add(d, "hour", incr * 24);
+ }
+ return d;
+ }
+ }
+ }
+ }else{
+ // Numeric date
+ d = new Date(getUTCStamp(year, month, parseInt(day, 10),
+ time[1], time[2], time[3], off));
+ return d;
+ }
+ return null;
+ }
+
+ function _getRulesForYear(/* Zone */ zone, /* int */ year){
+ var rules = [];
+ dojo.forEach(_rules[zone[1]]||[], function(r){
+ // Clean up rules as needed
+ for(var i = 0; i < 2; i++){
+ switch(r[i]){
+ case "min":
+ r[i] = _minYear;
+ break;
+ case "max":
+ r[i] = _maxYear;
+ break;
+ case "only":
+ break;
+ default:
+ r[i] = parseInt(r[i], 10);
+ if(isNaN(r[i])){
+ throw new Error('Invalid year found on rule');
+ }
+ break;
+ }
+ }
+ if(typeof r[6] == "string"){
+ // Change our offset to be an integer
+ r[6] = getOffsetInMins(r[6]);
+ }
+
+ // Quick-filter to grab all rules that match my year
+ if((r[0] <= year && r[1] >= year) || // Matches my y
+ (r[0] == year && r[1] == "only")){ // Matches my only
+ rules.push({r: r, d: _getRuleStart(r, year, zone[0])});
+ }
+ });
+ return rules;
+ }
+
+
+ function _loadZoneRanges(/* String */ tz, /* Object[] */ zoneList) {
+ // summary:
+ // Loads the zone ranges for the given timezone
+
+ var zr = _loadedRanges[tz] = [];
+ for(var i = 0; i < zoneList.length; i++){
+ var z = zoneList[i];
+ var r = zr[i] = [];
+ var prevZone = null;
+ var prevRange = null;
+ var prevRules = [];
+
+ // Set up our zone offset to not be a string anymore
+ if(typeof z[0] == "string"){
+ z[0] = getOffsetInMins(z[0]);
+ }
+
+ if(i === 0){
+ // The beginning of zoneinfo time - let's not worry about
+ // to-the-hour accuracy before Jan 1, 1835
+ r[0] = Date.UTC(_minYear,0,1,0,0,0,0);
+ }else{
+ r[0] = zr[i - 1][1];
+ prevZone = zoneList[i - 1];
+ prevRange = zr[i - 1];
+ prevRules = prevRange[2];
+ }
+
+ // Load the rules that will be going in to our zone
+ var startYear = new Date(r[0]).getUTCFullYear();
+ var endYear = z[3] ? parseInt(z[3], 10) : _maxYear;
+ var rlz = [];
+ var j;
+ for(j = startYear; j <= endYear; j++){
+ rlz = rlz.concat(_getRulesForYear(z, j));
+ }
+ rlz.sort(function(a, b){
+ return _dd.compare(a.d, b.d);
+ });
+ var rl;
+ for(j = 0, rl; (rl = rlz[j]); j++){
+ var prevRule = j > 0 ? rlz[j - 1] : null;
+ if(rl.r[5].indexOf("u") < 0 && rl.r[5].indexOf("s") < 0){
+ if(j === 0 && i > 0){
+ if(prevRules.length){
+ // We have a previous rule - so use it
+ rl.d = _dd.add(rl.d, "minute", prevRules[prevRules.length - 1].r[6]);
+ }else if(_dd.compare(new Date(prevRange[1]), rl.d, "date") === 0){
+ // No previous rules - but our date is the same as the
+ // previous zone ended on - so use that.
+ rl.d = new Date(prevRange[1]);
+ }else{
+ rl.d = _dd.add(rl.d, "minute", getOffsetInMins(prevZone[1]));
+ }
+ }else if(j > 0){
+ rl.d = _dd.add(rl.d, "minute", prevRule.r[6]);
+ }
+ }
+ }
+ r[2] = rlz;
+
+ if(!z[3]){
+ // The end of zoneinfo time - we'll cross this bridge when we
+ // get close to Dec 31, 2038
+ r[1] = Date.UTC(_maxYear,11,31,23,59,59,999);
+ }else{
+ var year = parseInt(z[3], 10),
+ month = getMonthNumber(z[4]||"Jan"),
+ day = parseInt(z[5]||"1", 10),
+ time = parseTimeString(z[6]||"0");
+ var utcStmp = r[1] = getUTCStamp(year, month, day,
+ time[1], time[2], time[3],
+ ((time[4] == "u") ? 0 : z[0]));
+ if(isNaN(utcStmp)){
+ utcStmp = r[1] = _getRuleStart([0,0,0,z[4],z[5],z[6]||"0"],
+ year, ((time[4] == "u") ? 0 : z[0])).getTime();
+ }
+ var matches = dojo.filter(rlz, function(rl, idx){
+ var o = idx > 0 ? rlz[idx - 1].r[6] * 60 * 1000 : 0;
+ return (rl.d.getTime() < utcStmp + o);
+ });
+ if(time[4] != "u" && time[4] != "s"){
+ if(matches.length){
+ r[1] += matches[matches.length - 1].r[6] * 60 * 1000;
+ }else{
+ r[1] += getOffsetInMins(z[1]) * 60 * 1000;
+ }
+ }
+ }
+ }
+ }
+
+ function getZoneInfo(/* String */ dt, /* String */ tz) {
+ // summary:
+ // Returns the zone entry from the zoneinfo database for the given date
+ // and timezone
+ var t = tz;
+ var zoneList = _zones[t];
+
+ // Follow links to get to an actual zone
+ while(typeof zoneList == "string"){
+ t = zoneList;
+ zoneList = _zones[t];
+ }
+ if(!zoneList){
+ // Backward-compat file hasn't loaded yet, try looking in there
+ if(!_loadedZones.backward){
+ // This is for backward entries like "America/Fort_Wayne" that
+ // getRegionForTimezone *thinks* it has a region file and zone
+ // for (e.g., America => 'northamerica'), but in reality it's a
+ // legacy zone we need the backward file for
+ var parsed = loadZoneFile("backward", true);
+ return getZoneInfo(dt, tz); //Object
+ }
+ invalidTZError(t);
+ }
+
+ if(!_loadedRanges[tz]){
+ _loadZoneRanges(tz, zoneList);
+ }
+ var ranges = _loadedRanges[tz];
+ var tm = dt.getTime();
+ for(var i = 0, r; (r = ranges[i]); i++){
+ if(tm >= r[0] && tm < r[1]){
+ return {zone: zoneList[i], range: ranges[i], idx: i};
+ }
+ }
+ throw new Error('No Zone found for "' + tz + '" on ' + dt);
+ }
+
+ function getRule(/* Date */ dt, /* ZoneInfo */ zoneInfo) {
+ // summary:
+ // Returns the latest-matching rule entry from the zoneinfo
+ // database for the given date and zone
+
+ var lastMatch = -1;
+ var rules = zoneInfo.range[2]||[];
+ var tsp = dt.getTime();
+ var zr = zoneInfo.range;
+ for(var i = 0, r; (r = rules[i]); i++){
+ if(tsp >= r.d.getTime()){
+ lastMatch = i;
+ }
+ }
+ if(lastMatch >= 0){
+ return rules[lastMatch].r;
+ }
+ return null;
+ }
+
+ function getAbbreviation(/* String */ tz, /* Object */ zoneInfo, /* Object */ rule) {
+ // summary:
+ // Returns the abbreviation for the given zone and rule
+ var res;
+ var zone = zoneInfo.zone;
+ var base = zone[2];
+ if(base.indexOf('%s') > -1){
+ var repl;
+ if(rule){
+ repl = rule[7];
+ if(repl == "-"){ repl = ""; }
+ }else if(zone[1] in abbrExceptions){
+ repl = abbrExceptions[zone[1]];
+ }else{
+ if(zoneInfo.idx > 0){
+ // Check if our previous zone's base is the same as our
+ // current in "S" (standard) mode. If so, then use "S"
+ // for our replacement
+ var pz = _zones[tz][zoneInfo.idx - 1];
+ var pb = pz[2];
+ if(pb.indexOf('%s') < 0){
+ if(base.replace('%s', "S") == pb){
+ repl = "S";
+ }else{
+ repl = "";
+ }
+ }else{
+ repl = "";
+ }
+ }else{
+ repl = "";
+ }
+ }
+ res = base.replace('%s', repl);
+ }else if(base.indexOf("/") > -1){
+ var bs = base.split("/");
+ if(rule){
+ res = bs[rule[6] === 0 ? 0 : 1];
+ }else{
+ res = bs[0];
+ }
+ }else{
+ res = base;
+ }
+ return res; // String
+ }
+
+/*=====
+dojox.date.timezone = function(){
+ // summary:
+ // mix-in to dojo.date to provide timezones based on
+ // the Olson timezone data
+ //
+ // description:
+ // mix-in to dojo.date to provide timezones based on
+ // the Olson timezone data.
+ // If you pass "timezone" as a parameter to your format options,
+ // then you get the date formatted (and offset) for that timezone
+
+//TODOC
+};
+
+dojox.date.timezone.getTzInfo = function(dt, tz){
+ // summary:
+ // Returns the timezone information for the given date and
+ // timezone string
+ //
+ // dt: Date
+ // The Date - a "proxyDate"
+ //
+ // tz: String
+ // String representation of the timezone you want to get info
+ // for date
+};
+
+dojox.date.timezone.loadZoneData = function(data){
+ // summary:
+ // Loads the given data object into the zone database
+ //
+ // data: Object
+ // The data to load - contains "zones" and "rules" parameters
+};
+
+dojox.date.timezone.getAllZones = function(){
+ // summary:
+ // Returns an array of zones that have been loaded
+};
+=====*/
+ dojo.setObject("dojox.date.timezone", {
+ getTzInfo: function(/* Date */ dt, /* String */ tz){
+ // Lazy-load any zones not yet loaded
+ if(loadingScheme == "lazyLoad"){
+ // Get the correct region for the zone
+ var zoneFile = getRegionForTimezone(tz);
+ if(!zoneFile){
+ throw new Error("Not a valid timezone ID.");
+ }else{
+ if(!_loadedZones[zoneFile]){
+ // Get the file and parse it -- use synchronous XHR
+ loadZoneFile(zoneFile);
+ }
+ }
+ }
+ var zoneInfo = getZoneInfo(dt, tz);
+ var off = zoneInfo.zone[0];
+ // See if the offset needs adjustment
+ var rule = getRule(dt, zoneInfo);
+ if(rule){
+ off += rule[6];
+ }else{
+ if(_rules[zoneInfo.zone[1]] && zoneInfo.idx > 0){
+ off += getOffsetInMins(_zones[tz][zoneInfo.idx - 1][1]);
+ }else{
+ off += getOffsetInMins(zoneInfo.zone[1]);
+ }
+ }
+
+ var abbr = getAbbreviation(tz, zoneInfo, rule);
+ return { tzOffset: off, tzAbbr: abbr }; // Object
+ },
+ loadZoneData: function(data){
+ loadZoneData(data);
+ },
+ getAllZones: function(){
+ var arr = [];
+ for(var z in _zones){ arr.push(z); }
+ arr.sort();
+ return arr; // String[]
+ }
+ });
+
+ // Now - initialize the stuff that we should have pre-loaded
+ if(typeof defaultZoneFile == "string" && defaultZoneFile){
+ defaultZoneFile = [defaultZoneFile];
+ }
+ if(dojo.isArray(defaultZoneFile)){
+ dojo.forEach(defaultZoneFile, loadZoneFile);
+ }
+
+ // And enhance the default formatting functions
+ // If you pass "timezone" as a parameter to your format options,
+ // then you get the date formatted (and offset) for that timezone
+ var oLocaleFmt = _ddl.format,
+ oGetZone = _ddl._getZone;
+ _ddl.format = function(dateObject, options){
+ options = options||{};
+ if(options.timezone && !options._tzInfo){
+ // Store it in our options so we can use it later
+ options._tzInfo = dojox.date.timezone.getTzInfo(dateObject, options.timezone);
+ }
+ if(options._tzInfo){
+ // Roll our date to display the correct time according to the
+ // desired offset
+ var offset = dateObject.getTimezoneOffset() - options._tzInfo.tzOffset;
+ dateObject = new Date(dateObject.getTime() + (offset * 60 * 1000));
+ }
+ return oLocaleFmt.call(this, dateObject, options);
+ };
+ _ddl._getZone = function(dateObject, getName, options){
+ if(options._tzInfo){
+ return getName ? options._tzInfo.tzAbbr : options._tzInfo.tzOffset;
+ }
+ return oGetZone.call(this, dateObject, getName, options);
+ };
+});