1 74 75 package org.eclipse.emf.ecore.xml.type.internal; 76 77 78 import java.text.DateFormat ; 79 import java.text.FieldPosition ; 80 import java.text.ParseException ; 81 import java.text.SimpleDateFormat ; 82 import java.util.Date ; 83 import java.util.TimeZone ; 84 85 import org.eclipse.emf.common.util.WrappedException; 86 import org.eclipse.emf.ecore.xml.type.InvalidDatatypeValueException; 87 import org.eclipse.emf.ecore.xml.type.internal.DataValue.TypeValidator; 88 89 97 public final class XMLCalendar 98 { 99 public final static short DATETIME = 0; 100 101 public final static short TIME = 1; 102 103 public final static short DATE = 2; 104 105 public final static short GYEARMONTH = 3; 106 107 public final static short GYEAR = 4; 108 109 public final static short GMONTHDAY = 5; 110 111 public final static short GDAY = 6; 112 113 public final static short GMONTH = 7; 114 115 public final static int EQUALS = 0; 116 public final static int LESS_THAN = -1; 117 public final static int GREATER_THAN = 1; 118 public final static int INDETERMINATE = 2; 119 120 121 123 protected final static int CY = 0, M = 1, D = 2, h = 3, m = 4, s = 5, ms = 6, utc = 7, hh = 0, mm = 1; 125 126 protected final static int TOTAL_SIZE = 8; 129 130 private final static int DAY_SIZE = 5; 132 133 private final static int MONTHDAY_SIZE = 7; 135 136 protected final static int YEAR = 2000; 139 140 protected final static int MONTH = 01; 141 142 protected final static int DAY = 15; 143 144 private int[] dateValue; 145 146 final short dataType; 147 148 private Date date; 149 150 protected static final DateFormat [] EDATE_FORMATS = 151 { 152 new SafeSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'.'S'Z'"), 153 new SafeSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"), 154 new SafeSimpleDateFormat("yyyy-MM-dd") 155 }; 156 157 { 158 EDATE_FORMATS[0].setTimeZone(TimeZone.getTimeZone("GMT")); 159 } 160 161 public XMLCalendar(String value, short datatype) 162 { 163 if (value == null || value.length() == 0) 164 { 165 throw new InvalidDatatypeValueException("Incomplete value"); 166 } 167 168 this.dataType = datatype; 169 switch (dataType) 170 { 171 case DATETIME: 172 { 173 this.dateValue = parseDateTime(value); 174 break; 175 } 176 case TIME: 177 { 178 this.dateValue = parseTime(value); 179 break; 180 } 181 case DATE: 182 { 183 this.dateValue = parseDate(value); 184 break; 185 } 186 case GYEAR: 187 { 188 this.dateValue = parseYear(value); 189 break; 190 } 191 case GYEARMONTH: 192 { 193 this.dateValue = parseYearMonth(value); 194 break; 195 } 196 case GMONTHDAY: 197 { 198 this.dateValue = parseMonthDay(value); 199 break; 200 } 201 case GMONTH: 202 { 203 this.dateValue = parseMonth(value); 204 break; 205 } 206 case GDAY: 207 { 208 this.dateValue = parseDay(value); 209 break; 210 } 211 default: 212 throw new IllegalArgumentException ("Illegal datatype value"); 213 } 214 } 215 216 public XMLCalendar(Date date, short dataType) 217 { 218 this.date = date; 219 this.dataType = dataType; 220 } 221 222 public boolean equals(Object obj) 223 { 224 if (!(obj instanceof XMLCalendar)) 225 { 226 return false; 227 } 228 229 XMLCalendar xmlCalendarObj = (XMLCalendar)obj; 230 if (dataType != xmlCalendarObj.dataType) 231 { 232 return false; 233 } 234 235 return compare(this, (XMLCalendar)obj) == EQUALS; 236 } 237 238 public int hashCode() 239 { 240 int hashCode = dataType; 241 int [] dateValue = getDateValue(); 242 for (int i=0;i<TOTAL_SIZE;i++) 243 { 244 hashCode^=dateValue[i]; 245 } 246 return hashCode; 247 } 248 249 public String toString() 250 { 251 switch (dataType) 252 { 253 case DATETIME: return dateTimeToString(); 254 case TIME: return timeToString(); 255 case DATE: return dateToString(); 256 case GYEAR: return yearToString(); 257 case GYEARMONTH: return yearMonthToString(); 258 case GMONTHDAY: return monthDayToString(); 259 case GMONTH: return monthToString(); 260 case GDAY: return dayToString(); 261 } 262 return null; 263 } 264 265 public static int compare(XMLCalendar value1, XMLCalendar value2) 267 { 268 return (value1.dataType != value2.dataType) ? INDETERMINATE : compareDates(value1.getDateValue(), value2.getDateValue(), true); 269 } 271 protected int[] getDateValue() 272 { 273 if (dateValue == null) 274 { 275 dateValue = parseDateTime(XMLCalendar.EDATE_FORMATS[1].format(date)); 276 } 277 return dateValue; 278 } 279 280 public Date getDate() 281 { 282 if (date == null) 283 { 284 try 285 { 286 if (dataType == XMLCalendar.DATETIME) 287 { 288 date = XMLCalendar.EDATE_FORMATS[0].parse(dateTimeToString()); 289 } 290 else if (dataType == XMLCalendar.DATE) 291 { 292 date = XMLCalendar.EDATE_FORMATS[2].parse(dateToString()); 293 } 294 } 295 catch (Exception e) 296 { 297 throw new WrappedException(e); 298 } 299 } 300 return date; 301 } 302 303 312 private static int compareDates(int[] date1, int[] date2, boolean strict) 313 { 314 if (date1[utc] == date2[utc]) 315 { 316 return compareOrder(date1, date2); 317 } 318 short c1, c2; 319 320 int[] tempDate = new int [TOTAL_SIZE]; 321 int[] timeZone = new int [2]; 322 323 if (date1[utc] == 'Z') 324 { 325 326 cloneDate(date2, tempDate); timeZone[hh] = 14; 330 timeZone[mm] = 0; 331 tempDate[utc] = '+'; 332 normalize(tempDate, timeZone); 333 c1 = compareOrder(date1, tempDate); 334 if (c1 == TypeValidator.LESS_THAN) 335 return c1; 336 337 cloneDate(date2, tempDate); timeZone[hh] = 14; 341 timeZone[mm] = 0; 342 tempDate[utc] = '-'; 343 normalize(tempDate, timeZone); 344 c2 = compareOrder(date1, tempDate); 345 if (c2 == TypeValidator.GREATER_THAN) 346 return c2; 347 348 return TypeValidator.INDETERMINATE; 349 } 350 else if (date2[utc] == 'Z') 351 { 352 353 cloneDate(date1, tempDate); timeZone[hh] = 14; 357 timeZone[mm] = 0; 358 tempDate[utc] = '-'; 359 360 normalize(tempDate, timeZone); 361 c1 = compareOrder(tempDate, date2); 362 363 if (c1 == TypeValidator.LESS_THAN) 364 return c1; 365 366 cloneDate(date1, tempDate); timeZone[hh] = 14; 370 timeZone[mm] = 0; 371 tempDate[utc] = '+'; 372 normalize(tempDate, timeZone); 373 c2 = compareOrder(tempDate, date2); 374 375 if (c2 == TypeValidator.GREATER_THAN) 376 return c2; 377 378 return TypeValidator.INDETERMINATE; 379 } 380 return TypeValidator.INDETERMINATE; 381 382 } 383 384 392 protected static short compareOrder(int[] date1, int[] date2) 393 { 394 395 for (int i = 0; i < TOTAL_SIZE; i++) 396 { 397 if (date1[i] < date2[i]) 398 { 399 return -1; 400 } 401 else if (date1[i] > date2[i]) 402 { 403 return 1; 404 } 405 } 406 return 0; 407 } 408 409 412 protected static void getTime(String buffer, int start, int end, int[] data, int[] timeZone) 413 { 414 415 int stop = start + 2; 416 417 data[h] = parseInt(buffer, start, stop); 419 420 422 if (buffer.charAt(stop++) != ':') 423 { 424 throw new InvalidDatatypeValueException("Error in parsing time zone"); 425 } 426 start = stop; 427 stop = stop + 2; 428 data[m] = parseInt(buffer, start, stop); 429 430 if (buffer.charAt(stop++) != ':') 432 { 433 throw new InvalidDatatypeValueException("Error in parsing time zone"); 434 } 435 start = stop; 436 stop = stop + 2; 437 data[s] = parseInt(buffer, start, stop); 438 439 if (stop == end) 440 return; 441 442 start = stop; 444 int milisec = buffer.charAt(start) == '.' ? start : -1; 445 446 int sign = findUTCSign(buffer, start, end); 448 449 if (milisec != -1) 451 { 452 start = sign < 0 ? end : sign; 455 data[ms] = parseInt(buffer, milisec + 1, start); 456 } 457 458 if (sign > 0) 460 { 461 if (start != sign) 462 throw new InvalidDatatypeValueException("Error in parsing time zone"); 463 getTimeZone(buffer, data, sign, end, timeZone); 464 } 465 else if (start != end) 466 { 467 throw new InvalidDatatypeValueException("Error in parsing time zone"); 468 } 469 } 470 471 478 protected static int getDate(String buffer, int start, int end, int[] date) 479 { 480 481 start = getYearMonth(buffer, start, end, date); 482 483 if (buffer.charAt(start++) != '-') 484 { 485 throw new InvalidDatatypeValueException("CCYY-MM must be followed by '-' sign"); 486 } 487 int stop = start + 2; 488 date[D] = parseInt(buffer, start, stop); 489 return stop; 490 } 491 492 499 protected static int getYearMonth(String buffer, int start, int end, int[] date) 500 { 501 502 if (buffer.charAt(0) == '-') 503 { 504 start++; 508 } 509 int i = indexOf(buffer, start, end, '-'); 510 if (i == -1) 511 throw new InvalidDatatypeValueException("Year separator is missing or misplaced"); 512 int length = i - start; 513 if (length < 4) 514 { 515 throw new InvalidDatatypeValueException("Year must have 'CCYY' format"); 516 } 517 else if (length > 4 && buffer.charAt(start) == '0') 518 { 519 throw new InvalidDatatypeValueException( 520 "Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden"); 521 } 522 date[CY] = parseIntYear(buffer, i); 523 if (buffer.charAt(i) != '-') 524 { 525 throw new InvalidDatatypeValueException("CCYY must be followed by '-' sign"); 526 } 527 start = ++i; 528 i = start + 2; 529 date[M] = parseInt(buffer, start, i); 530 return i; } 532 533 540 protected static void parseTimeZone(String buffer, int start, int end, int[] date, int[] timeZone) 541 { 542 543 545 if (start < end) 546 { 547 int sign = findUTCSign(buffer, start, end); 548 if (sign < 0) 549 { 550 throw new InvalidDatatypeValueException("Error in month parsing"); 551 } 552 else 553 { 554 getTimeZone(buffer, date, sign, end, timeZone); 555 } 556 } 557 } 558 559 565 protected static void getTimeZone(String buffer, int[] data, int sign, int end, int[] timeZone) 566 { 567 data[utc] = buffer.charAt(sign); 568 569 if (buffer.charAt(sign) == 'Z') 570 { 571 if (end > (++sign)) 572 { 573 throw new InvalidDatatypeValueException("Error in parsing time zone"); 574 } 575 return; 576 } 577 if (sign <= (end - 6)) 578 { 579 580 int stop = ++sign + 2; 582 timeZone[hh] = parseInt(buffer, sign, stop); 583 if (buffer.charAt(stop++) != ':') 584 { 585 throw new InvalidDatatypeValueException("Error in parsing time zone"); 586 } 587 588 timeZone[mm] = parseInt(buffer, stop, stop + 2); 590 591 if (stop + 2 != end) 592 { 593 throw new InvalidDatatypeValueException("Error in parsing time zone"); 594 } 595 596 } 597 else 598 { 599 throw new InvalidDatatypeValueException("Error in parsing time zone"); 600 } 601 } 602 603 611 protected static int indexOf(String buffer, int start, int end, char ch) 612 { 613 for (int i = start; i < end; i++) 614 { 615 if (buffer.charAt(i) == ch) 616 { 617 return i; 618 } 619 } 620 return -1; 621 } 622 623 629 protected static void validateDateTime(int[] data, int[] timeZone) 630 { 631 632 if (data[CY] == 0) 635 { 636 throw new InvalidDatatypeValueException("The year \"0000\" is an illegal year value"); 637 638 } 639 640 if (data[M] < 1 || data[M] > 12) 641 { 642 throw new InvalidDatatypeValueException("The month must have values 1 to 12"); 643 644 } 645 646 if (data[D] > maxDayInMonthFor(data[CY], data[M]) || data[D] < 1) 648 { 649 throw new InvalidDatatypeValueException("The day must have values 1 to 31"); 650 } 651 652 if (data[h] > 23 || data[h] < 0) 654 { 655 if (data[h] == 24 && data[m] == 0 && data[s] == 0 && data[ms] == 0) 656 { 657 data[h] = 0; 658 if (++data[D] > maxDayInMonthFor(data[CY], data[M])) 659 { 660 data[D] = 1; 661 if (++data[M] > 12) 662 { 663 data[M] = 1; 664 if (++data[CY] == 0) 665 data[CY] = 1; 666 } 667 } 668 } 669 else 670 { 671 throw new InvalidDatatypeValueException("Hour must have values 0-23, unless 24:00:00"); 672 } 673 } 674 675 if (data[m] > 59 || data[m] < 0) 677 { 678 throw new InvalidDatatypeValueException("Minute must have values 0-59"); 679 } 680 681 if (data[s] > 60 || data[s] < 0) 683 { 684 throw new InvalidDatatypeValueException("Second must have values 0-60"); 685 686 } 687 688 if (timeZone[hh] > 14 || timeZone[hh] < -14) 690 { 691 throw new InvalidDatatypeValueException("Time zone should have range -14..+14"); 692 } 693 694 if (timeZone[mm] > 59 || timeZone[mm] < -59) 696 { 697 throw new InvalidDatatypeValueException("Minute must have values 0-59"); 698 } 699 } 700 701 708 private static int findUTCSign(String buffer, int start, int end) 709 { 710 int c; 711 for (int i = start; i < end; i++) 712 { 713 c = buffer.charAt(i); 714 if (c == 'Z' || c == '+' || c == '-') 715 { 716 return i; 717 } 718 719 } 720 return -1; 721 } 722 723 731 protected static int parseInt(String buffer, int start, int end) throws NumberFormatException 732 { 733 int radix = 10; 735 int result = 0; 736 int digit = 0; 737 int limit = -Integer.MAX_VALUE; 738 int multmin = limit / radix; 739 int i = start; 740 do 741 { 742 digit = TypeValidator.getDigit(buffer.charAt(i)); 743 if (digit < 0) 744 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 745 if (result < multmin) 746 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 747 result *= radix; 748 if (result < limit + digit) 749 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 750 result -= digit; 751 752 } 753 while (++i < end); 754 return -result; 755 } 756 757 protected static int parseIntYear(String buffer, int end) 759 { 760 int radix = 10; 761 int result = 0; 762 boolean negative = false; 763 int i = 0; 764 int limit; 765 int multmin; 766 int digit = 0; 767 768 if (buffer.charAt(0) == '-') 769 { 770 negative = true; 771 limit = Integer.MIN_VALUE; 772 i++; 773 774 } 775 else 776 { 777 limit = -Integer.MAX_VALUE; 778 } 779 multmin = limit / radix; 780 while (i < end) 781 { 782 digit = TypeValidator.getDigit(buffer.charAt(i++)); 783 if (digit < 0) 784 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 785 if (result < multmin) 786 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 787 result *= radix; 788 if (result < limit + digit) 789 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 790 result -= digit; 791 } 792 793 if (negative) 794 { 795 if (i > 1) 796 return result; 797 else 798 throw new NumberFormatException ("'" + buffer.toString() + "' has wrong format"); 799 } 800 return -result; 801 802 } 803 804 810 protected static void normalize(int[] date, int[] timeZone) 811 { 812 813 817 int negate = 1; 819 if (date[utc] == '+') 820 { 821 negate = -1; 822 } 823 int temp = date[m] + negate * timeZone[mm]; 824 int carry = fQuotient(temp, 60); 825 date[m] = mod(temp, 60, carry); 826 827 temp = date[h] + negate * timeZone[hh] + carry; 829 carry = fQuotient(temp, 24); 830 date[h] = mod(temp, 24, carry); 831 832 date[D] = date[D] + carry; 833 834 while (true) 835 { 836 temp = maxDayInMonthFor(date[CY], date[M]); 837 if (date[D] < 1) 838 { 839 date[D] = date[D] + maxDayInMonthFor(date[CY], date[M] - 1); 840 carry = -1; 841 } 842 else if (date[D] > temp) 843 { 844 date[D] = date[D] - temp; 845 carry = 1; 846 } 847 else 848 { 849 break; 850 } 851 temp = date[M] + carry; 852 date[M] = modulo(temp, 1, 13); 853 date[CY] = date[CY] + fQuotient(temp, 1, 13); 854 } 855 date[utc] = 'Z'; 856 } 857 858 863 protected static void resetDateObj(int[] data) 864 { 865 for (int i = 0; i < TOTAL_SIZE; i++) 866 { 867 data[i] = 0; 868 } 869 } 870 871 879 protected static int maxDayInMonthFor(int year, int month) 880 { 881 if (month == 4 || month == 6 || month == 9 || month == 11) 883 { 884 return 30; 885 } 886 else if (month == 2) 887 { 888 if (isLeapYear(year)) 889 { 890 return 29; 891 } 892 else 893 { 894 return 28; 895 } 896 } 897 else 898 { 899 return 31; 900 } 901 } 902 903 private static boolean isLeapYear(int year) 904 { 905 906 return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0))); 908 } 909 910 protected static int mod(int a, int b, int quotient) 914 { 915 return (a - quotient * b); 917 } 918 919 protected static int fQuotient(int a, int b) 923 { 924 925 return (int)Math.floor((float)a / b); 927 } 928 929 protected static int modulo(int temp, int low, int high) 933 { 934 int a = temp - low; 936 int b = high - low; 937 return (mod(a, b, fQuotient(a, b)) + low); 938 } 939 940 protected static int fQuotient(int temp, int low, int high) 944 { 945 return fQuotient(temp - low, high - low); 947 } 948 949 private String dateTimeToString() 950 { 951 if (date != null) 952 { 953 return XMLCalendar.EDATE_FORMATS[1].format(date); 954 } 955 StringBuffer message = new StringBuffer (25); 956 append(message, dateValue[CY], 4); 957 message.append('-'); 958 append(message, dateValue[M], 2); 959 message.append('-'); 960 append(message, dateValue[D], 2); 961 message.append('T'); 962 append(message, dateValue[h], 2); 963 message.append(':'); 964 append(message, dateValue[m], 2); 965 message.append(':'); 966 append(message, dateValue[s], 2); 967 message.append('.'); 968 message.append(dateValue[ms]); 969 append(message, (char)dateValue[utc], 0); 970 return message.toString(); 971 } 972 973 private String dateToString() 974 { 975 StringBuffer message = new StringBuffer (25); 976 int[] dateValue = getDateValue(); 977 append(message, dateValue[CY], 4); 978 message.append('-'); 979 append(message, dateValue[M], 2); 980 message.append('-'); 981 append(message, dateValue[D], 2); 982 append(message, (char)dateValue[utc], 0); 983 return message.toString(); 984 } 985 986 private String dayToString() 987 { 988 StringBuffer message = new StringBuffer (6); 989 message.append('-'); 990 message.append('-'); 991 message.append('-'); 992 append(message, dateValue[D], 2); 993 append(message, (char)dateValue[utc], 0); 994 return message.toString(); 995 } 996 997 private String monthDayToString() 998 { 999 StringBuffer message = new StringBuffer (8); 1000 message.append('-'); 1001 message.append('-'); 1002 append(message, dateValue[M], 2); 1003 message.append('-'); 1004 append(message, dateValue[D], 2); 1005 append(message, (char)dateValue[utc], 0); 1006 return message.toString(); 1007 } 1008 1009 private String monthToString() 1010 { 1011 StringBuffer message = new StringBuffer (5); 1012 message.append('-'); 1013 message.append('-'); 1014 append(message, dateValue[M], 2); 1015 append(message, (char)dateValue[utc], 0); 1016 return message.toString(); 1017 } 1018 1019 private String timeToString() 1020 { 1021 StringBuffer message = new StringBuffer (16); 1022 append(message, dateValue[h], 2); 1023 message.append(':'); 1024 append(message, dateValue[m], 2); 1025 message.append(':'); 1026 append(message, dateValue[s], 2); 1027 message.append('.'); 1028 message.append(dateValue[ms]); 1029 append(message, (char)dateValue[utc], 0); 1030 return message.toString(); 1031 } 1032 1033 private String yearToString() 1034 { 1035 StringBuffer message = new StringBuffer (5); 1036 append(message, dateValue[CY], 4); 1037 append(message, (char)dateValue[utc], 0); 1038 return message.toString(); 1039 } 1040 1041 private String yearMonthToString() 1042 { 1043 StringBuffer message = new StringBuffer (25); 1044 append(message, dateValue[CY], 4); 1045 message.append('-'); 1046 append(message, dateValue[M], 2); 1047 append(message, (char)dateValue[utc], 0); 1048 return message.toString(); 1049 } 1050 1051 private static void append(StringBuffer message, int value, int nch) 1052 { 1053 if (value < 0) 1054 { 1055 message.append('-'); 1056 value = -value; 1057 } 1058 if (nch == 4) 1059 { 1060 if (value < 10) 1061 message.append("000"); 1062 else if (value < 100) 1063 message.append("00"); 1064 else if (value < 1000) 1065 message.append("0"); 1066 message.append(value); 1067 } 1068 else if (nch == 2) 1069 { 1070 if (value < 10) 1071 message.append('0'); 1072 message.append(value); 1073 } 1074 else 1075 { 1076 if (value != 0) 1077 message.append((char)value); 1078 } 1079 } 1080 1081 1085 private static void cloneDate(int[] finalValue, int[] tempDate) 1086 { 1087 System.arraycopy(finalValue, 0, tempDate, 0, TOTAL_SIZE); 1088 } 1089 1090 private int[] parseDateTime(String str) throws InvalidDatatypeValueException 1091 { 1092 int len = str.length(); 1093 int[] date = new int [TOTAL_SIZE]; 1094 int[] timeZone = new int [2]; 1095 1096 int end = indexOf(str, 0, len, 'T'); 1097 1098 getDate(str, 0, end, date); 1100 getTime(str, end + 1, len, date, timeZone); 1101 1102 validateDateTime(date, timeZone); 1104 1105 if (date[utc] != 0 && date[utc] != 'Z') 1106 { 1107 normalize(date, timeZone); 1108 } 1109 return date; 1110 } 1111 1112 private int[] parseDate(String str) throws InvalidDatatypeValueException 1113 { 1114 int len = str.length(); 1115 int[] date = new int [TOTAL_SIZE]; 1116 int[] timeZone = new int [2]; 1117 1118 int end = getDate(str, 0, len, date); 1119 parseTimeZone(str, end, len, date, timeZone); 1120 1121 validateDateTime(date, timeZone); 1123 1124 if (date[utc] != 0 && date[utc] != 'Z') 1125 { 1126 normalize(date, timeZone); 1127 } 1128 return date; 1129 } 1130 1131 private int[] parseDay(String str) throws InvalidDatatypeValueException 1132 { 1133 int len = str.length(); 1134 int[] date = new int [TOTAL_SIZE]; 1135 int[] timeZone = new int [2]; 1136 1137 if (str.charAt(0) != '-' || str.charAt(1) != '-' || str.charAt(2) != '-') 1138 { 1139 throw new InvalidDatatypeValueException("Error in day parsing"); 1140 } 1141 1142 date[CY] = YEAR; 1144 date[M] = MONTH; 1145 1146 date[D] = parseInt(str, 3, 5); 1147 1148 if (DAY_SIZE < len) 1149 { 1150 int sign = findUTCSign(str, DAY_SIZE, len); 1151 if (sign < 0) 1152 { 1153 throw new InvalidDatatypeValueException("Error in day parsing"); 1154 } 1155 else 1156 { 1157 getTimeZone(str, date, sign, len, timeZone); 1158 } 1159 } 1160 1161 validateDateTime(date, timeZone); 1163 1164 if (date[utc] != 0 && date[utc] != 'Z') 1165 { 1166 normalize(date, timeZone); 1167 } 1168 return date; 1169 } 1170 1171 private int[] parseMonthDay(String str) throws InvalidDatatypeValueException 1172 { 1173 int len = str.length(); 1174 int[] date = new int [TOTAL_SIZE]; 1175 int[] timeZone = new int [2]; 1176 1177 date[CY] = YEAR; 1179 1180 if (str.charAt(0) != '-' || str.charAt(1) != '-') 1181 { 1182 throw new InvalidDatatypeValueException("Invalid format for gMonthDay: " + str); 1183 } 1184 date[M] = parseInt(str, 2, 4); 1185 int start = 4; 1186 1187 if (str.charAt(start++) != '-') 1188 { 1189 throw new InvalidDatatypeValueException("Invalid format for gMonthDay: " + str); 1190 } 1191 1192 date[D] = parseInt(str, start, start + 2); 1193 1194 if (MONTHDAY_SIZE < len) 1195 { 1196 int sign = findUTCSign(str, MONTHDAY_SIZE, len); 1197 if (sign < 0) 1198 { 1199 throw new InvalidDatatypeValueException("Error in month parsing:" + str); 1200 } 1201 else 1202 { 1203 getTimeZone(str, date, sign, len, timeZone); 1204 } 1205 } 1206 1208 validateDateTime(date, timeZone); 1209 1210 if (date[utc] != 0 && date[utc] != 'Z') 1211 { 1212 normalize(date, timeZone); 1213 } 1214 return date; 1215 } 1216 1217 private int[] parseMonth(String str) throws InvalidDatatypeValueException 1218 { 1219 int len = str.length(); 1220 int[] date = new int [TOTAL_SIZE]; 1221 int[] timeZone = new int [2]; 1222 1223 date[CY] = YEAR; 1225 date[D] = DAY; 1226 if (str.charAt(0) != '-' || str.charAt(1) != '-') 1227 { 1228 throw new InvalidDatatypeValueException("Invalid format for gMonth: " + str); 1229 } 1230 int stop = 4; 1231 date[M] = parseInt(str, 2, stop); 1232 1233 if (str.length() >= stop + 2 && str.charAt(stop) == '-' && str.charAt(stop + 1) == '-') 1237 { 1238 stop += 2; 1239 } 1240 if (stop < len) 1241 { 1242 int sign = findUTCSign(str, stop, len); 1243 if (sign < 0) 1244 { 1245 throw new InvalidDatatypeValueException("Error in month parsing: " + str); 1246 } 1247 else 1248 { 1249 getTimeZone(str, date, sign, len, timeZone); 1250 } 1251 } 1252 validateDateTime(date, timeZone); 1254 1255 if (date[utc] != 0 && date[utc] != 'Z') 1256 { 1257 normalize(date, timeZone); 1258 } 1259 return date; 1260 } 1261 1262 private int[] parseYear(String str) throws InvalidDatatypeValueException 1263 { 1264 int len = str.length(); 1265 int[] date = new int [TOTAL_SIZE]; 1266 int[] timeZone = new int [2]; 1267 1268 int start = 0; 1270 if (str.charAt(0) == '-') 1271 { 1272 start = 1; 1273 } 1274 int sign = findUTCSign(str, start, len); 1275 if (sign == -1) 1276 { 1277 date[CY] = parseIntYear(str, len); 1278 } 1279 else 1280 { 1281 date[CY] = parseIntYear(str, sign); 1282 getTimeZone(str, date, sign, len, timeZone); 1283 } 1284 1285 date[M] = MONTH; 1287 date[D] = 1; 1288 1289 validateDateTime(date, timeZone); 1291 1292 if (date[utc] != 0 && date[utc] != 'Z') 1293 { 1294 normalize(date, timeZone); 1295 } 1296 return date; 1297 } 1298 1299 private int[] parseYearMonth(String str) throws InvalidDatatypeValueException 1300 { 1301 int len = str.length(); 1302 int[] date = new int [TOTAL_SIZE]; 1303 int[] timeZone = new int [2]; 1304 1305 int end = getYearMonth(str, 0, len, date); 1307 date[D] = DAY; 1308 parseTimeZone(str, end, len, date, timeZone); 1309 1310 validateDateTime(date, timeZone); 1312 1313 if (date[utc] != 0 && date[utc] != 'Z') 1314 { 1315 normalize(date, timeZone); 1316 } 1317 return date; 1318 } 1319 1320 private int[] parseTime(String str) throws InvalidDatatypeValueException 1321 { 1322 int len = str.length(); 1323 int[] date = new int [TOTAL_SIZE]; 1324 int[] timeZone = new int [2]; 1325 1326 date[CY] = YEAR; 1329 date[M] = MONTH; 1330 date[D] = DAY; 1331 getTime(str, 0, len, date, timeZone); 1332 1333 1335 validateDateTime(date, timeZone); 1336 1337 if (date[utc] != 0) 1338 { 1339 normalize(date, timeZone); 1340 } 1341 return date; 1342 } 1343 1344 private static class SafeSimpleDateFormat extends SimpleDateFormat 1345 { 1346 public SafeSimpleDateFormat(String pattern) 1347 { 1348 super(pattern); 1349 } 1350 1351 public synchronized Date parse(String source) throws ParseException 1352 { 1353 return super.parse(source); 1354 } 1355 1356 public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) 1357 { 1358 StringBuffer result = super.format(date, toAppendTo, pos); 1359 result.insert(result.length() - 2, ":"); 1360 return result; 1361 } 1362 } 1363 1364} 1365 | Popular Tags |