You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
711 lines
22 KiB
711 lines
22 KiB
/****************************************************************************** |
|
* 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([ |
|
"dojo/_base/array", |
|
"dojo/_base/config", |
|
"dojo/_base/declare", |
|
"dojo/_base/kernel", |
|
"dojo/_base/lang", |
|
"dojo/date", |
|
"dojo/date/locale", |
|
"dojo/request", |
|
"dojo/request/handlers" |
|
], |
|
function(arrayUtil, config, declare, kernel, lang, dateUtil, localeUtil, request, handlers){ |
|
kernel.experimental("dojox.date.timezone"); |
|
|
|
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 = {}; |
|
|
|
// loadingScheme: String |
|
// One of "preloadAll", "lazyLoad" (Defaults "preloadAll") |
|
var loadingScheme = config.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 = config.defaultZoneFile || |
|
((loadingScheme == "preloadAll") ? _zoneFiles : "northamerica"); |
|
|
|
// Set our olson_zoneinfo content handler |
|
handlers.register("olson_zoneinfo", function(response) { |
|
var text = response.text, |
|
s = "", |
|
lines = text.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 = lang.mixin(_zones, data.zones||{}); |
|
_rules = lang.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 request.get? |
|
_loadedZones[fileName] = true; |
|
request.get(require.toUrl((config.timezoneFileBasePath || "dojox/date/zoneinfo") + "/" + fileName), { |
|
handleAs: "olson_zoneinfo", |
|
sync: true |
|
}).then(loadZoneData, 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 = dateUtil.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 = dateUtil.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 = dateUtil.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 = dateUtil.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 = dateUtil.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 = dateUtil.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 = []; |
|
arrayUtil.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 dateUtil.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 = dateUtil.add(rl.d, "minute", prevRules[prevRules.length - 1].r[6]); |
|
}else if(dateUtil.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 = dateUtil.add(rl.d, "minute", getOffsetInMins(prevZone[1])); |
|
} |
|
}else if(j > 0){ |
|
rl.d = dateUtil.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 = arrayUtil.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 |
|
} |
|
|
|
lang.setObject("dojox.date.timezone", { |
|
// 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 |
|
|
|
getTzInfo: function(/* Date */ dt, /* String */ 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 |
|
|
|
// 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){ |
|
// summary: |
|
// Loads the given data object into the zone database |
|
// data: Object |
|
// The data to load - contains "zones" and "rules" parameters |
|
loadZoneData(data); |
|
}, |
|
|
|
getAllZones: function(){ |
|
// summary: |
|
// Returns an array of zones that have been loaded |
|
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(defaultZoneFile instanceof Array){ |
|
arrayUtil.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 = localeUtil.format, |
|
oGetZone = localeUtil._getZone; |
|
localeUtil.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); |
|
}; |
|
localeUtil._getZone = function(dateObject, getName, options){ |
|
if(options._tzInfo){ |
|
return getName ? options._tzInfo.tzAbbr : options._tzInfo.tzOffset; |
|
} |
|
return oGetZone.call(this, dateObject, getName, options); |
|
}; |
|
|
|
/*===== |
|
// Hide these enhancements from the doc parser because they obscure the original definition of _getZone() and |
|
// format. TODO: change above overrides to around() advice so that original definitions aren't changed. |
|
localeUtil.format = oLocaleFmt; |
|
localeUtil._getZone = oGetZone; |
|
=====*/ |
|
|
|
return dojox.date.timezone; |
|
});
|
|
|