1 57 58 package com.sun.org.apache.xerces.internal.impl.dv.xs; 59 60 77 public abstract class AbstractDateTimeDV extends TypeValidator { 78 79 private static final boolean DEBUG=false; 81 82 84 protected final static int CY = 0, M = 1, D = 2, h = 3, 86 m = 4, s = 5, ms = 6, utc=7, hh=0, mm=1; 87 88 protected final static int TOTAL_SIZE = 8; 91 92 protected final static int YEAR=2000; 95 protected final static int MONTH=01; 96 protected final static int DAY = 15; 97 98 public short getAllowedFacets(){ 99 return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE ); 100 } 102 public int compare (Object value1, Object value2) { 104 return compareDates(((DateTimeData)value1).data, 105 ((DateTimeData)value2).data, true); 106 } 108 117 protected short compareDates(int[] date1, int[] date2, boolean strict) { 118 if ( date1[utc]==date2[utc] ) { 119 return compareOrder(date1, date2); 120 } 121 short c1, c2; 122 123 int[] tempDate = new int[TOTAL_SIZE]; 124 int[] timeZone = new int[2]; 125 126 if ( date1[utc]=='Z' ) { 127 128 cloneDate(date2, tempDate); timeZone[hh]=14; 132 timeZone[mm]=0; 133 tempDate[utc]='+'; 134 normalize(tempDate, timeZone); 135 c1 = compareOrder(date1, tempDate); 136 if (c1 == LESS_THAN) 137 return c1; 138 139 cloneDate(date2, tempDate); timeZone[hh]=14; 143 timeZone[mm]=0; 144 tempDate[utc]='-'; 145 normalize(tempDate, timeZone); 146 c2 = compareOrder(date1, tempDate); 147 if (c2 == GREATER_THAN) 148 return c2; 149 150 return INDETERMINATE; 151 } 152 else if ( date2[utc]=='Z' ) { 153 154 cloneDate(date1, tempDate); timeZone[hh]=14; 158 timeZone[mm]=0; 159 tempDate[utc]='-'; 160 if (DEBUG) { 161 System.out.println("tempDate=" + dateToString(tempDate)); 162 } 163 normalize(tempDate, timeZone); 164 c1 = compareOrder(tempDate, date2); 165 if (DEBUG) { 166 System.out.println("date=" + dateToString(date2)); 167 System.out.println("tempDate=" + dateToString(tempDate)); 168 } 169 if (c1 == LESS_THAN) 170 return c1; 171 172 cloneDate(date1, tempDate); timeZone[hh]=14; 176 timeZone[mm]=0; 177 tempDate[utc]='+'; 178 normalize(tempDate, timeZone); 179 c2 = compareOrder(tempDate, date2); 180 if (DEBUG) { 181 System.out.println("tempDate=" + dateToString(tempDate)); 182 } 183 if (c2 == GREATER_THAN) 184 return c2; 185 186 return INDETERMINATE; 187 } 188 return INDETERMINATE; 189 190 } 191 192 200 protected short compareOrder (int[] date1, int[] date2) { 201 202 for ( int i=0;i<TOTAL_SIZE;i++ ) { 203 if ( date1[i]<date2[i] ) { 204 return -1; 205 } 206 else if ( date1[i]>date2[i] ) { 207 return 1; 208 } 209 } 210 return 0; 211 } 212 213 221 protected void getTime (String buffer, int start, int end, int[] data, int[] timeZone) throws RuntimeException { 222 223 int stop = start+2; 224 225 data[h]=parseInt(buffer, start,stop); 227 228 230 if (buffer.charAt(stop++)!=':') { 231 throw new RuntimeException ("Error in parsing time zone" ); 232 } 233 start = stop; 234 stop = stop+2; 235 data[m]=parseInt(buffer, start,stop); 236 237 if (buffer.charAt(stop++)!=':') { 239 throw new RuntimeException ("Error in parsing time zone" ); 240 } 241 start = stop; 242 stop = stop+2; 243 data[s]=parseInt(buffer, start,stop); 244 245 if (stop == end) 246 return; 247 248 start = stop; 250 int milisec = buffer.charAt(start) == '.' ? start : -1; 251 252 int sign = findUTCSign(buffer, start, end); 254 255 if ( milisec != -1 ) { 257 start = sign < 0 ? end : sign; 260 data[ms]=parseInt(buffer, milisec+1, start); 261 } 262 263 if ( sign>0 ) { 265 if (start != sign) 266 throw new RuntimeException ("Error in parsing time zone" ); 267 getTimeZone(buffer, data, sign, end, timeZone); 268 } 269 else if (start != end) { 270 throw new RuntimeException ("Error in parsing time zone" ); 271 } 272 } 273 274 282 protected int getDate (String buffer, int start, int end, int[] date) throws RuntimeException { 283 284 start = getYearMonth(buffer, start, end, date); 285 286 if (buffer.charAt(start++) !='-') { 287 throw new RuntimeException ("CCYY-MM must be followed by '-' sign"); 288 } 289 int stop = start + 2; 290 date[D]=parseInt(buffer, start, stop); 291 return stop; 292 } 293 294 302 protected int getYearMonth (String buffer, int start, int end, int[] date) throws RuntimeException { 303 304 if ( buffer.charAt(0)=='-' ) { 305 start++; 309 } 310 int i = indexOf(buffer, start, end, '-'); 311 if ( i==-1 ) throw new RuntimeException ("Year separator is missing or misplaced"); 312 int length = i-start; 313 if (length<4) { 314 throw new RuntimeException ("Year must have 'CCYY' format"); 315 } 316 else if (length > 4 && buffer.charAt(start)=='0'){ 317 throw new RuntimeException ("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden"); 318 } 319 date[CY]= parseIntYear(buffer, i); 320 if (buffer.charAt(i)!='-') { 321 throw new RuntimeException ("CCYY must be followed by '-' sign"); 322 } 323 start = ++i; 324 i = start +2; 325 date[M]=parseInt(buffer, start, i); 326 return i; } 328 329 337 protected void parseTimeZone (String buffer, int start, int end, int[] date, int[] timeZone) throws RuntimeException { 338 339 341 if ( start<end ) { 342 int sign = findUTCSign(buffer, start, end); 343 if ( sign<0 ) { 344 throw new RuntimeException ("Error in month parsing"); 345 } 346 else { 347 getTimeZone(buffer, date, sign, end, timeZone); 348 } 349 } 350 } 351 352 359 protected void getTimeZone (String buffer, int[] data, int sign, int end, int[] timeZone) throws RuntimeException { 360 data[utc]=buffer.charAt(sign); 361 362 if ( buffer.charAt(sign) == 'Z' ) { 363 if (end>(++sign)) { 364 throw new RuntimeException ("Error in parsing time zone"); 365 } 366 return; 367 } 368 if ( sign<=(end-6) ) { 369 370 int stop = ++sign+2; 372 timeZone[hh]=parseInt(buffer, sign, stop); 373 if (buffer.charAt(stop++)!=':') { 374 throw new RuntimeException ("Error in parsing time zone" ); 375 } 376 377 timeZone[mm]=parseInt(buffer, stop, stop+2); 379 380 if ( stop+2!=end ) { 381 throw new RuntimeException ("Error in parsing time zone"); 382 } 383 384 } 385 else { 386 throw new RuntimeException ("Error in parsing time zone"); 387 } 388 if ( DEBUG ) { 389 System.out.println("time[hh]="+timeZone[hh] + " time[mm]=" +timeZone[mm]); 390 } 391 } 392 393 401 protected int indexOf (String buffer, int start, int end, char ch) { 402 for ( int i=start;i<end;i++ ) { 403 if ( buffer.charAt(i) == ch ) { 404 return i; 405 } 406 } 407 return -1; 408 } 409 410 416 protected void validateDateTime (int[] data, int[] timeZone) { 417 418 if ( data[CY]==0 ) { 421 throw new RuntimeException ("The year \"0000\" is an illegal year value"); 422 423 } 424 425 if ( data[M]<1 || data[M]>12 ) { 426 throw new RuntimeException ("The month must have values 1 to 12"); 427 428 } 429 430 if ( data[D]>maxDayInMonthFor(data[CY], data[M]) || data[D]<1 ) { 432 throw new RuntimeException ("The day must have values 1 to 31"); 433 } 434 435 if ( data[h]>23 || data[h]<0 ) { 437 if (data[h] == 24 && data[m] == 0 && data[s] == 0 && data[ms] == 0) { 438 data[h] = 0; 439 if (++data[D] > maxDayInMonthFor(data[CY], data[M])) { 440 data[D] = 1; 441 if (++data[M] > 12) { 442 data[M] = 1; 443 if (++data[CY] == 0) 444 data[CY] = 1; 445 } 446 } 447 } 448 else { 449 throw new RuntimeException ("Hour must have values 0-23, unless 24:00:00"); 450 } 451 } 452 453 if ( data[m]>59 || data[m]<0 ) { 455 throw new RuntimeException ("Minute must have values 0-59"); 456 } 457 458 if ( data[s]>60 || data[s]<0 ) { 460 throw new RuntimeException ("Second must have values 0-60"); 461 462 } 463 464 if ( timeZone[hh]>14 || timeZone[hh]<-14 ) { 466 throw new RuntimeException ("Time zone should have range -14..+14"); 467 } 468 469 if ( timeZone[mm]>59 || timeZone[mm]<-59 ) { 471 throw new RuntimeException ("Minute must have values 0-59"); 472 } 473 } 474 475 482 protected int findUTCSign (String buffer, int start, int end) { 483 int c; 484 for ( int i=start;i<end;i++ ) { 485 c=buffer.charAt(i); 486 if ( c == 'Z' || c=='+' || c=='-' ) { 487 return i; 488 } 489 490 } 491 return -1; 492 } 493 494 502 protected int parseInt (String buffer, int start, int end) 503 throws NumberFormatException { 504 int radix=10; 506 int result = 0; 507 int digit=0; 508 int limit = -Integer.MAX_VALUE; 509 int multmin = limit / radix; 510 int i = start; 511 do { 512 digit = getDigit(buffer.charAt(i)); 513 if ( digit < 0 ) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 514 if ( result < multmin ) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 515 result *= radix; 516 if ( result < limit + digit ) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 517 result -= digit; 518 519 }while ( ++i < end ); 520 return -result; 521 } 522 523 protected int parseIntYear (String buffer, int end){ 525 int radix=10; 526 int result = 0; 527 boolean negative = false; 528 int i=0; 529 int limit; 530 int multmin; 531 int digit=0; 532 533 if (buffer.charAt(0) == '-'){ 534 negative = true; 535 limit = Integer.MIN_VALUE; 536 i++; 537 538 } 539 else{ 540 limit = -Integer.MAX_VALUE; 541 } 542 multmin = limit / radix; 543 while (i < end) 544 { 545 digit = getDigit(buffer.charAt(i++)); 546 if (digit < 0) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 547 if (result < multmin) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 548 result *= radix; 549 if (result < limit + digit) throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 550 result -= digit; 551 } 552 553 if (negative) 554 { 555 if (i > 1) return result; 556 else throw new NumberFormatException ("'"+buffer.toString()+"' has wrong format"); 557 } 558 return -result; 559 560 } 561 562 568 protected void normalize (int[] date, int[] timeZone) { 569 570 574 int negate = 1; 576 if (date[utc]=='+') { 577 negate = -1; 578 } 579 if ( DEBUG ) { 580 System.out.println("==>date[m]"+date[m]); 581 System.out.println("==>timeZone[mm]" +timeZone[mm]); 582 } 583 int temp = date[m] + negate*timeZone[mm]; 584 int carry = fQuotient (temp, 60); 585 date[m]= mod(temp, 60, carry); 586 587 if ( DEBUG ) { 588 System.out.println("==>carry: " + carry); 589 } 590 temp = date[h] + negate*timeZone[hh] + carry; 592 carry = fQuotient(temp, 24); 593 date[h]=mod(temp, 24, carry); 594 if ( DEBUG ) { 595 System.out.println("==>date[h]"+date[h]); 596 System.out.println("==>carry: " + carry); 597 } 598 599 date[D]=date[D]+carry; 600 601 while ( true ) { 602 temp=maxDayInMonthFor(date[CY], date[M]); 603 if (date[D]<1) { 604 date[D] = date[D] + maxDayInMonthFor(date[CY], date[M]-1); 605 carry=-1; 606 } 607 else if ( date[D]>temp ) { 608 date[D]=date[D]-temp; 609 carry=1; 610 } 611 else { 612 break; 613 } 614 temp=date[M]+carry; 615 date[M]=modulo(temp, 1, 13); 616 date[CY]=date[CY]+fQuotient(temp, 1, 13); 617 } 618 date[utc]='Z'; 619 } 620 621 622 627 protected void resetDateObj (int[] data) { 628 for ( int i=0;i<TOTAL_SIZE;i++ ) { 629 data[i]=0; 630 } 631 } 632 633 641 protected int maxDayInMonthFor(int year, int month) { 642 if ( month==4 || month==6 || month==9 || month==11 ) { 644 return 30; 645 } 646 else if ( month==2 ) { 647 if ( isLeapYear(year) ) { 648 return 29; 649 } 650 else { 651 return 28; 652 } 653 } 654 else { 655 return 31; 656 } 657 } 658 659 private boolean isLeapYear(int year) { 660 661 return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); 663 } 664 665 protected int mod (int a, int b, int quotient) { 669 return (a - quotient*b) ; 671 } 672 673 protected int fQuotient (int a, int b) { 677 678 return (int)Math.floor((float)a/b); 680 } 681 682 protected int modulo (int temp, int low, int high) { 686 int a = temp - low; 688 int b = high - low; 689 return (mod (a, b, fQuotient(a, b)) + low) ; 690 } 691 692 protected int fQuotient (int temp, int low, int high) { 696 698 return fQuotient(temp - low, high - low); 699 } 700 701 702 protected String dateToString(int[] date) { 703 StringBuffer message = new StringBuffer (25); 704 append(message, date[CY], 4); 705 message.append('-'); 706 append(message, date[M], 2); 707 message.append('-'); 708 append(message, date[D], 2); 709 message.append('T'); 710 append(message, date[h], 2); 711 message.append(':'); 712 append(message, date[m], 2); 713 message.append(':'); 714 append(message, date[s], 2); 715 message.append('.'); 716 message.append(date[ms]); 717 append(message, (char)date[utc], 0); 718 return message.toString(); 719 } 720 721 protected void append(StringBuffer message, int value, int nch) { 722 if (value < 0) { 723 message.append('-'); 724 value = -value; 725 } 726 if (nch == 4) { 727 if (value < 10) 728 message.append("000"); 729 else if (value < 100) 730 message.append("00"); 731 else if (value < 1000) 732 message.append("0"); 733 message.append(value); 734 } 735 else if (nch == 2) { 736 if (value < 10) 737 message.append('0'); 738 message.append(value); 739 } 740 else { 741 if (value != 0) 742 message.append((char)value); 743 } 744 } 745 746 750 private void cloneDate (int[] finalValue, int[] tempDate) { 751 System.arraycopy(finalValue, 0, tempDate, 0, TOTAL_SIZE); 752 } 753 754 757 static final class DateTimeData { 758 final int[] data; 760 final AbstractDateTimeDV type; 764 private String canonical; 765 public DateTimeData(int[] data, AbstractDateTimeDV type) { 766 this.data = data; 767 this.type = type; 768 } 769 public boolean equals(Object obj) { 770 if (!(obj instanceof DateTimeData)) 771 return false; 772 int[] odata = ((DateTimeData)obj).data; 773 return type.compareDates(data, odata, true)==0; 774 } 775 public synchronized String toString() { 776 if (canonical == null) { 777 canonical = type.dateToString(data); 778 } 779 return canonical; 780 } 781 } 782 } 783 | Popular Tags |