Changeset 5777 for branches/i18ndate
- Timestamp:
- 09/23/06 13:05:25 (2 years ago)
- Location:
- branches/i18ndate
- Files:
-
- 5 modified
-
src/date/format.js (modified) (7 diffs)
-
src/loader.js (modified) (1 diff)
-
src/uri/Uri.js (modified) (2 diffs)
-
tests/date/test_format.js (modified) (2 diffs)
-
tests/widget/test_ComboBox.html (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
branches/i18ndate/src/date/format.js
r5753 r5777 176 176 s = Math.round(dateObject.getMilliseconds() * Math.pow(10, l-3)); 177 177 break; 178 case 'v': // FIXME: don't know what this is. seems to be same as z?179 case 'z':180 // We only have one timezone to offer; the one from the browser181 s = dojo.date.getTimezoneName(dateObject);182 if(s){break;}183 l=4;184 // fallthrough... use GMT if tz not available185 178 case 'Z': 186 179 var offset = dateObject.getTimezoneOffset(); … … 202 195 case 'g': 203 196 case 'A': 197 case 'v': 198 case 'z': 204 199 dojo.debug(match+" modifier not yet implemented"); 205 200 s = "?"; … … 258 253 // strict- strict parsing, off by default 259 254 // 260 261 //TODO: this is still quite rough - it only implements a small portion of the parsing algorithm needed, 262 // and doesn't provide much flexibility in matching. 255 263 256 var locale = dojo.hostenv.normalizeLocale(options.locale); 264 257 var info = dojo.date._getGregorianBundle(locale); 265 258 var formatLength = options.formatLength || 'full'; 266 if (options.selector != 'dateOnly'){ dojo.unimplemented("can only parse dates at this time"); } 267 var pattern = options.datePattern || info["dateFormat-"+formatLength]; 259 if (!options.selector) options.selector = 'dateOnly'; 260 var datePattern = options.datePattern || info["dateFormat-" + formatLength]; 261 var timePattern = options.timePattern || info["timeFormat-" + formatLength]; 262 263 var pattern; 264 options.selector = options.selector.toLowerCase(); 265 if (options.selector == 'dateonly') { 266 pattern = datePattern; 267 } 268 else if (options.selector == 'timeonly') { 269 pattern = timePattern; 270 } else if (options.selector == 'datetime') { 271 pattern = datePattern + ' ' + timePattern; //TODO: use locale-specific pattern to assemble date + time 272 } else { 273 var msg = "dojo.date.parse: Unknown selector param passed: '" + options.selector + "'."; 274 msg += " Defaulting to date pattern."; 275 dojo.debug(msg); 276 pattern = datePattern; 277 } 278 279 dojo.debug("Locale: " + locale + ", parsing value '" + value + "' against pattern: " + pattern); 280 281 //DEBUG 282 //for (p in info) 283 // dojo.debug(p + ': ' + info[p]); 284 268 285 var groups = []; 269 270 var dateREString = _processPattern(pattern, dojo.lang.curry(this, _buildDateTimeRE, groups)); 271 //TODO: escape special regexp chars 272 //TODO: make whitespace flexible? 286 var dateREString = _processPattern(pattern, dojo.lang.curry(this, _buildDateTimeRE, groups, info, options)); 273 287 var dateRE = new RegExp("^" + dateREString + "$"); 274 288 289 //DEBUG 290 //if (typeof window != 'undefined') window.re = dateRE; 291 275 292 var match = dateRE.exec(value); 276 if(!match){return null;} // null 277 278 var result = new Date(2004,0); 293 if(!match){ 294 return null; 295 } 296 297 var widthList = ['abbr', 'wide', 'narrow']; 298 var result = new Date(1970, 0); 299 var expected = {}; 279 300 for(var i=1; i<match.length; i++){ 280 301 var grp=groups[i-1]; … … 282 303 var v=match[i]; 283 304 switch(grp.charAt(0)){ 305 case 'y': 306 if(l != 2){ 307 //interpret year literally, so '5' would be 5 A.D. 308 result.setFullYear(v); 309 expected.year = v; 310 } else { 311 if(v<100){ 312 v = Number(v); 313 //choose century to apply, according to a sliding window 314 //of 80 years before and 20 years after present year 315 var year = '' + new Date().getFullYear(); 316 var century = year.substring(0, 2) * 100; 317 var yearPart = new Number(year.substring(2, 4)); 318 var cutoff = Math.min(yearPart + 20, 99); 319 var num = (v < cutoff) ? century + v : century - 100 + v; 320 result.setFullYear(num); 321 expected.year = num; 322 } else { 323 //we expected 2 digits and got more... 324 if(options.strict){ 325 return null; 326 } 327 //interpret literally, so '150' would be 150 A.D. 328 //also tolerate '1950', if 'yyyy' input passed to 'yy' format 329 result.setFullYear(v); 330 expected.year = v; 331 } 332 } 333 break; 334 case 'M': 335 if (l>2) { 336 if(!options.strict){ 337 //Tolerate abbreviating period in month part 338 v = v.replace(/\./g,''); 339 //Case-insensitive 340 v = v.toLowerCase(); 341 } 342 var strs = info['months-format-' + widthList[l-3]]; 343 for (var j=0; j<strs.length; j++) { 344 if (!options.strict) { 345 //Case-insensitive 346 strs[j] = strs[j].toLowerCase(); 347 } 348 if (v == strs[j]) { 349 result.setMonth(j); 350 expected.month = j; 351 break; 352 } 353 } 354 if (j==strs.length) { 355 dojo.debug("dojo.date.parse: Could not parse month name: '" + v + "'."); 356 return null; 357 } 358 } else { 359 result.setMonth(v-1); 360 expected.month = v-1; 361 } 362 break; 363 case 'E': 364 case 'e': 365 if(!options.strict){ 366 //Case-insensitive 367 v = v.toLowerCase(); 368 } 369 var strs = info['days-format-' + widthList[l-3]]; 370 for (var j=0; j<strs.length; j++) { 371 if (!options.strict) { 372 //Case-insensitive 373 strs[j] = strs[j].toLowerCase(); 374 } 375 if (v == strs[j]) { 376 //TODO: not sure what to actually do with this input, 377 //in terms of setting something on the Date obj...? 378 //without more context, can't affect the actual date 379 break; 380 } 381 } 382 if (j==strs.length) { 383 dojo.debug("dojo.date.parse: Could not parse weekday name: '" + v + "'."); 384 return null; 385 } 386 break; 284 387 case 'd': 285 388 result.setDate(v); 286 break; 287 case 'M': 288 result.setMonth(v-1); 289 break; 290 case 'y': 291 var century = 0; 292 if(l == 2){ 293 if(v<100){ 294 century = Math.floor(result.getFullYear()/100)*100; 295 } else if(options.strict){ 296 return null; // null 297 } 389 expected.date = v; 390 break; 391 case 'a': //am/pm 392 var am = info['am']; 393 var pm = info['pm']; 394 if (!options.strict) { 395 v = v.replace(/\./g,'').toLowerCase(); 396 am = am.replace(/\./g,'').toLowerCase(); 397 pm = pm.replace(/\./g,'').toLowerCase(); 298 398 } 299 result.setFullYear(century+Number(v)); 399 if (options.strict && v != am && v != pm) { 400 dojo.debug("dojo.date.parse: Could not parse am/pm part."); 401 return null; 402 } 403 var hours = result.getHours(); 404 if (v == pm && hours < 12) { 405 result.setHours(hours + 12); //e.g., 3pm -> 15 406 } else if (v == am && hours == 12) { 407 result.setHours(0); //12am -> 0 408 } 409 break; 410 case 'h': //hour (1-12) 411 //in the 12-hour case, adjusting for am/pm requires the 'a' part 412 //which for now we will assume always comes after the 'h' part 413 result.setHours(v); 414 break; 415 case 'H': //hour (0-23) 416 result.setHours(v); 417 break; 418 case 'k': //hour (0-11) 419 ++v; //adjust to the 1-12 input that js setHours() expects 420 //also see 12-hour case comment in the 'h' case above 421 result.setHours(v); 422 break; 423 case 'K': //hour (1-24) 424 --v; // js setHours() range is 0 to 23 425 result.setHours(v); 426 break; 427 case 'm': //minutes 428 result.setMinutes(v); 429 break; 430 case 's': //seconds 431 result.setSeconds(s); 300 432 break; 301 433 default: 302 dojo.unimplemented("incomplete parse algorithm ");434 dojo.unimplemented("incomplete parse algorithm: " + grp.charAt(0)); 303 435 } 304 436 } 305 return result; // Date 437 438 //validate parse date fields versus input date fields 439 if (expected.year && result.getFullYear() != expected.year) { 440 dojo.debug("Parsed year: '" + result.getFullYear() + "' did not match input year: '" + expected.year + "'."); 441 return null; 442 } 443 if (expected.month && result.getMonth() != expected.month) { 444 dojo.debug("Parsed month: '" + result.getMonth() + "' did not match input month: '" + expected.month + "'."); 445 return null; 446 } 447 if (expected.date && result.getDate() != expected.date) { 448 dojo.debug("Parsed day of month: '" + result.getDate() + "' did not match input day of month: '" + expected.date + "'."); 449 return null; 450 } 451 452 //TODO: need to implement a getWeekday() method in order to test 453 //validity of input strings containing 'EEE' or 'EEEE'.... 454 455 return result; 306 456 }; 307 457 … … 316 466 var chunks = pattern.split('\''); 317 467 var literal = false; 468 //DEBUG 469 //for(var i=0; i<chunks.length; i++) { dojo.debug("Chunk #" + i + ": " + chunks[i]); } 470 318 471 for(var i=0; i<chunks.length; i++){ 319 if(!chunks[i]){chunks[i]='\'';} //FIXME 320 else{ 472 if(!chunks[i]){ 473 chunks[i]=''; //FIXME - was chunks[i]='\'' 474 } else{ 321 475 chunks[i]=(literal ? applyLiteral : applyPattern)(chunks[i]); 322 476 literal = !literal; 323 477 } 324 } 325 326 return applyAll(chunks.join("")); 478 479 //DEBUG 480 //dojo.debug("Chunk #" + i + ": " + chunks[i]); 481 482 } 483 //DEBUG 484 //dojo.debug("Chunks: " + chunks.join('')); 485 486 return applyAll(chunks.join('')); 327 487 } 328 488 329 function _buildDateTimeRE(groups, pattern) {489 function _buildDateTimeRE(groups, info, options, pattern) { 330 490 return pattern.replace(/[a-zA-Z]+/g, function(match){ 331 491 var s; … … 334 494 switch(c){ 335 495 case 'y': 336 s = "\\d" + ((l==2)?"{2,4}":"+");496 s = '\\d' + ((l==2) ? '{2,4}' : '+'); 337 497 break; 338 498 case 'M': 339 s = "\\d{1,2}"; //TODO make sure it conforms to month range...499 s = (l>2) ? '\\S+' : '\\d{1,2}'; 340 500 break; 341 501 case 'd': 342 s = "\\d{1,2}"; //TODO 343 break; 344 case 'h': case 'H': case 'K': case 'k': 345 s = "\\d{2}"; //TODO 502 s = '\\d{1,2}'; 503 break; 504 case 'E': 505 s = '\\S+'; 506 break; 507 case 'h': 508 case 'H': 509 case 'K': 510 case 'k': 511 s = '\\d{2}'; 346 512 break; 347 513 case 'm': 348 514 case 's': 349 s = "\\d{2}"; //TODO515 s = '\\d{2}'; 350 516 break; 351 517 case 'S': 352 s = "\\d+"; //TODO518 s = '\\d+'; 353 519 break; 354 520 case 'a': 355 s = info.am + "|" + info.pm; 521 var am = info.am || 'AM'; 522 var pm = info.pm || 'PM'; 523 if (options.strict) { 524 s = am + '|' + pm; 525 } else { 526 s = am; 527 s += (am != am.toLowerCase()) ? '|' + am.toLowerCase() : ''; 528 s += '|'; 529 s += (pm != pm.toLowerCase()) ? pm + '|' + pm.toLowerCase() : pm; 530 } 356 531 break; 357 532 default: 358 dojo.unimplemented("parse of date format, pattern=" +pattern);533 dojo.unimplemented("parse of date format, pattern=" + pattern); 359 534 } 360 535 if(groups){ groups.push(match); } 361 return "("+s+")"; 536 return '\\s*(' + s + ')\\s*'; 537 //DEBUG 538 //return '(' + s + ')'; 362 539 }); 363 540 }; … … 529 706 530 707 case "Z": // time zone or name or abbreviation 531 return dojo.date.getTimezoneName(dateObject); 708 return dojo.date.getTimezoneName(dateObject); //TODO 532 709 533 710 case "%": -
branches/i18ndate/src/loader.js
r5753 r5777 593 593 if(bundle){ 594 594 if(djConfig.localizationComplete && bundle._built){return;} 595 var jsLoc = dojo.hostenv.normalizeLocale(locale).replace(' -','_');595 var jsLoc = dojo.hostenv.normalizeLocale(locale).replace('_', '-'); 596 596 var translationPackage = bundlePackage+"."+jsLoc; 597 597 if(dojo.hostenv.findModule(translationPackage)){return;} -
branches/i18ndate/src/uri/Uri.js
r5760 r5777 33 33 var relobj = new dojo.uri.Uri(arguments[i].toString()); 34 34 var uriobj = new dojo.uri.Uri(uri.toString()); 35 35 36 36 if (relobj.path == "" && relobj.scheme == null && 37 37 relobj.authority == null && relobj.query == null) { 38 38 if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; } 39 39 relobj = uriobj; 40 } else if (relobj.scheme == null) { 41 relobj.scheme = uriobj.scheme; 40 } 42 41 43 if (relobj.authority == null) { 44 relobj.authority = uriobj.authority; 45 46 if (relobj.path.charAt(0) != "/") { 47 var path = uriobj.path.substring(0, 48 uriobj.path.lastIndexOf("/") + 1) + relobj.path; 49 50 var segs = path.split("/"); 51 for (var j = 0; j < segs.length; j++) { 52 if (segs[j] == ".") { 53 if (j == segs.length - 1) { segs[j] = ""; } 54 else { segs.splice(j, 1); j--; } 55 } else if (j > 0 && !(j == 1 && segs[0] == "") && 56 segs[j] == ".." && segs[j-1] != "..") { 57 58 if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; } 59 else { segs.splice(j - 1, 2); j -= 2; } 60 } 61 } 62 relobj.path = segs.join("/"); 63 } 64 } 65 } 66 67 uri = ""; 42 if (relobj.scheme != null && relobj.authority != null) 43 uri = ""; 68 44 if (relobj.scheme != null) { uri += relobj.scheme + ":"; } 69 45 if (relobj.authority != null) { uri += "//" + relobj.authority; } … … 72 48 if (relobj.fragment != null) { uri += "#" + relobj.fragment; } 73 49 } 74 50 75 51 this.uri = uri.toString(); 76 52 77 53 // break the uri into its main components 78 54 var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"; 79 var r = this.uri.match(new RegExp(regexp));55 var r = this.uri.match(new RegExp(regexp)); 80 56 81 57 this.scheme = r[2] || (r[1] ? "" : null); -
branches/i18ndate/tests/date/test_format.js
r5701 r5777 1 1 // can't set djConfig.extraLocale before bootstrapping unit tests, so manually load resources here for specific locales: 2 /** 2 3 dojo.requireLocalization("dojo.i18n.calendar","gregorian","en-us"); 3 4 dojo.requireLocalization("dojo.i18n.calendar","gregorian","fr-fr"); 4 5 dojo.requireLocalization("dojo.i18n.calendar","gregorian","de-at"); 5 6 dojo.requireLocalization("dojo.i18n.calendar","gregorian","ja-jp"); 7 */ 8 9 dojo.requireLocalization("dojo.i18n.calendar","gregorian","en"); 10 dojo.requireLocalization("dojo.i18n.calendar","gregorian","fr"); 11 dojo.requireLocalization("dojo.i18n.calendar","gregorian","de"); 12 dojo.requireLocalization("dojo.i18n.calendar","gregorian","ja"); 6 13 7 14 dojo.require("dojo.date.format"); … … 156 163 157 164 function test_date_parse() { 158 var tzOffset = new Date().getTimezoneOffset()*60*1000; 159 jum.assertEquals("parse_test1", "1155283200000", dojo.date.parse("08/11/06", {formatLength:'short',selector:'dateOnly', locale:'en-us'}).getTime()+tzOffset); 160 } 165 var i = 0; 166 function name() { return "parse_test" + i++; } 167 168 /*********** 169 DATES 170 ***********/ 171 172 var aug_11_2006 = new Date(2006, 7, 11, 0); 173 var aug_11_06CE = new Date(2006, 7, 11, 0); 174 aug_11_06CE.setFullYear(6); //literally the year 6 C.E. 175 176 //en: 'short' fmt: M/d/yy 177 // Tolerate either 8 or 08 for month part. 178 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("08/11/06", {formatLength:'short', locale:'en'})); 179 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("8/11/06", {formatLength:'short', locale:'en'})); 180 // Tolerate yyyy input in yy part... 181 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("8/11/2006", {formatLength:'short', locale:'en'})); 182 // ...but not in strict mode 183 jum.assertEquals(name(), null, dojo.date.parse("8/11/2006", {formatLength:'short', locale:'en', strict:true})); 184 185 //en: 'medium' fmt: MMM d, yyyy 186 // Tolerate either 8 or 08 for month part. 187 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("Aug 11, 2006", {formatLength:'medium', locale:'en'})); 188 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("Aug 11, 2006", {formatLength:'medium', locale:'en'})); 189 // Tolerate abbreviating period in month part... 190 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("Aug. 11, 2006", {formatLength:'medium', locale:'en'})); 191 // ...but not in strict mode 192 jum.assertEquals(name(), null, dojo.date.parse("Aug. 11, 2006", {formatLength:'medium', locale:'en', strict:true})); 193 // Note: 06 for year part will be translated literally as the year 6 C.E. 194 jum.assertEquals(name(), aug_11_06CE, dojo.date.parse("Aug 11, 06", {formatLength:'medium', locale:'en'})); 195 //en: 'long' fmt: MMMM d, yyyy 196 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("August 11, 2006", {formatLength:'long', locale:'en'})); 197 198 //en: 'full' fmt: EEEE, MMMM d, yyyy 199 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("Friday, August 11, 2006", {formatLength:'full', locale:'en'})); 200 //TODO: wrong day-of-week should fail 201 //jum.assertEquals(name(), null, dojo.date.parse("Thursday, August 11, 2006", {formatLength:'full', locale:'en'})); 202 203 //Whitespace tolerance 204 jum.assertEquals(name(), aug_11_2006, dojo.date.parse(" August 11, 2006", {formatLength:'long', locale:'en'})); 205 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("August 11, 2006", {formatLength:'long', locale:'en'})); 206 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("August 11 , 2006", {formatLength:'long', locale:'en'})); 207 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("August 11, 2006", {formatLength:'long', locale:'en'})); 208 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("August 11, 2006 ", {formatLength:'long', locale:'en'})); 209 210 //Simple Validation Tests 211 //catch "month" > 12 (note: month/day reversals are common when user expectation isn't met wrt european versus US formats) 212 jum.assertEquals(name(), null, dojo.date.parse("15/1/2005", {formatLength:'short', locale:'en'})); 213 //day of month typo rolls over to the next month 214 jum.assertEquals(name(), null, dojo.date.parse("Aug 32, 2006", {formatLength:'medium', locale:'en'})); 215 216 //Spanish (es) 217 //es: 'short' fmt: d/MM/yy 218 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11/08/06", {formatLength:'short', locale:'es'})); 219 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11/8/06", {formatLength:'short', locale:'es'})); 220 // Tolerate yyyy input in yy part... 221 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11/8/2006", {formatLength:'short', locale:'es'})); 222 // ...but not in strict mode 223 jum.assertEquals(name(), null, dojo.date.parse("11/8/2006", {formatLength:'short', locale:'es', strict:true})); 224 //es: 'medium' fmt: dd-MMM-yy 225 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11-ago-06", {formatLength:'medium', locale:'es'})); 226 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11-ago-2006", {formatLength:'medium', locale:'es'})); 227 // Tolerate abbreviating period in month part... 228 jum.assertEquals(name(), aug_11_2006, dojo.date.parse("11-ago.-2006", {formatLength:'medium', locale:'es'})); 229 // ...but not in strict mode 230 jum.assertEquals(name(), null, dojo.date.parse("11-ago.-2006", {formatLength:'medium', locale:'es', strict:true})); 231 //es: 'long' fmt: d' de 'MMMM' de 'yyyy