1 16 17 package org.apache.xerces.jaxp.datatype; 18 19 import java.io.Serializable ; 20 import java.math.BigDecimal ; 21 import java.math.BigInteger ; 22 import java.util.Calendar ; 23 import java.util.Date ; 24 import java.util.GregorianCalendar ; 25 import java.util.Locale ; 26 import java.util.TimeZone ; 27 28 import javax.xml.datatype.DatatypeConstants ; 29 import javax.xml.datatype.Duration ; 30 import javax.xml.datatype.XMLGregorianCalendar ; 31 import javax.xml.namespace.QName ; 32 33 import org.apache.xerces.util.DatatypeMessageFormatter; 34 35 178 179 class XMLGregorianCalendarImpl 180 extends XMLGregorianCalendar 181 implements Serializable , Cloneable { 182 183 184 private BigInteger orig_eon; 185 private int orig_year = DatatypeConstants.FIELD_UNDEFINED; 186 private int orig_month = DatatypeConstants.FIELD_UNDEFINED; 187 private int orig_day = DatatypeConstants.FIELD_UNDEFINED; 188 private int orig_hour = DatatypeConstants.FIELD_UNDEFINED; 189 private int orig_minute = DatatypeConstants.FIELD_UNDEFINED; 190 private int orig_second = DatatypeConstants.FIELD_UNDEFINED; 191 private BigDecimal orig_fracSeconds; 192 private int orig_timezone = DatatypeConstants.FIELD_UNDEFINED; 193 194 197 private BigInteger eon = null; 198 199 202 private int year = DatatypeConstants.FIELD_UNDEFINED; 203 204 207 private int month = DatatypeConstants.FIELD_UNDEFINED; 208 209 212 private int day = DatatypeConstants.FIELD_UNDEFINED; 213 214 217 private int timezone = DatatypeConstants.FIELD_UNDEFINED; 218 219 222 private int hour = DatatypeConstants.FIELD_UNDEFINED; 223 224 227 private int minute = DatatypeConstants.FIELD_UNDEFINED; 228 229 232 private int second = DatatypeConstants.FIELD_UNDEFINED ; 233 234 237 private BigDecimal fractionalSecond = null; 238 239 242 private static final BigInteger BILLION = new BigInteger ("1000000000"); 243 244 248 private static final Date PURE_GREGORIAN_CHANGE = 249 new Date (Long.MIN_VALUE); 250 251 254 private static final int YEAR = 0; 255 256 259 private static final int MONTH = 1; 260 261 264 private static final int DAY = 2; 265 266 269 private static final int HOUR = 3; 270 271 274 private static final int MINUTE = 4; 275 276 279 private static final int SECOND = 5; 280 281 284 private static final int MILLISECOND = 6; 285 286 289 private static final int TIMEZONE = 7; 290 291 294 private static final int MIN_FIELD_VALUE[] = { 295 Integer.MIN_VALUE, DatatypeConstants.JANUARY, 298 1, 0, 0, 0, 0, -14 * 60 }; 305 306 309 private static final int MAX_FIELD_VALUE[] = { 310 Integer.MAX_VALUE, DatatypeConstants.DECEMBER, 313 31, 23, 59, 60, 999, 14 * 60 }; 320 321 324 private static final String FIELD_NAME[] = { 325 "Year", 326 "Month", 327 "Day", 328 "Hour", 329 "Minute", 330 "Second", 331 "Millisecond", 332 "Timezone" 333 }; 334 335 341 private static final long serialVersionUID = 1L; 342 343 355 public static final XMLGregorianCalendar LEAP_YEAR_DEFAULT = 356 createDateTime( 357 400, DatatypeConstants.JANUARY, 1, 0, 0, 0, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED ); 366 367 369 386 protected XMLGregorianCalendarImpl(String lexicalRepresentation) 387 throws IllegalArgumentException { 388 389 String format = null; 391 String lexRep = lexicalRepresentation; 392 final int NOT_FOUND = -1; 393 int lexRepLength = lexRep.length(); 394 395 396 if (lexRep.indexOf('T') != NOT_FOUND) { 400 format = "%Y-%M-%DT%h:%m:%s" + "%z"; 402 } else if (lexRepLength >= 3 && lexRep.charAt(2) == ':') { 403 format = "%h:%m:%s" +"%z"; 405 } else if (lexRep.startsWith("--")) { 406 if (lexRepLength >= 3 && lexRep.charAt(2) == '-') { 408 format = "---%D" + "%z"; 411 } else if (lexRepLength == 4 || (lexRepLength >= 6 && (lexRep.charAt(4) == '+' || (lexRep.charAt(4) == '-' && (lexRep.charAt(5) == '-' || lexRepLength == 10))))) { 412 format = "--%M--%z"; 415 Parser p = new Parser(format, lexRep); 416 try { 417 p.parse(); 418 if (!isValid()) { 420 throw new IllegalArgumentException ( 421 DatatypeMessageFormatter.formatMessage(null,"InvalidXGCRepresentation", new Object []{lexicalRepresentation}) 422 ); 424 } 425 save(); 426 return; 427 } 428 catch(IllegalArgumentException e) { 429 format = "--%M%z"; 430 } 431 } else { 432 format = "--%M-%D" + "%z"; 434 } 435 } else { 436 int countSeparator = 0; 438 439 441 442 int timezoneOffset = lexRep.indexOf(':'); 443 if (timezoneOffset != NOT_FOUND) { 444 445 lexRepLength -= 6; 450 } 451 452 for (int i=1; i < lexRepLength; i++) { 453 if (lexRep.charAt(i) == '-') { 454 countSeparator++; 455 } 456 } 457 if (countSeparator == 0) { 458 format = "%Y" + "%z"; 460 } else if (countSeparator == 1) { 461 format = "%Y-%M" + "%z"; 463 } else { 464 format = "%Y-%M-%D" + "%z"; 467 } 468 } 469 Parser p = new Parser(format, lexRep); 470 p.parse(); 471 472 if (!isValid()) { 474 throw new IllegalArgumentException ( 475 DatatypeMessageFormatter.formatMessage(null,"InvalidXGCRepresentation", new Object []{lexicalRepresentation}) 476 ); 478 } 479 save(); 480 } 481 482 485 private void save() { 486 orig_eon = eon; 487 orig_year = year; 488 orig_month = month; 489 orig_day = day; 490 orig_hour = hour; 491 orig_minute = minute; 492 orig_second = second; 493 orig_fracSeconds = fractionalSecond; 494 orig_timezone = timezone; 495 } 496 497 501 public XMLGregorianCalendarImpl() { 502 503 } 505 506 523 protected XMLGregorianCalendarImpl( 524 BigInteger year, 525 int month, 526 int day, 527 int hour, 528 int minute, 529 int second, 530 BigDecimal fractionalSecond, 531 int timezone) { 532 533 setYear(year); 534 setMonth(month); 535 setDay(day); 536 setTime(hour, minute, second, fractionalSecond); 537 setTimezone(timezone); 538 539 if (!isValid()) { 541 542 throw new IllegalArgumentException ( 543 DatatypeMessageFormatter.formatMessage(null, 544 "InvalidXGCValue-fractional", 545 new Object [] { year, new Integer (month), new Integer (day), 546 new Integer (hour), new Integer (minute), new Integer (second), 547 fractionalSecond, new Integer (timezone)}) 548 ); 549 550 572 573 } 574 575 save(); 576 577 } 578 579 596 private XMLGregorianCalendarImpl( 597 int year, 598 int month, 599 int day, 600 int hour, 601 int minute, 602 int second, 603 int millisecond, 604 int timezone) { 605 606 setYear(year); 607 setMonth(month); 608 setDay(day); 609 setTime(hour, minute, second); 610 setTimezone(timezone); 611 setMillisecond(millisecond); 612 613 if (!isValid()) { 614 615 throw new IllegalArgumentException ( 616 DatatypeMessageFormatter.formatMessage(null, 617 "InvalidXGCValue-milli", 618 new Object [] { new Integer (year), new Integer (month), new Integer (day), 619 new Integer (hour), new Integer (minute), new Integer (second), 620 new Integer (millisecond), new Integer (timezone)}) 621 ); 622 635 636 } 637 save(); 638 } 639 640 697 public XMLGregorianCalendarImpl(GregorianCalendar cal) { 698 699 int year = cal.get(Calendar.YEAR); 700 if (cal.get(Calendar.ERA) == GregorianCalendar.BC) { 701 year = -year; 702 } 703 this.setYear(year); 704 705 this.setMonth(cal.get(Calendar.MONTH) + 1); 708 this.setDay(cal.get(Calendar.DAY_OF_MONTH)); 709 this.setTime( 710 cal.get(Calendar.HOUR_OF_DAY), 711 cal.get(Calendar.MINUTE), 712 cal.get(Calendar.SECOND), 713 cal.get(Calendar.MILLISECOND)); 714 715 int offsetInMinutes = (cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET)) / (60 * 1000); 717 this.setTimezone(offsetInMinutes); 718 save(); 719 } 720 721 723 744 public static XMLGregorianCalendar createDateTime( 745 BigInteger year, 746 int month, 747 int day, 748 int hours, 749 int minutes, 750 int seconds, 751 BigDecimal fractionalSecond, 752 int timezone) { 753 754 return new XMLGregorianCalendarImpl( 755 year, 756 month, 757 day, 758 hours, 759 minutes, 760 seconds, 761 fractionalSecond, 762 timezone); 763 } 764 765 782 public static XMLGregorianCalendar createDateTime( 783 int year, 784 int month, 785 int day, 786 int hour, 787 int minute, 788 int second) { 789 790 return new XMLGregorianCalendarImpl( 791 year, 792 month, 793 day, 794 hour, 795 minute, 796 second, 797 DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED ); 800 } 801 802 822 public static XMLGregorianCalendar createDateTime( 823 int year, 824 int month, 825 int day, 826 int hours, 827 int minutes, 828 int seconds, 829 int milliseconds, 830 int timezone) { 831 832 return new XMLGregorianCalendarImpl( 833 year, 834 month, 835 day, 836 hours, 837 minutes, 838 seconds, 839 milliseconds, 840 timezone); 841 } 842 843 863 public static XMLGregorianCalendar createDate( 864 int year, 865 int month, 866 int day, 867 int timezone) { 868 869 return new XMLGregorianCalendarImpl( 870 year, 871 month, 872 day, 873 DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, timezone); 878 } 879 880 895 public static XMLGregorianCalendar createTime( 896 int hours, 897 int minutes, 898 int seconds, 899 int timezone) { 900 901 return new XMLGregorianCalendarImpl( 902 DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, hours, 906 minutes, 907 seconds, 908 DatatypeConstants.FIELD_UNDEFINED, timezone); 910 } 911 912 929 public static XMLGregorianCalendar createTime( 930 int hours, 931 int minutes, 932 int seconds, 933 BigDecimal fractionalSecond, 934 int timezone) { 935 936 return new XMLGregorianCalendarImpl( 937 null, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, hours, 941 minutes, 942 seconds, 943 fractionalSecond, 944 timezone); 945 } 946 947 964 public static XMLGregorianCalendar createTime( 965 int hours, 966 int minutes, 967 int seconds, 968 int milliseconds, 969 int timezone) { 970 971 return new XMLGregorianCalendarImpl( 972 DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, DatatypeConstants.FIELD_UNDEFINED, hours, 976 minutes, 977 seconds, 978 milliseconds, 979 timezone); 980 } 981 982 984 997 public BigInteger getEon() { 998 return eon; 999 } 1000 1001 1013 public int getYear() { 1014 return year; 1015 } 1016 1017 1032 public BigInteger getEonAndYear() { 1033 1034 if (year != DatatypeConstants.FIELD_UNDEFINED 1036 && eon != null) { 1037 1038 return eon.add(BigInteger.valueOf((long) year)); 1039 } 1040 1041 if (year != DatatypeConstants.FIELD_UNDEFINED 1043 && eon == null) { 1044 1045 return BigInteger.valueOf((long) year); 1046 } 1047 1048 return null; 1051 } 1052 1053 1062 public int getMonth() { 1063 return month; 1064 } 1065 1066 1074 public int getDay() { 1075 return day; 1076 } 1077 1078 1087 public int getTimezone() { 1088 return timezone; 1089 } 1090 1091 1099 public int getHour() { 1100 return hour; 1101 } 1102 1103 1111 public int getMinute() { 1112 return minute; 1113 } 1114 1115 1133 public int getSecond() { 1134 return second; 1135 } 1136 1137 1140 private BigDecimal getSeconds() { 1141 1142 if (second == DatatypeConstants.FIELD_UNDEFINED) { 1143 return DECIMAL_ZERO; 1144 } 1145 BigDecimal result = BigDecimal.valueOf((long)second); 1146 if (fractionalSecond != null){ 1147 return result.add(fractionalSecond); 1148 } else { 1149 return result; 1150 } 1151 } 1152 1153 1154 1173 public int getMillisecond() { 1174 if (fractionalSecond == null) { 1175 return DatatypeConstants.FIELD_UNDEFINED; 1176 } else { 1177 return fractionalSecond.movePointRight(3).intValue(); 1181 } 1182 } 1183 1184 1201 public BigDecimal getFractionalSecond() { 1202 return fractionalSecond; 1203 } 1204 1205 1207 1218 public void setYear(BigInteger year) { 1219 if (year == null) { 1220 this.eon = null; 1221 this.year = DatatypeConstants.FIELD_UNDEFINED; 1222 } else { 1223 BigInteger temp = year.remainder(BILLION); 1224 this.year = temp.intValue(); 1225 setEon(year.subtract(temp)); 1226 } 1227 } 1228 1229 1242 public void setYear(int year) { 1243 if (year == DatatypeConstants.FIELD_UNDEFINED) { 1244 this.year = DatatypeConstants.FIELD_UNDEFINED; 1245 this.eon = null; 1246 } else if (Math.abs(year) < BILLION.intValue()) { 1247 this.year = year; 1248 this.eon = null; 1249 } else { 1250 BigInteger theYear = BigInteger.valueOf((long) year); 1251 BigInteger remainder = theYear.remainder(BILLION); 1252 this.year = remainder.intValue(); 1253 setEon(theYear.subtract(remainder)); 1254 } 1255 } 1256 1257 1265 private void setEon(BigInteger eon) { 1266 if (eon != null && eon.compareTo(BigInteger.ZERO) == 0) { 1267 this.eon = null; 1269 } else { 1270 this.eon = eon; 1271 } 1272 } 1273 1274 1285 public void setMonth(int month) { 1286 checkFieldValueConstraint(MONTH, month); 1287 this.month = month; 1288 } 1289 1290 1301 public void setDay(int day) { 1302 checkFieldValueConstraint(DAY, day); 1303 this.day = day; 1304 } 1305 1306 1318 public void setTimezone(int offset) { 1319 checkFieldValueConstraint(TIMEZONE, offset); 1320 this.timezone = offset; 1321 } 1322 1323 1339 public void setTime(int hour, int minute, int second) { 1340 setTime(hour, minute, second, null); 1341 } 1342 1343 private void checkFieldValueConstraint(int field, int value) 1344 throws IllegalArgumentException 1345 { 1346 if ((value < MIN_FIELD_VALUE[field] && value != DatatypeConstants.FIELD_UNDEFINED) || 1347 value > MAX_FIELD_VALUE[field]) { 1348 1353 throw new IllegalArgumentException ( 1354 DatatypeMessageFormatter.formatMessage(null, "InvalidFieldValue", new Object []{ new Integer (value), FIELD_NAME[field]}) 1355 ); 1356 } 1357 } 1358 1359 public void setHour(int hour) { 1360 checkFieldValueConstraint(HOUR, hour); 1361 this.hour = hour; 1362 } 1363 1364 public void setMinute(int minute) { 1365 checkFieldValueConstraint(MINUTE, minute); 1366 this.minute = minute; 1367 } 1368 1369 public void setSecond(int second) { 1370 checkFieldValueConstraint(SECOND, second); 1371 this.second = second; 1372 } 1373 1374 1391 public void setTime( 1392 int hour, 1393 int minute, 1394 int second, 1395 BigDecimal fractional) { 1396 setHour(hour); 1397 setMinute(minute); 1398 setSecond(second); 1399 setFractionalSecond(fractional); 1400 } 1401 1402 1403 1419 public void setTime(int hour, int minute, int second, int millisecond) { 1420 setHour(hour); 1421 setMinute(minute); 1422 setSecond(second); 1423 setMillisecond(millisecond); 1424 } 1425 1426 1448 public int compare(XMLGregorianCalendar rhs) { 1449 1450 1452 int result = DatatypeConstants.INDETERMINATE; 1453 XMLGregorianCalendar P = this; 1454 XMLGregorianCalendar Q = rhs; 1455 1456 if (P.getTimezone() == Q.getTimezone()) { 1457 return internalCompare(P, Q); 1462 1463 } else if (P.getTimezone() != DatatypeConstants.FIELD_UNDEFINED && 1464 Q.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) { 1465 1466 P = (XMLGregorianCalendarImpl) P.normalize(); 1469 Q = (XMLGregorianCalendarImpl) Q.normalize(); 1470 return internalCompare(P, Q); 1471 } else if (P.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) { 1472 1473 if (P.getTimezone() != 0) { 1474 P = (XMLGregorianCalendarImpl) P.normalize(); 1475 } 1476 1477 XMLGregorianCalendar MinQ = normalizeToTimezone(Q, DatatypeConstants.MIN_TIMEZONE_OFFSET); 1479 result = internalCompare(P, MinQ); 1480 if (result == DatatypeConstants.LESSER) { 1481 return result; 1482 } 1483 1484 XMLGregorianCalendar MaxQ = normalizeToTimezone(Q, DatatypeConstants.MAX_TIMEZONE_OFFSET); 1486 result = internalCompare(P, MaxQ); 1487 if (result == DatatypeConstants.GREATER) { 1488 return result; 1489 } else { 1490 return DatatypeConstants.INDETERMINATE; 1492 } 1493 } else { if (Q.getTimezone() != 0 ) { 1496 Q = (XMLGregorianCalendarImpl) normalizeToTimezone(Q, Q.getTimezone()); 1497 } 1498 1499 XMLGregorianCalendar MaxP = normalizeToTimezone(P, DatatypeConstants.MAX_TIMEZONE_OFFSET); 1501 result = internalCompare(MaxP, Q); 1502 if (result == DatatypeConstants.LESSER) { 1503 return result; 1504 } 1505 1506 XMLGregorianCalendar MinP = normalizeToTimezone(P, DatatypeConstants.MIN_TIMEZONE_OFFSET); 1508 result = internalCompare(MinP, Q); 1509 if (result == DatatypeConstants.GREATER) { 1510 return result; 1511 } else { 1512 return DatatypeConstants.INDETERMINATE; 1514 } 1515 } 1516 } 1517 1518 1524 public XMLGregorianCalendar normalize() { 1525 1526 XMLGregorianCalendar normalized = normalizeToTimezone(this, timezone); 1527 1528 if (getTimezone() == DatatypeConstants.FIELD_UNDEFINED) { 1530 normalized.setTimezone(DatatypeConstants.FIELD_UNDEFINED); 1531 } 1532 1533 if (getMillisecond() == DatatypeConstants.FIELD_UNDEFINED) { 1535 normalized.setMillisecond(DatatypeConstants.FIELD_UNDEFINED); 1536 } 1537 1538 return normalized; 1539 } 1540 1541 1547 private XMLGregorianCalendar normalizeToTimezone(XMLGregorianCalendar cal, int timezone) { 1548 1549 int minutes = timezone; 1550 XMLGregorianCalendar result = (XMLGregorianCalendar ) cal.clone(); 1551 1552 minutes = -minutes; 1555 Duration d = new DurationImpl(minutes >= 0, 0, 0, 0, 0, minutes < 0 ? -minutes : minutes, 0 ); 1563 result.add(d); 1564 1565 result.setTimezone(0); 1567 return result; 1568 } 1569 1570 1584 private static int internalCompare(XMLGregorianCalendar P, 1585 XMLGregorianCalendar Q) { 1586 1587 int result; 1588 1589 if (P.getEon() == Q.getEon()) { 1591 1592 result = compareField(P.getYear(), Q.getYear()); 1595 if (result != DatatypeConstants.EQUAL) { 1596 return result; 1597 } 1598 } else { 1599 result = compareField(P.getEonAndYear(), Q.getEonAndYear()); 1600 if (result != DatatypeConstants.EQUAL) { 1601 return result; 1602 } 1603 } 1604 1605 result = compareField(P.getMonth(), Q.getMonth()); 1606 if (result != DatatypeConstants.EQUAL) { 1607 return result; 1608 } 1609 1610 result = compareField(P.getDay(), Q.getDay()); 1611 if (result != DatatypeConstants.EQUAL) { 1612 return result; 1613 } 1614 1615 result = compareField(P.getHour(), Q.getHour()); 1616 if (result != DatatypeConstants.EQUAL) { 1617 return result; 1618 } 1619 1620 result = compareField(P.getMinute(), Q.getMinute()); 1621 if (result != DatatypeConstants.EQUAL) { 1622 return result; 1623 } 1624 result = compareField(P.getSecond(), Q.getSecond()); 1625 if (result != DatatypeConstants.EQUAL) { 1626 return result; 1627 } 1628 1629 result = compareField(P.getFractionalSecond(), Q.getFractionalSecond()); 1630 return result; 1631 } 1632 1633 1637 private static int compareField(int Pfield, int Qfield) { 1638 if (Pfield == Qfield) { 1639 1640 return DatatypeConstants.EQUAL; 1643 } else { 1644 if (Pfield == DatatypeConstants.FIELD_UNDEFINED || Qfield == DatatypeConstants.FIELD_UNDEFINED) { 1645 return DatatypeConstants.INDETERMINATE; 1647 } else { 1648 return (Pfield < Qfield ? DatatypeConstants.LESSER : DatatypeConstants.GREATER); 1650 } 1651 } 1652 } 1653 1654 private static int compareField(BigInteger Pfield, BigInteger Qfield) { 1655 if (Pfield == null) { 1656 return (Qfield == null ? DatatypeConstants.EQUAL : DatatypeConstants.INDETERMINATE); 1657 } 1658 if (Qfield == null) { 1659 return DatatypeConstants.INDETERMINATE; 1660 } 1661 return Pfield.compareTo(Qfield); 1662 } 1663 1664 private static int compareField(BigDecimal Pfield, BigDecimal Qfield) { 1665 if (Pfield == Qfield) { 1667 return DatatypeConstants.EQUAL; 1668 } 1669 1670 if (Pfield == null) { 1671 Pfield = DECIMAL_ZERO; 1672 } 1673 1674 if (Qfield == null) { 1675 Qfield = DECIMAL_ZERO; 1676 } 1677 1678 return Pfield.compareTo(Qfield); 1679 } 1680 1681 1688 public boolean equals(Object obj) { 1689 boolean result = false; 1690 if (obj instanceof XMLGregorianCalendar ) { 1691 result = compare((XMLGregorianCalendar ) obj) == DatatypeConstants.EQUAL; 1692 } 1693 return result; 1694 } 1695 1696 1701 public int hashCode() { 1702 1703 int timezone = getTimezone(); 1709 if (timezone == DatatypeConstants.FIELD_UNDEFINED){ 1710 timezone = 0; 1711 } 1712 XMLGregorianCalendar gc = this; 1713 if (timezone != 0) { 1714 gc = normalizeToTimezone(this, getTimezone()); 1715 } 1716 return gc.getYear() + gc.getMonth() + gc.getDay() + 1717 gc.getHour() + gc.getMinute() + gc.getSecond(); 1718 } 1719 1720 1721 1751 public static XMLGregorianCalendar parse(String lexicalRepresentation) { 1752 1753 return new XMLGregorianCalendarImpl(lexicalRepresentation); 1754 } 1755 1756 1770 public String toXMLFormat() { 1771 1772 QName typekind = getXMLSchemaType(); 1773 1774 String formatString = null; 1775 if (typekind == DatatypeConstants.DATETIME) { 1776 formatString = "%Y-%M-%DT%h:%m:%s"+ "%z"; 1777 } else if (typekind == DatatypeConstants.DATE) { 1778 formatString = "%Y-%M-%D" +"%z"; 1780 } else if (typekind == DatatypeConstants.TIME) { 1781 formatString = "%h:%m:%s"+ "%z"; 1782 } else if (typekind == DatatypeConstants.GMONTH) { 1783 formatString = "--%M--%z"; 1784 } else if (typekind == DatatypeConstants.GDAY) { 1785 formatString = "---%D" + "%z"; 1787 } else if (typekind == DatatypeConstants.GYEAR) { 1788 formatString = "%Y" + "%z"; 1789 } else if (typekind == DatatypeConstants.GYEARMONTH) { 1790 formatString = "%Y-%M" + "%z"; 1792 } else if (typekind == DatatypeConstants.GMONTHDAY) { 1793 formatString = "--%M-%D" +"%z"; 1795 } 1796 return format(formatString); 1797 } 1798 1799 1910 public QName getXMLSchemaType() { 1911 1912 if (year != DatatypeConstants.FIELD_UNDEFINED 1914 && month != DatatypeConstants.FIELD_UNDEFINED 1915 && day != DatatypeConstants.FIELD_UNDEFINED 1916 && hour != DatatypeConstants.FIELD_UNDEFINED 1917 && minute != DatatypeConstants.FIELD_UNDEFINED 1918 && second != DatatypeConstants.FIELD_UNDEFINED) { 1919 return DatatypeConstants.DATETIME; 1920 } 1921 1922 if (year != DatatypeConstants.FIELD_UNDEFINED 1924 && month != DatatypeConstants.FIELD_UNDEFINED 1925 && day != DatatypeConstants.FIELD_UNDEFINED 1926 && hour == DatatypeConstants.FIELD_UNDEFINED 1927 && minute == DatatypeConstants.FIELD_UNDEFINED 1928 && second == DatatypeConstants.FIELD_UNDEFINED) { 1929 return DatatypeConstants.DATE; 1930 } 1931 1932 if (year == DatatypeConstants.FIELD_UNDEFINED 1934 && month == DatatypeConstants.FIELD_UNDEFINED 1935 && day == DatatypeConstants.FIELD_UNDEFINED 1936 && hour != DatatypeConstants.FIELD_UNDEFINED 1937 && minute != DatatypeConstants.FIELD_UNDEFINED 1938 && second != DatatypeConstants.FIELD_UNDEFINED) { 1939 return DatatypeConstants.TIME; 1940 } 1941 1942 1943 if (year != DatatypeConstants.FIELD_UNDEFINED 1945 && month != DatatypeConstants.FIELD_UNDEFINED 1946 && day == DatatypeConstants.FIELD_UNDEFINED 1947 && hour == DatatypeConstants.FIELD_UNDEFINED 1948 && minute == DatatypeConstants.FIELD_UNDEFINED 1949 && second == DatatypeConstants.FIELD_UNDEFINED) { 1950 return DatatypeConstants.GYEARMONTH; 1951 } 1952 1953 if (year == DatatypeConstants.FIELD_UNDEFINED 1955 && month != DatatypeConstants.FIELD_UNDEFINED 1956 && day != DatatypeConstants.FIELD_UNDEFINED 1957 && hour == DatatypeConstants.FIELD_UNDEFINED 1958 && minute == DatatypeConstants.FIELD_UNDEFINED 1959 && second == DatatypeConstants.FIELD_UNDEFINED) { 1960 return DatatypeConstants.GMONTHDAY; 1961 } 1962 1963 if (year != DatatypeConstants.FIELD_UNDEFINED 1965 && month == DatatypeConstants.FIELD_UNDEFINED 1966 && day == DatatypeConstants.FIELD_UNDEFINED 1967 && hour == DatatypeConstants.FIELD_UNDEFINED 1968 && minute == DatatypeConstants.FIELD_UNDEFINED 1969 && second == DatatypeConstants.FIELD_UNDEFINED) { 1970 return DatatypeConstants.GYEAR; 1971 } 1972 1973 if (year == DatatypeConstants.FIELD_UNDEFINED 1975 && month != DatatypeConstants.FIELD_UNDEFINED 1976 && day == DatatypeConstants.FIELD_UNDEFINED 1977 && hour == DatatypeConstants.FIELD_UNDEFINED 1978 && minute == DatatypeConstants.FIELD_UNDEFINED 1979 && second == DatatypeConstants.FIELD_UNDEFINED) { 1980 return DatatypeConstants.GMONTH; 1981 } 1982 1983 if (year == DatatypeConstants.FIELD_UNDEFINED 1985 && month == DatatypeConstants.FIELD_UNDEFINED 1986 && day != DatatypeConstants.FIELD_UNDEFINED 1987 && hour == DatatypeConstants.FIELD_UNDEFINED 1988 && minute == DatatypeConstants.FIELD_UNDEFINED 1989 && second == DatatypeConstants.FIELD_UNDEFINED) { 1990 return DatatypeConstants.GDAY; 1991 } 1992 1993 throw new IllegalStateException ( 1995 this.getClass().getName() 1996 + "#getXMLSchemaType() :" 1997 + DatatypeMessageFormatter.formatMessage(null, "InvalidXGCFields", null) 1998 ); 1999 } 2000 2001 2002 2006 public boolean isValid() { 2007 2012 if (getMonth() == DatatypeConstants.FEBRUARY) { 2014 int maxDays = DatatypeConstants.FIELD_UNDEFINED; 2016 BigInteger years = getEonAndYear(); 2017 if (years != null) { 2018 maxDays = maximumDayInMonthFor(getEonAndYear(), DatatypeConstants.FEBRUARY); 2019 } else { 2020 maxDays = 29; 2022 } 2023 if (getDay() > maxDays) { 2024 return false; 2025 } 2026 } 2027 2028 if (getHour() == 24) { 2030 if(getMinute() != 0) { 2031 return false; 2032 } else if (getSecond() != 0) { 2033 return false; 2034 } 2035 } 2036 2037 if (eon == null) { 2042 if (year == 0) { 2044 return false; 2045 } 2046 } else { 2047 BigInteger yearField = getEonAndYear(); 2048 if (yearField != null) { 2049 int result = compareField(yearField, BigInteger.ZERO); 2050 if (result == DatatypeConstants.EQUAL) { 2051 return false; 2052 } 2053 } 2054 } 2055 return true; 2056 } 2057 2058 2072 public void add(Duration duration) { 2073 2074 2097 2098 boolean fieldUndefined[] = { 2099 false, 2100 false, 2101 false, 2102 false, 2103 false, 2104 false 2105 }; 2106 2107 int signum = duration.getSign(); 2108 2109 int startMonth = getMonth(); 2110 if (startMonth == DatatypeConstants.FIELD_UNDEFINED) { 2111 startMonth = MIN_FIELD_VALUE[MONTH]; 2112 fieldUndefined[MONTH] = true; 2113 } 2114 2115 BigInteger dMonths = sanitize(duration.getField(DatatypeConstants.MONTHS), signum); 2116 BigInteger temp = BigInteger.valueOf((long) startMonth).add(dMonths); 2117 setMonth(temp.subtract(BigInteger.ONE).mod(TWELVE).intValue() + 1); 2118 BigInteger carry = 2119 new BigDecimal (temp.subtract(BigInteger.ONE)).divide(new BigDecimal (TWELVE), BigDecimal.ROUND_FLOOR).toBigInteger(); 2120 2121 2124 BigInteger startYear = getEonAndYear(); 2125 if (startYear == null) { 2126 fieldUndefined[YEAR] = true; 2127 startYear = BigInteger.ZERO; 2128 } 2129 BigInteger dYears = sanitize(duration.getField(DatatypeConstants.YEARS), signum); 2130 BigInteger endYear = startYear.add(dYears).add(carry); 2131 setYear(endYear); 2132 2133 2138 2139 2144 BigDecimal startSeconds; 2145 if (getSecond() == DatatypeConstants.FIELD_UNDEFINED) { 2146 fieldUndefined[SECOND] = true; 2147 startSeconds = DECIMAL_ZERO; 2148 } else { 2149 startSeconds = getSeconds(); 2151 } 2152 2153 BigDecimal dSeconds = DurationImpl.sanitize((BigDecimal ) duration.getField(DatatypeConstants.SECONDS), signum); 2155 BigDecimal tempBD = startSeconds.add(dSeconds); 2156 BigDecimal fQuotient = 2157 new BigDecimal (new BigDecimal (tempBD.toBigInteger()).divide(DECIMAL_SIXTY, BigDecimal.ROUND_FLOOR).toBigInteger()); 2158 BigDecimal endSeconds = tempBD.subtract(fQuotient.multiply(DECIMAL_SIXTY)); 2159 2160 carry = fQuotient.toBigInteger(); 2161 setSecond(endSeconds.intValue()); 2162 BigDecimal tempFracSeconds = endSeconds.subtract(new BigDecimal (BigInteger.valueOf((long) getSecond()))); 2163 if (tempFracSeconds.compareTo(DECIMAL_ZERO) < 0) { 2164 setFractionalSecond(DECIMAL_ONE.add(tempFracSeconds)); 2165 if (getSecond() == 0) { 2166 setSecond(59); 2167 carry = carry.subtract(BigInteger.ONE); 2168 } else { 2169 setSecond(getSecond() - 1); 2170 } 2171 } else { 2172 setFractionalSecond(tempFracSeconds); 2173 } 2174 2175 2180 int startMinutes = getMinute(); 2181 if (startMinutes == DatatypeConstants.FIELD_UNDEFINED) { 2182 fieldUndefined[MINUTE] = true; 2183 startMinutes = MIN_FIELD_VALUE[MINUTE]; 2184 } 2185 BigInteger dMinutes = sanitize(duration.getField(DatatypeConstants.MINUTES), signum); 2186 2187 temp = BigInteger.valueOf(startMinutes).add(dMinutes).add(carry); 2188 setMinute(temp.mod(SIXTY).intValue()); 2189 carry = new BigDecimal (temp).divide(DECIMAL_SIXTY, BigDecimal.ROUND_FLOOR).toBigInteger(); 2190 2191 2196 int startHours = getHour(); 2197 if (startHours == DatatypeConstants.FIELD_UNDEFINED) { 2198 fieldUndefined[HOUR] = true; 2199 startHours = MIN_FIELD_VALUE[HOUR]; 2200 } 2201 BigInteger dHours = sanitize(duration.getField(DatatypeConstants.HOURS), signum); 2202 2203 temp = BigInteger.valueOf(startHours).add(dHours).add(carry); 2204 setHour(temp.mod(TWENTY_FOUR).intValue()); 2205 carry = new BigDecimal (temp).divide(new BigDecimal (TWENTY_FOUR), BigDecimal.ROUND_FLOOR).toBigInteger(); 2206 2207 2230 BigInteger tempDays; 2231 int startDay = getDay(); 2232 if (startDay == DatatypeConstants.FIELD_UNDEFINED) { 2233 fieldUndefined[DAY] = true; 2234 startDay = MIN_FIELD_VALUE[DAY]; 2235 } 2236 BigInteger dDays = sanitize(duration.getField(DatatypeConstants.DAYS), signum); 2237 int maxDayInMonth = maximumDayInMonthFor(getEonAndYear(), getMonth()); 2238 if (startDay > maxDayInMonth) { 2239 tempDays = BigInteger.valueOf(maxDayInMonth); 2240 } else if (startDay < 1) { 2241 tempDays = BigInteger.ONE; 2242 } else { 2243 tempDays = BigInteger.valueOf(startDay); 2244 } 2245 BigInteger endDays = tempDays.add(dDays).add(carry); 2246 int monthCarry; 2247 int intTemp; 2248 while (true) { 2249 if (endDays.compareTo(BigInteger.ONE) < 0) { 2250 BigInteger mdimf = null; 2252 if (month >= 2) { 2253 mdimf = BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear(), getMonth() - 1)); 2254 } else { 2255 mdimf = BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear().subtract(BigInteger.valueOf((long) 1)), 12)); 2257 } 2258 endDays = endDays.add(mdimf); 2259 monthCarry = -1; 2260 } else if (endDays.compareTo(BigInteger.valueOf(maximumDayInMonthFor(getEonAndYear(), getMonth()))) > 0) { 2261 endDays = endDays.add(BigInteger.valueOf(-maximumDayInMonthFor(getEonAndYear(), getMonth()))); 2262 monthCarry = 1; 2263 } else { 2264 break; 2265 } 2266 2267 intTemp = getMonth() + monthCarry; 2268 int endMonth = (intTemp - 1) % (13 - 1); 2269 int quotient; 2270 if (endMonth < 0) { 2271 endMonth = (13 - 1) + endMonth + 1; 2272 quotient = new BigDecimal (intTemp - 1).divide(new BigDecimal (TWELVE), BigDecimal.ROUND_UP).intValue(); 2273 } else { 2274 quotient = (intTemp - 1) / (13 - 1); 2275 endMonth += 1; 2276 } 2277 setMonth(endMonth); 2278 if (quotient != 0) { 2279 setYear(getEonAndYear().add(BigInteger.valueOf(quotient))); 2280 } 2281 } 2282 setDay(endDays.intValue()); 2283 2284 for (int i = YEAR; i <= SECOND; i++) { 2286 if (fieldUndefined[i]) { 2287 switch (i) { 2288 case YEAR: 2289 setYear(DatatypeConstants.FIELD_UNDEFINED); 2290 break; 2291 case MONTH: 2292 setMonth(DatatypeConstants.FIELD_UNDEFINED); 2293 break; 2294 case DAY: 2295 setDay(DatatypeConstants.FIELD_UNDEFINED); 2296 break; 2297 case HOUR: 2298 setHour(DatatypeConstants.FIELD_UNDEFINED); 2299 break; 2300 case MINUTE: 2301 setMinute(DatatypeConstants.FIELD_UNDEFINED); 2302 break; 2303 case SECOND: 2304 setSecond(DatatypeConstants.FIELD_UNDEFINED); 2305 setFractionalSecond(null); 2306 break; 2307 } 2308 } 2309 } 2310 } 2311 2312 private static final BigInteger FOUR = BigInteger.valueOf(4); 2313 private static final BigInteger HUNDRED = BigInteger.valueOf(100); 2314 private static final BigInteger FOUR_HUNDRED = BigInteger.valueOf(400); 2315 private static final BigInteger SIXTY = BigInteger.valueOf(60); 2316 private static final BigInteger TWENTY_FOUR = BigInteger.valueOf(24); 2317 private static final BigInteger TWELVE = BigInteger.valueOf(12); 2318 private static final BigDecimal DECIMAL_ZERO = new BigDecimal ("0"); 2319 private static final BigDecimal DECIMAL_ONE = new BigDecimal ("1"); 2320 private static final BigDecimal DECIMAL_SIXTY = new BigDecimal ("60"); 2321 2322 2323 private static int daysInMonth[] = { 0, 31, 28, 31, 30, 31, 30, 2325 31, 31, 30, 31, 30, 31}; 2326 2327 private static int maximumDayInMonthFor(BigInteger year, int month) { 2328 if (month != DatatypeConstants.FEBRUARY) { 2329 return daysInMonth[month]; 2330 } else { 2331 if (year.mod(FOUR_HUNDRED).equals(BigInteger.ZERO) || 2332 (!year.mod(HUNDRED).equals(BigInteger.ZERO) && 2333 year.mod(FOUR).equals(BigInteger.ZERO))) { 2334 return 29; 2336 } else { 2337 return daysInMonth[month]; 2338 } 2339 } 2340 } 2341 2342 private static int maximumDayInMonthFor(int year, int month) { 2343 if (month != DatatypeConstants.FEBRUARY) { 2344 return daysInMonth[month]; 2345 } else { 2346 if ( ((year %400) == 0) || 2347 ( ((year % 100) != 0) && ((year % 4) == 0))) { 2348 return 29; 2350 } else { 2351 return daysInMonth[DatatypeConstants.FEBRUARY]; 2352 } 2353 } 2354 } 2355 2356 2448 public java.util.GregorianCalendar toGregorianCalendar() { 2449 2450 GregorianCalendar result = null; 2451 final int DEFAULT_TIMEZONE_OFFSET = DatatypeConstants.FIELD_UNDEFINED; 2452 TimeZone tz = getTimeZone(DEFAULT_TIMEZONE_OFFSET); 2453 Locale locale = java.util.Locale.getDefault(); 2454 2455 result = new GregorianCalendar (tz, locale); 2456 result.clear(); 2457 result.setGregorianChange(PURE_GREGORIAN_CHANGE); 2458 2459 BigInteger year = getEonAndYear(); 2461 if (year != null) { 2462 result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); 2463 result.set(Calendar.YEAR, year.abs().intValue()); 2464 } 2465 2466 if (month != DatatypeConstants.FIELD_UNDEFINED) { 2468 result.set(Calendar.MONTH, month - 1); 2470 } 2471 2472 if (day != DatatypeConstants.FIELD_UNDEFINED) { 2474 result.set(Calendar.DAY_OF_MONTH, day); 2475 } 2476 2477 if (hour != DatatypeConstants.FIELD_UNDEFINED) { 2479 result.set(Calendar.HOUR_OF_DAY, hour); 2480 } 2481 2482 if (minute != DatatypeConstants.FIELD_UNDEFINED) { 2484 result.set(Calendar.MINUTE, minute); 2485 } 2486 2487 if (second != DatatypeConstants.FIELD_UNDEFINED) { 2489 result.set(Calendar.SECOND, second); 2490 } 2491 2492 if (fractionalSecond != null) { 2494 result.set(Calendar.MILLISECOND, getMillisecond()); 2495 } 2496 2497 return result; 2498 } 2499 2500 2552 public GregorianCalendar toGregorianCalendar(java.util.TimeZone timezone, 2553 java.util.Locale aLocale, 2554 XMLGregorianCalendar defaults) { 2555 GregorianCalendar result = null; 2556 TimeZone tz = timezone; 2557 if (tz == null) { 2558 int defaultZoneoffset = DatatypeConstants.FIELD_UNDEFINED; 2559 if (defaults != null) { 2560 defaultZoneoffset = defaults.getTimezone(); 2561 } 2562 tz = getTimeZone(defaultZoneoffset); 2563 } 2564 if (aLocale == null) { 2565 aLocale = java.util.Locale.getDefault(); 2566 } 2567 result = new GregorianCalendar (tz, aLocale); 2568 result.clear(); 2569 result.setGregorianChange(PURE_GREGORIAN_CHANGE); 2570 2571 BigInteger year = getEonAndYear(); 2573 if (year != null) { 2574 result.set(Calendar.ERA, year.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); 2575 result.set(Calendar.YEAR, year.abs().intValue()); 2576 } else { 2577 BigInteger defaultYear = (defaults != null) ? defaults.getEonAndYear() : null; 2579 if (defaultYear != null) { 2580 result.set(Calendar.ERA, defaultYear.signum() == -1 ? GregorianCalendar.BC : GregorianCalendar.AD); 2581 result.set(Calendar.YEAR, defaultYear.abs().intValue()); 2582 } 2583 } 2584 2585 if (month != DatatypeConstants.FIELD_UNDEFINED) { 2587 result.set(Calendar.MONTH, month - 1); 2589 } else { 2590 int defaultMonth = (defaults != null) ? defaults.getMonth() : DatatypeConstants.FIELD_UNDEFINED; 2592 if (defaultMonth != DatatypeConstants.FIELD_UNDEFINED) { 2593 result.set(Calendar.MONTH, defaultMonth - 1); 2595 } 2596 } 2597 2598 if (day != DatatypeConstants.FIELD_UNDEFINED) { 2600 result.set(Calendar.DAY_OF_MONTH, day); 2601 } else { 2602 int defaultDay = (defaults != null) ? defaults.getDay() : DatatypeConstants.FIELD_UNDEFINED; 2604 if (defaultDay != DatatypeConstants.FIELD_UNDEFINED) { 2605 result.set(Calendar.DAY_OF_MONTH, defaultDay); 2606 } 2607 } 2608 2609 if (hour != DatatypeConstants.FIELD_UNDEFINED) { 2611 result.set(Calendar.HOUR_OF_DAY, hour); 2612 } else { 2613 int defaultHour = (defaults != null) ? defaults.getHour() : DatatypeConstants.FIELD_UNDEFINED; 2615 if (defaultHour != DatatypeConstants.FIELD_UNDEFINED) { 2616 result.set(Calendar.HOUR_OF_DAY, defaultHour); 2617 } 2618 } 2619 2620 if (minute != DatatypeConstants.FIELD_UNDEFINED) { 2622 result.set(Calendar.MINUTE, minute); 2623 } else { 2624 int defaultMinute = (defaults != null) ? defaults.getMinute() : DatatypeConstants.FIELD_UNDEFINED; 2626 if (defaultMinute != DatatypeConstants.FIELD_UNDEFINED) { 2627 result.set(Calendar.MINUTE, defaultMinute); 2628 } 2629 } 2630 2631 if (second != DatatypeConstants.FIELD_UNDEFINED) { 2633 result.set(Calendar.SECOND, second); 2634 } else { 2635 int defaultSecond = (defaults != null) ? defaults.getSecond() : DatatypeConstants.FIELD_UNDEFINED; 2637 if (defaultSecond != DatatypeConstants.FIELD_UNDEFINED) { 2638 result.set(Calendar.SECOND, defaultSecond); 2639 } 2640 } 2641 2642 if (fractionalSecond != null) { 2644 result.set(Calendar.MILLISECOND, getMillisecond()); 2645 } else { 2646 BigDecimal defaultFractionalSecond = (defaults != null) ? defaults.getFractionalSecond() : null; 2648 if (defaultFractionalSecond != null) { 2649 result.set(Calendar.MILLISECOND, defaults.getMillisecond()); 2650 } 2651 } 2652 2653 return result; 2654 } 2655 2656 2672 public TimeZone getTimeZone(int defaultZoneoffset) { 2673 TimeZone result = null; 2674 int zoneoffset = getTimezone(); 2675 2676 if (zoneoffset == DatatypeConstants.FIELD_UNDEFINED) { 2677 zoneoffset = defaultZoneoffset; 2678 } 2679 if (zoneoffset == DatatypeConstants.FIELD_UNDEFINED) { 2680 result = TimeZone.getDefault(); 2681 } else { 2682 char sign = zoneoffset < 0 ? '-' : '+'; 2684 if (sign == '-') { 2685 zoneoffset = -zoneoffset; 2686 } 2687 int hour = zoneoffset / 60; 2688 int minutes = zoneoffset - (hour * 60); 2689 2690 StringBuffer customTimezoneId = new StringBuffer (8); 2696 customTimezoneId.append("GMT"); 2697 customTimezoneId.append(sign); 2698 customTimezoneId.append(hour); 2699 if (minutes != 0) { 2700 customTimezoneId.append(minutes); 2701 } 2702 result = TimeZone.getTimeZone(customTimezoneId.toString()); 2703 } 2704 return result; 2705 } 2706 2707 2712 public Object clone() { 2713 return new XMLGregorianCalendarImpl(getEonAndYear(), 2716 this.month, this.day, 2717 this.hour, this.minute, this.second, 2718 this.fractionalSecond, 2719 this.timezone); 2720 } 2721 2722 2728 public void clear() { 2729 eon = null; 2730 year = DatatypeConstants.FIELD_UNDEFINED; 2731 month = DatatypeConstants.FIELD_UNDEFINED; 2732 day = DatatypeConstants.FIELD_UNDEFINED; 2733 timezone = DatatypeConstants.FIELD_UNDEFINED; hour = DatatypeConstants.FIELD_UNDEFINED; 2735 minute = DatatypeConstants.FIELD_UNDEFINED; 2736 second = DatatypeConstants.FIELD_UNDEFINED; 2737 fractionalSecond = null; 2738 } 2739 2740 public void setMillisecond(int millisecond) { 2741 if (millisecond == DatatypeConstants.FIELD_UNDEFINED) { 2742 fractionalSecond = null; 2743 } else { 2744 checkFieldValueConstraint(MILLISECOND, millisecond); 2745 fractionalSecond = new BigDecimal ((long) millisecond).movePointLeft(3); 2746 } 2747 } 2748 2749 public void setFractionalSecond(BigDecimal fractional) { 2750 if (fractional != null) { 2751 if ((fractional.compareTo(DECIMAL_ZERO) < 0) || 2752 (fractional.compareTo(DECIMAL_ONE) > 0)) { 2753 throw new IllegalArgumentException (DatatypeMessageFormatter.formatMessage(null, 2754 "InvalidFractional", new Object []{fractional})); 2755 } 2756 } 2757 this.fractionalSecond = fractional; 2758 } 2759 2760 private final class Parser { 2761 private final String format; 2762 private final String value; 2763 2764 private final int flen; 2765 private final int vlen; 2766 2767 private int fidx; 2768 private int vidx; 2769 2770 private Parser(String format, String value) { 2771 this.format = format; 2772 this.value = value; 2773 this.flen = format.length(); 2774 this.vlen = value.length(); 2775 } 2776 2777 2785 public void parse() throws IllegalArgumentException { 2786 while (fidx < flen) { 2787 char fch = format.charAt(fidx++); 2788 2789 if (fch != '%') { skip(fch); 2791 continue; 2792 } 2793 2794 switch (format.charAt(fidx++)) { 2796 case 'Y' : setYear(parseBigInteger(4)); 2798 break; 2799 2800 case 'M' : setMonth(parseInt(2, 2)); 2802 break; 2803 2804 case 'D' : setDay(parseInt(2, 2)); 2806 break; 2807 2808 case 'h' : setHour(parseInt(2, 2)); 2810 break; 2811 2812 case 'm' : setMinute(parseInt(2, 2)); 2814 break; 2815 2816 case 's' : setSecond(parseInt(2, 2)); 2818 2819 if (peek() == '.') { 2820 setFractionalSecond(parseBigDecimal()); 2821 } 2822 break; 2823 2824 case 'z' : char vch = peek(); 2826 if (vch == 'Z') { 2827 vidx++; 2828 setTimezone(0); 2829 } else if (vch == '+' || vch == '-') { 2830 vidx++; 2831 int h = parseInt(2, 2); 2832 skip(':'); 2833 int m = parseInt(2, 2); 2834 setTimezone((h * 60 + m) * (vch == '+' ? 1 : -1)); 2835 } 2836 2837 break; 2838 2839 default : 2840 throw new InternalError (); 2842 } 2843 } 2844 2845 if (vidx != vlen) { 2846 throw new IllegalArgumentException (value); } 2849 } 2850 2851 private char peek() throws IllegalArgumentException { 2852 if (vidx == vlen) { 2853 return (char) -1; 2854 } 2855 return value.charAt(vidx); 2856 } 2857 2858 private char read() throws IllegalArgumentException { 2859 if (vidx == vlen) { 2860 throw new IllegalArgumentException (value); } 2862 return value.charAt(vidx++); 2863 } 2864 2865 private void skip(char ch) throws IllegalArgumentException { 2866 if (read() != ch) { 2867 throw new IllegalArgumentException (value); } 2869 } 2870 2871 private int parseInt(int minDigits, int maxDigits) 2872 throws IllegalArgumentException { 2873 int vstart = vidx; 2874 while (isDigit(peek()) && (vidx - vstart) <= maxDigits) { 2875 vidx++; 2876 } 2877 if ((vidx - vstart) < minDigits) { 2878 throw new IllegalArgumentException (value); } 2881 2882 return Integer.parseInt(value.substring(vstart, vidx)); 2885 } 2890 2891 private BigInteger parseBigInteger(int minDigits) 2892 throws IllegalArgumentException { 2893 int vstart = vidx; 2894 2895 if (peek() == '-') { 2897 vidx++; 2898 } 2899 while (isDigit(peek())) { 2900 vidx++; 2901 } 2902 if ((vidx - vstart) < minDigits) { 2903 throw new IllegalArgumentException (value); } 2906 2907 return new BigInteger (value.substring(vstart, vidx)); 2908 } 2909 2910 private BigDecimal parseBigDecimal() 2911 throws IllegalArgumentException { 2912 int vstart = vidx; 2913 2914 if (peek() == '.') { 2915 vidx++; 2916 } else { 2917 throw new IllegalArgumentException (value); 2918 } 2919 while (isDigit(peek())) { 2920 vidx++; 2921 } 2922 return new BigDecimal (value.substring(vstart, vidx)); 2923 } 2924 } 2925 2926 private static boolean isDigit(char ch) { 2927 return '0' <= ch && ch <= '9'; 2928 } 2929 2930 private String format( String format ) { 2931 StringBuffer buf = new StringBuffer (); 2932 int fidx=0,flen=format.length(); 2933 2934 while(fidx<flen) { 2935 char fch = format.charAt(fidx++); 2936 if(fch!='%') { buf.append(fch); 2938 continue; 2939 } 2940 2941 switch(format.charAt(fidx++)) { 2942 case 'Y': 2943 printNumber(buf,getEonAndYear(), 4); 2944 break; 2945 case 'M': 2946 printNumber(buf,getMonth(),2); 2947 break; 2948 case 'D': 2949 printNumber(buf,getDay(),2); 2950 break; 2951 case 'h': 2952 printNumber(buf,getHour(),2); 2953 break; 2954 case 'm': 2955 printNumber(buf,getMinute(),2); 2956 break; 2957 case 's': 2958 printNumber(buf,getSecond(),2); 2959 if (getFractionalSecond() != null) { 2960 String frac = getFractionalSecond().toString(); 2961 buf.append(frac.substring(1, frac.length())); 2963 } 2964 break; 2965 case 'z': 2966 int offset = getTimezone(); 2967 if(offset == 0) { 2968 buf.append('Z'); 2969 } else if (offset != DatatypeConstants.FIELD_UNDEFINED) { 2970 if(offset<0) { 2971 buf.append('-'); 2972 offset *= -1; 2973 } else { 2974 buf.append('+'); 2975 } 2976 printNumber(buf,offset/60,2); 2977 buf.append(':'); 2978 printNumber(buf,offset%60,2); 2979 } 2980 break; 2981 default: 2982 throw new InternalError (); } 2984 } 2985 2986 return buf.toString(); 2987 } 2988 2989 3001 private void printNumber( StringBuffer out, int number, int nDigits ) { 3002 String s = String.valueOf(number); 3003 for( int i=s.length(); i<nDigits; i++ ) 3004 out.append('0'); 3005 out.append(s); 3006 } 3007 3008 3020 private void printNumber( StringBuffer out, BigInteger number, int nDigits) { 3021 String s = number.toString(); 3022 for( int i=s.length(); i<nDigits; i++ ) 3023 out.append('0'); 3024 out.append(s); 3025 } 3026 3027 3032 static BigInteger sanitize(Number value, int signum) { 3033 if (signum == 0 || value == null) { 3034 return BigInteger.ZERO; 3035 } 3036 return (signum < 0)? ((BigInteger )value).negate() : (BigInteger )value; 3037 } 3038 3039 3043 public void reset() { 3044 eon = orig_eon; 3045 year = orig_year; 3046 month = orig_month; 3047 day = orig_day; 3048 hour = orig_hour; 3049 minute = orig_minute; 3050 second = orig_second; 3051 fractionalSecond = orig_fracSeconds; 3052 timezone = orig_timezone; 3053 } 3054} 3055 3056 | Popular Tags |