1 16 17 package com.google.gwt.i18n.client; 18 19 import com.google.gwt.core.client.GWT; 20 import com.google.gwt.i18n.client.constants.DateTimeConstants; 21 22 import java.util.ArrayList ; 23 import java.util.Date ; 24 25 303 public class DateTimeFormat { 304 307 private class PatternPart { 308 public String text; 309 public int count; public boolean abutStart; 311 312 public PatternPart(String txt, int cnt) { 313 text = txt; 314 count = cnt; 315 abutStart = false; 316 } 317 } 318 319 private static final int FULL_DATE_FORMAT = 0; 320 private static final int LONG_DATE_FORMAT = 1; 321 private static final int MEDIUM_DATE_FORMAT = 2; 322 private static final int SHORT_DATE_FORMAT = 3; 323 private static final int FULL_TIME_FORMAT = 0; 324 private static final int LONG_TIME_FORMAT = 1; 325 private static final int MEDIUM_TIME_FORMAT = 2; 326 327 private static final int SHORT_TIME_FORMAT = 3; 328 private static final int NUMBER_BASE = 10; 329 private static final int JS_START_YEAR = 1900; 330 331 private static DateTimeFormat cachedFullDateFormat; 332 private static DateTimeFormat cachedLongDateFormat; 333 private static DateTimeFormat cachedMediumDateFormat; 334 335 private static DateTimeFormat cachedShortDateFormat; 336 private static DateTimeFormat cachedFullTimeFormat; 337 private static DateTimeFormat cachedLongTimeFormat; 338 private static DateTimeFormat cachedMediumTimeFormat; 339 340 private static DateTimeFormat cachedShortTimeFormat; 341 private static DateTimeFormat cachedFullDateTimeFormat; 342 private static DateTimeFormat cachedLongDateTimeFormat; 343 private static DateTimeFormat cachedMediumDateTimeFormat; 344 private static DateTimeFormat cachedShortDateTimeFormat; 345 346 private static final DateTimeConstants defaultDateTimeConstants = (DateTimeConstants) GWT.create(DateTimeConstants.class); 347 348 private static final String PATTERN_CHARS = "GyMdkHmsSEDahKzZv"; 349 350 private static final String NUMERIC_FORMAT_CHARS = "MydhHmsSDkK"; 351 352 private static final String WHITE_SPACE = " \t\r\n"; 353 354 private static final String GMT = "GMT"; 355 356 private static final int MINUTES_PER_HOUR = 60; 357 358 373 public static DateTimeFormat getFormat(String pattern) { 374 return new DateTimeFormat(pattern, defaultDateTimeConstants); 375 } 376 377 public static DateTimeFormat getFullDateFormat() { 378 if (cachedFullDateFormat == null) { 379 String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT]; 380 cachedFullDateFormat = new DateTimeFormat(pattern); 381 } 382 return cachedFullDateFormat; 383 } 384 385 public static DateTimeFormat getFullDateTimeFormat() { 386 if (cachedFullDateTimeFormat == null) { 387 String pattern = defaultDateTimeConstants.dateFormats()[FULL_DATE_FORMAT] 388 + " " + defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT]; 389 cachedFullDateTimeFormat = new DateTimeFormat(pattern); 390 } 391 return cachedFullDateTimeFormat; 392 } 393 394 public static DateTimeFormat getFullTimeFormat() { 395 if (cachedFullTimeFormat == null) { 396 String pattern = defaultDateTimeConstants.timeFormats()[FULL_TIME_FORMAT]; 397 cachedFullTimeFormat = new DateTimeFormat(pattern); 398 } 399 return cachedFullTimeFormat; 400 } 401 402 public static DateTimeFormat getLongDateFormat() { 403 if (cachedLongDateFormat == null) { 404 String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT]; 405 cachedLongDateFormat = new DateTimeFormat(pattern); 406 } 407 return cachedLongDateFormat; 408 } 409 410 public static DateTimeFormat getLongDateTimeFormat() { 411 if (cachedLongDateTimeFormat == null) { 412 String pattern = defaultDateTimeConstants.dateFormats()[LONG_DATE_FORMAT] 413 + " " + defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT]; 414 cachedLongDateTimeFormat = new DateTimeFormat(pattern); 415 } 416 return cachedLongDateTimeFormat; 417 } 418 419 public static DateTimeFormat getLongTimeFormat() { 420 if (cachedLongTimeFormat == null) { 421 String pattern = defaultDateTimeConstants.timeFormats()[LONG_TIME_FORMAT]; 422 cachedLongTimeFormat = new DateTimeFormat(pattern); 423 } 424 return cachedLongTimeFormat; 425 } 426 427 public static DateTimeFormat getMediumDateFormat() { 428 if (cachedMediumDateFormat == null) { 429 String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT]; 430 cachedMediumDateFormat = new DateTimeFormat(pattern); 431 } 432 return cachedMediumDateFormat; 433 }; 434 435 public static DateTimeFormat getMediumDateTimeFormat() { 436 if (cachedMediumDateTimeFormat == null) { 437 String pattern = defaultDateTimeConstants.dateFormats()[MEDIUM_DATE_FORMAT] 438 + " " + defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT]; 439 cachedMediumDateTimeFormat = new DateTimeFormat(pattern); 440 } 441 return cachedMediumDateTimeFormat; 442 } 443 444 public static DateTimeFormat getMediumTimeFormat() { 445 if (cachedMediumTimeFormat == null) { 446 String pattern = defaultDateTimeConstants.timeFormats()[MEDIUM_TIME_FORMAT]; 447 cachedMediumTimeFormat = new DateTimeFormat(pattern); 448 } 449 return cachedMediumTimeFormat; 450 } 451 452 public static DateTimeFormat getShortDateFormat() { 453 if (cachedShortDateFormat == null) { 454 String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT]; 455 cachedShortDateFormat = new DateTimeFormat(pattern); 456 } 457 return cachedShortDateFormat; 458 } 459 460 public static DateTimeFormat getShortDateTimeFormat() { 461 if (cachedShortDateTimeFormat == null) { 462 String pattern = defaultDateTimeConstants.dateFormats()[SHORT_DATE_FORMAT] 463 + " " + defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT]; 464 cachedShortDateTimeFormat = new DateTimeFormat(pattern); 465 } 466 return cachedShortDateTimeFormat; 467 } 468 469 public static DateTimeFormat getShortTimeFormat() { 470 if (cachedShortTimeFormat == null) { 471 String pattern = defaultDateTimeConstants.timeFormats()[SHORT_TIME_FORMAT]; 472 cachedShortTimeFormat = new DateTimeFormat(pattern); 473 } 474 return cachedShortTimeFormat; 475 } 476 477 private final ArrayList patternParts = new ArrayList (); 478 479 private final DateTimeConstants dateTimeConstants; 480 481 private final String pattern;; 482 483 489 protected DateTimeFormat(String pattern) { 490 this(pattern, defaultDateTimeConstants); 491 }; 492 493 500 protected DateTimeFormat(String pattern, DateTimeConstants dateTimeConstants) { 501 this.pattern = pattern; 502 this.dateTimeConstants = dateTimeConstants; 503 504 509 parsePattern(pattern); 510 }; 511 512 519 public String format(Date date) { 520 StringBuffer toAppendTo = new StringBuffer (64); 521 int j, n = pattern.length(); 522 for (int i = 0; i < n;) { 523 char ch = pattern.charAt(i); 524 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) { 525 for (j = i + 1; j < n && pattern.charAt(j) == ch; ++j) { 528 } 529 subFormat(toAppendTo, ch, j - i, date); 530 i = j; 531 } else if (ch == '\'') { 532 535 ++i; 537 538 if (i < n && pattern.charAt(i) == '\'') { 540 toAppendTo.append('\''); 541 ++i; 542 continue; 543 } 544 545 boolean trailQuote = false; 547 while (!trailQuote) { 548 j = i; 550 while (j < n && pattern.charAt(j) != '\'') { 551 ++j; 552 } 553 554 if (j >= n) { 555 throw new IllegalArgumentException ("Missing trailing \'"); 557 } 558 559 if (j + 1 < n && pattern.charAt(j + 1) == '\'') { 561 ++j; 562 } else { 563 trailQuote = true; 564 } 565 toAppendTo.append(pattern.substring(i, j)); 566 i = j + 1; 567 } 568 } else { 569 toAppendTo.append(ch); 571 ++i; 572 } 573 } 574 575 return toAppendTo.toString(); 576 }; 577 578 public String getPattern() { 579 return pattern; 580 }; 581 582 592 public Date parse(String text) { 593 Date date = new Date (); 594 int charsConsumed = parse(text, 0, date); 595 if (charsConsumed == 0 || charsConsumed < text.length()) { 596 throw new IllegalArgumentException (text); 597 } 598 return date; 599 } 600 601 610 public int parse(String text, int start, Date date) { 611 DateRecord cal = new DateRecord(); 612 int[] parsePos = {start}; 613 614 int abutPat = -1; int abutStart = 0; 621 int abutPass = 0; 622 623 for (int i = 0; i < patternParts.size(); ++i) { 624 PatternPart part = (PatternPart) patternParts.get(i); 625 626 if (part.count > 0) { 627 if (abutPat < 0 && part.abutStart) { 628 abutPat = i; 629 abutStart = start; 630 abutPass = 0; 631 } 632 633 if (abutPat >= 0) { 641 int count = part.count; 646 if (i == abutPat) { 647 count -= abutPass++; 648 if (count == 0) { 649 return 0; 650 } 651 } 652 653 if (!subParse(text, parsePos, part, count, cal)) { 654 i = abutPat - 1; 657 parsePos[0] = abutStart; 658 continue; 659 } 660 } else { 661 abutPat = -1; 663 if (!subParse(text, parsePos, part, 0, cal)) { 664 return 0; 665 } 666 } 667 } else { 668 abutPat = -1; 671 if (part.text.charAt(0) == ' ') { 674 int s = parsePos[0]; 676 skipSpace(text, parsePos); 677 678 if (parsePos[0] > s) { 680 continue; 681 } 682 } else if (text.startsWith(part.text, parsePos[0])) { 683 parsePos[0] += part.text.length(); 684 continue; 685 } 686 687 return 0; 689 } 690 } 691 692 if (!cal.calcDate(date)) { 693 return 0; 694 } 695 696 return parsePos[0] - start; 698 }; 699 700 707 private void addPart(StringBuffer buf, int count) { 708 if (buf.length() > 0) { 709 patternParts.add((new PatternPart(buf.toString(), count))); 710 buf.setLength(0); 711 } 712 }; 713 714 720 private void appendGMT(StringBuffer buf, Date date) { 721 int value = -date.getTimezoneOffset(); 722 723 if (value < 0) { 724 buf.append("GMT-"); 725 value = -value; } else { 727 buf.append("GMT+"); 728 } 729 730 zeroPaddingNumber(buf, value / MINUTES_PER_HOUR, 2); 731 buf.append(':'); 732 zeroPaddingNumber(buf, value % MINUTES_PER_HOUR, 2); 733 }; 734 735 743 private void format0To11Hours(StringBuffer buf, int count, Date date) { 744 int value = date.getHours() % 12; 745 zeroPaddingNumber(buf, value, count); 746 }; 747 748 756 private void format0To23Hours(StringBuffer buf, int count, Date date) { 757 int value = date.getHours(); 758 zeroPaddingNumber(buf, value, count); 759 }; 760 761 769 private void format1To12Hours(StringBuffer buf, int count, Date date) { 770 int value = date.getHours() % 12; 771 if (value == 0) { 772 zeroPaddingNumber(buf, 12, count); 773 } else { 774 zeroPaddingNumber(buf, value, count); 775 } 776 }; 777 778 786 private void format24Hours(StringBuffer buf, int count, Date date) { 787 int value = date.getHours(); 788 if (value == 0) { 789 zeroPaddingNumber(buf, 24, count); 790 } else { 791 zeroPaddingNumber(buf, value, count); 792 } 793 } 794 795 803 private void formatAmPm(StringBuffer buf, int count, Date date) { 804 if (date.getHours() >= 12 && date.getHours() < 24) { 805 buf.append(dateTimeConstants.ampms()[1]); 806 } else { 807 buf.append(dateTimeConstants.ampms()[0]); 808 } 809 }; 810 811 819 private void formatDate(StringBuffer buf, int count, Date date) { 820 int value = date.getDate(); 821 zeroPaddingNumber(buf, value, count); 822 }; 823 824 832 private void formatDayOfWeek(StringBuffer buf, int count, Date date) { 833 int value = date.getDay(); 834 if (count >= 4) { 835 buf.append(dateTimeConstants.weekdays()[value]); 836 } else { 837 buf.append(dateTimeConstants.shortWeekdays()[value]); 838 } 839 } 840 841 849 private void formatEra(StringBuffer buf, int count, Date date) { 850 int value = date.getYear() >= -JS_START_YEAR ? 1 : 0; 851 if (count >= 4) { 852 buf.append(dateTimeConstants.eraNames()[value]); 853 } else { 854 buf.append(dateTimeConstants.eras()[value]); 855 } 856 } 857 858 866 private void formatFractionalSeconds(StringBuffer buf, int count, Date date) { 867 int value = (int) (date.getTime() % 1000); 871 if (count == 1) { 872 value = (value + 50) / 100; buf.append(Integer.toString(value)); 874 } else if (count == 2) { 875 value = (value + 5) / 10; zeroPaddingNumber(buf, value, 2); 877 } else { 878 zeroPaddingNumber(buf, value, 3); 879 880 if (count > 3) { 881 zeroPaddingNumber(buf, 0, count - 3); 882 } 883 } 884 } 885 886 894 private void formatMinutes(StringBuffer buf, int count, Date date) { 895 int value = date.getMinutes(); 896 zeroPaddingNumber(buf, value, count); 897 } 898 899 907 private void formatMonth(StringBuffer buf, int count, Date date) { 908 int value = date.getMonth(); 909 switch (count) { 910 case 5: 911 buf.append(dateTimeConstants.narrowMonths()[value]); 912 break; 913 case 4: 914 buf.append(dateTimeConstants.standaloneMonths()[value]); 915 break; 916 case 3: 917 buf.append(dateTimeConstants.shortMonths()[value]); 918 break; 919 default: 920 zeroPaddingNumber(buf, value + 1, count); 921 } 922 } 923 924 932 private void formatQuarter(StringBuffer buf, int count, Date date) { 933 int value = date.getMonth() / 3; 934 if (count < 4) { 935 buf.append(dateTimeConstants.shortQuarters()[value]); 936 } else { 937 buf.append(dateTimeConstants.quarters()[value]); 938 } 939 } 940 941 949 private void formatSeconds(StringBuffer buf, int count, Date date) { 950 int value = date.getSeconds(); 951 zeroPaddingNumber(buf, value, count); 952 } 953 954 962 private void formatStandaloneDay(StringBuffer buf, int count, Date date) { 963 int value = date.getDay(); 964 if (count == 5) { 965 buf.append(dateTimeConstants.standaloneNarrowWeekdays()[value]); 966 } else if (count == 4) { 967 buf.append(dateTimeConstants.standaloneWeekdays()[value]); 968 } else if (count == 3) { 969 buf.append(dateTimeConstants.standaloneShortWeekdays()[value]); 970 } else { 971 zeroPaddingNumber(buf, value, 1); 972 } 973 } 974 975 983 private void formatStandaloneMonth(StringBuffer buf, int count, Date date) { 984 int value = date.getMonth(); 985 if (count == 5) { 986 buf.append(dateTimeConstants.standaloneNarrowMonths()[value]); 987 } else if (count == 4) { 988 buf.append(dateTimeConstants.standaloneMonths()[value]); 989 } else if (count == 3) { 990 buf.append(dateTimeConstants.standaloneShortMonths()[value]); 991 } else { 992 zeroPaddingNumber(buf, value + 1, count); 993 } 994 } 995 996 1004 private void formatTimeZoneRFC(StringBuffer buf, int count, Date date) { 1005 if (count < 4) { 1006 int val = date.getTimezoneOffset(); 1008 char sign = '-'; 1009 if (val < 0) { 1010 val = -val; 1011 sign = '+'; 1012 } 1013 1014 val = (val / 3) * 5 + (val % MINUTES_PER_HOUR); buf.append(sign); 1016 zeroPaddingNumber(buf, val, 4); 1017 } else { 1018 appendGMT(buf, date); 1019 } 1020 } 1021 1022 1033 private void formatYear(StringBuffer buf, int count, Date date) { 1034 int value = date.getYear() + JS_START_YEAR; 1035 if (value < 0) { 1036 value = -value; 1037 } 1038 if (count == 2) { 1039 zeroPaddingNumber(buf, value % 100, 2); 1040 } else { 1041 buf.append(Integer.toString(value)); 1043 } 1044 } 1045 1046 1054 private int getNextCharCountInPattern(String pattern, int start) { 1055 char ch = pattern.charAt(start); 1056 int next = start + 1; 1057 while (next < pattern.length() && pattern.charAt(next) == ch) { 1058 ++next; 1059 } 1060 return next - start; 1061 } 1062 1063 1073 private void identifyAbutStart() { 1074 boolean abut = false; 1077 1078 int len = patternParts.size(); 1079 for (int i = 0; i < len; i++) { 1080 if (isNumeric((PatternPart) patternParts.get(i))) { 1081 if (!abut && i + 1 < len 1083 && isNumeric((PatternPart) patternParts.get(i + 1))) { 1084 abut = true; 1085 ((PatternPart) patternParts.get(i)).abutStart = true; 1086 } 1087 } else { 1088 abut = false; 1089 } 1090 } 1091 } 1092 1093 1099 private final boolean isNumeric(PatternPart part) { 1100 if (part.count <= 0) { 1101 return false; 1102 } 1103 int i = NUMERIC_FORMAT_CHARS.indexOf(part.text.charAt(0)); 1104 return (i > 0 || (i == 0 && part.count < 3)); 1105 } 1106 1107 1120 private int matchString(String text, int start, String [] data, int[] pos) { 1121 int count = data.length; 1122 1123 int bestMatchLength = 0, bestMatch = -1; 1128 String textInLowerCase = text.substring(start).toLowerCase(); 1129 for (int i = 0; i < count; ++i) { 1130 int length = data[i].length(); 1131 if (length > bestMatchLength 1134 && textInLowerCase.startsWith(data[i].toLowerCase())) { 1135 bestMatch = i; 1136 bestMatchLength = length; 1137 } 1138 } 1139 if (bestMatch >= 0) { 1140 pos[0] = start + bestMatchLength; 1141 } 1142 return bestMatch; 1143 } 1144 1145 1153 private int parseInt(String text, int[] pos) { 1154 int ret = 0; 1155 int ind = pos[0]; 1156 char ch = text.charAt(ind); 1157 while (ch >= '0' && ch <= '9') { 1158 ret = ret * 10 + (ch - '0'); 1159 ind++; 1160 if (ind >= text.length()) { 1161 break; 1162 } 1163 ch = text.charAt(ind); 1164 } 1165 if (ind > pos[0]) { 1166 pos[0] = ind; 1167 } else { 1168 ret = -1; 1169 } 1170 return ret; 1171 } 1172 1173 1179 private void parsePattern(String pattern) { 1180 StringBuffer buf = new StringBuffer (32); 1181 boolean inQuote = false; 1182 1183 for (int i = 0; i < pattern.length(); i++) { 1184 char ch = pattern.charAt(i); 1185 1186 if (ch == ' ') { 1188 addPart(buf, 0); 1189 buf.append(' '); 1190 addPart(buf, 0); 1191 while (i + 1 < pattern.length() && pattern.charAt(i + 1) == ' ') { 1192 i++; 1193 } 1194 continue; 1195 } 1196 1197 if (inQuote) { 1199 if (ch == '\'') { 1200 if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') { 1201 buf.append(ch); 1203 ++i; 1204 } else { 1205 inQuote = false; 1206 } 1207 } else { 1208 buf.append(ch); 1210 } 1211 continue; 1212 } 1213 1214 if (PATTERN_CHARS.indexOf(ch) > 0) { 1216 addPart(buf, 0); 1217 buf.append(ch); 1218 int count = getNextCharCountInPattern(pattern, i); 1219 addPart(buf, count); 1220 i += count - 1; 1221 continue; 1222 } 1223 1224 if (ch == '\'') { 1226 if (i + 1 < pattern.length() && pattern.charAt(i + 1) == '\'') { 1227 buf.append('\''); 1228 i++; 1229 } else { 1230 inQuote = true; 1231 } 1232 } else { 1233 buf.append(ch); 1234 } 1235 } 1236 1237 addPart(buf, 0); 1238 1239 identifyAbutStart(); 1240 } 1241 1242 1252 private boolean parseTimeZoneOffset(String text, int[] pos, DateRecord cal) { 1253 if (pos[0] >= text.length()) { 1254 cal.setTzOffset(0); 1255 return true; 1256 } 1257 1258 int sign; 1259 switch (text.charAt(pos[0])) { 1260 case '+': 1261 sign = 1; 1262 break; 1263 case '-': 1264 sign = -1; 1265 break; 1266 default: 1267 cal.setTzOffset(0); 1268 return true; 1269 } 1270 ++(pos[0]); 1271 1272 int st = pos[0]; 1274 int value = parseInt(text, pos); 1275 if (value == 0 && pos[0] == st) { 1276 return false; 1277 } 1278 1279 int offset; 1280 if (pos[0] < text.length() && text.charAt(pos[0]) == ':') { 1281 offset = value * MINUTES_PER_HOUR; 1283 ++(pos[0]); 1284 st = pos[0]; 1285 value = parseInt(text, pos); 1286 if (value == 0 && pos[0] == st) { 1287 return false; 1288 } 1289 offset += value; 1290 } else { 1291 offset = value; 1293 if (offset < 24 && (pos[0] - st) <= 2) { 1295 offset *= MINUTES_PER_HOUR; 1296 } else { 1297 offset = offset % 100 + offset / 100 * MINUTES_PER_HOUR; 1298 } 1299 } 1300 1301 offset *= sign; 1302 cal.setTzOffset(-offset); 1303 return true; 1304 } 1305 1306 1312 private void skipSpace(String text, int[] pos) { 1313 while (pos[0] < text.length() 1314 && WHITE_SPACE.indexOf(text.charAt(pos[0])) >= 0) { 1315 ++(pos[0]); 1316 } 1317 } 1318 1319 1330 private boolean subFormat(StringBuffer buf, char ch, int count, Date date) { 1331 switch (ch) { 1332 case 'G': 1333 formatEra(buf, count, date); 1334 break; 1335 case 'y': 1336 formatYear(buf, count, date); 1337 break; 1338 case 'M': 1339 formatMonth(buf, count, date); 1340 break; 1341 case 'k': 1342 format24Hours(buf, count, date); 1343 break; 1344 case 'S': 1345 formatFractionalSeconds(buf, count, date); 1346 break; 1347 case 'E': 1348 formatDayOfWeek(buf, count, date); 1349 break; 1350 case 'a': 1351 formatAmPm(buf, count, date); 1352 break; 1353 case 'h': 1354 format1To12Hours(buf, count, date); 1355 break; 1356 case 'K': 1357 format0To11Hours(buf, count, date); 1358 break; 1359 case 'H': 1360 format0To23Hours(buf, count, date); 1361 break; 1362 case 'c': 1363 formatStandaloneDay(buf, count, date); 1364 break; 1365 case 'L': 1366 formatStandaloneMonth(buf, count, date); 1367 break; 1368 case 'Q': 1369 formatQuarter(buf, count, date); 1370 break; 1371 case 'd': 1372 formatDate(buf, count, date); 1373 break; 1374 case 'm': 1375 formatMinutes(buf, count, date); 1376 break; 1377 case 's': 1378 formatSeconds(buf, count, date); 1379 break; 1380 case 'z': 1381 case 'v': 1382 appendGMT(buf, date); 1383 break; 1384 case 'Z': 1385 formatTimeZoneRFC(buf, count, date); 1386 break; 1387 default: 1388 return false; 1389 } 1390 return true; 1391 } 1392 1393 1405 private boolean subParse(String text, int[] pos, PatternPart part, 1406 int digitCount, DateRecord cal) { 1407 1408 skipSpace(text, pos); 1409 1410 int start = pos[0]; 1411 char ch = part.text.charAt(0); 1412 1413 int value = -1; if (isNumeric(part)) { 1416 if (digitCount > 0) { 1417 if ((start + digitCount) > text.length()) { 1418 return false; 1419 } 1420 value = parseInt(text.substring(0, start + digitCount), pos); 1421 } else { 1422 value = parseInt(text, pos); 1423 } 1424 } 1425 1426 switch (ch) { 1427 case 'G': value = matchString(text, start, dateTimeConstants.eras(), pos); 1429 cal.setEra(value); 1430 return true; 1431 case 'M': return subParseMonth(text, pos, cal, value, start); 1433 case 'E': 1434 return subParseDayOfWeek(text, pos, start, cal); 1435 case 'a': value = matchString(text, start, dateTimeConstants.ampms(), pos); 1437 cal.setAmpm(value); 1438 return true; 1439 case 'y': return subParseYear(text, pos, start, value, part, cal); 1441 case 'd': cal.setDayOfMonth(value); 1443 return true; 1444 case 'S': return subParseFractionalSeconds(value, start, pos[0], cal); 1446 case 'h': if (value == 12) { 1448 value = 0; 1449 } 1450 case 'K': case 'H': cal.setHours(value); 1454 return true; 1455 case 'k': cal.setHours(value); 1457 return true; 1458 case 'm': cal.setMinutes(value); 1460 return true; 1461 case 's': cal.setSeconds(value); 1463 return true; 1464 1465 case 'z': case 'Z': case 'v': return subParseTimeZoneInGMT(text, start, pos, cal); 1469 default: 1470 return false; 1471 } 1472 } 1473 1474 1485 private boolean subParseDayOfWeek(String text, int[] pos, int start, 1486 DateRecord cal) { 1487 int value; 1488 value = matchString(text, start, dateTimeConstants.weekdays(), pos); 1492 if (value < 0) { 1493 value = matchString(text, start, dateTimeConstants.shortWeekdays(), pos); 1494 } 1495 if (value < 0) { 1496 return false; 1497 } 1498 cal.setDayOfWeek(value); 1499 return true; 1500 } 1501 1502 1512 private boolean subParseFractionalSeconds(int value, int start, int end, 1513 DateRecord cal) { 1514 int i = end - start; 1516 if (i < 3) { 1517 while (i < 3) { 1518 value *= 10; 1519 i++; 1520 } 1521 } else { 1522 int a = 1; 1523 while (i > 3) { 1524 a *= 10; 1525 i--; 1526 } 1527 value = (value + (a >> 1)) / a; 1528 } 1529 cal.setMilliseconds(value); 1530 return true; 1531 } 1532 1533 1545 private boolean subParseMonth(String text, int[] pos, DateRecord cal, 1546 int value, int start) { 1547 if (value < 0) { 1549 value = matchString(text, start, dateTimeConstants.months(), pos); 1552 if (value < 0) { value = matchString(text, start, dateTimeConstants.shortMonths(), pos); 1554 } 1555 if (value < 0) { 1556 return false; 1557 } 1558 cal.setMonth(value); 1559 return true; 1560 } else { 1561 cal.setMonth(value - 1); 1562 return true; 1563 } 1564 } 1565 1566 1577 private boolean subParseTimeZoneInGMT(String text, int start, int[] pos, 1578 DateRecord cal) { 1579 1584 if (text.startsWith(GMT, start)) { 1590 pos[0] = start + GMT.length(); 1591 return parseTimeZoneOffset(text, pos, cal); 1592 } 1593 1594 1600 1601 return parseTimeZoneOffset(text, pos, cal); 1606 } 1607 1608 1625 private boolean subParseYear(String text, int[] pos, int start, int value, 1626 PatternPart part, DateRecord cal) { 1627 char ch = ' '; 1628 if (value < 0) { 1629 ch = text.charAt(pos[0]); 1630 if (ch != '+' && ch != '-') { 1632 return false; 1633 } 1634 ++(pos[0]); 1635 value = parseInt(text, pos); 1636 if (value < 0) { 1637 return false; 1638 } 1639 if (ch == '-') { 1640 value = -value; 1641 } 1642 } 1643 1644 if (ch == ' ' && (pos[0] - start) == 2 && part.count == 2) { 1646 Date date = new Date (); 1655 int defaultCenturyStartYear = date.getYear() + 1900 - 80; 1656 int ambiguousTwoDigitYear = defaultCenturyStartYear % 100; 1657 cal.setAmbiguousYear(value == ambiguousTwoDigitYear); 1658 value += (defaultCenturyStartYear / 100) * 100 1659 + (value < ambiguousTwoDigitYear ? 100 : 0); 1660 } 1661 cal.setYear(value); 1662 return true; 1663 }; 1664 1665 1674 private void zeroPaddingNumber(StringBuffer buf, int value, int minWidth) { 1675 int b = NUMBER_BASE; 1676 for (int i = 0; i < minWidth - 1; i++) { 1677 if (value < b) { 1678 buf.append('0'); 1679 } 1680 b *= NUMBER_BASE; 1681 } 1682 buf.append(Integer.toString(value)); 1683 } 1684} 1685 | Popular Tags |