jaxp/src/com/sun/org/apache/xerces/internal/impl/dv/xs/AbstractDateTimeDV.java
changeset 17538 d8d911c4e5d4
parent 12457 c348e06f0e82
child 25264 040625ce9b72
equal deleted inserted replaced
17537:50528ec0ea37 17538:d8d911c4e5d4
    49  *
    49  *
    50  * @version $Id: AbstractDateTimeDV.java,v 1.7 2010-11-01 04:39:46 joehw Exp $
    50  * @version $Id: AbstractDateTimeDV.java,v 1.7 2010-11-01 04:39:46 joehw Exp $
    51  */
    51  */
    52 public abstract class AbstractDateTimeDV extends TypeValidator {
    52 public abstract class AbstractDateTimeDV extends TypeValidator {
    53 
    53 
    54         //debugging
    54     //debugging
    55         private static final boolean DEBUG=false;
    55     private static final boolean DEBUG = false;
    56 
    56     //define shared variables for date/time
    57         //define shared variables for date/time
    57     //define constants to be used in assigning default values for
    58 
    58     //all date/time excluding duration
    59 
    59     protected final static int YEAR = 2000;
    60         //define constants to be used in assigning default values for
    60     protected final static int MONTH = 01;
    61         //all date/time excluding duration
    61     protected final static int DAY = 01;
    62         protected final static int YEAR=2000;
       
    63         protected final static int MONTH=01;
       
    64         protected final static int DAY = 01;
       
    65 
       
    66     protected static final DatatypeFactory datatypeFactory = new DatatypeFactoryImpl();
    62     protected static final DatatypeFactory datatypeFactory = new DatatypeFactoryImpl();
    67 
    63 
    68         public short getAllowedFacets(){
    64     @Override
    69                 return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE  | XSSimpleTypeDecl.FACET_MINEXCLUSIVE  );
    65     public short getAllowedFacets() {
    70         }//getAllowedFacets()
    66         return (XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION | XSSimpleTypeDecl.FACET_MAXINCLUSIVE | XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE);
    71 
    67     }//getAllowedFacets()
    72 
    68 
    73         // distinguishes between identity and equality for date/time values
    69     // distinguishes between identity and equality for date/time values
    74         // ie: two values representing the same "moment in time" but with different
    70     // ie: two values representing the same "moment in time" but with different
    75         // remembered timezones are now equal but not identical.
    71     // remembered timezones are now equal but not identical.
    76         public boolean isIdentical (Object value1, Object value2) {
    72     @Override
    77                 if (!(value1 instanceof DateTimeData) || !(value2 instanceof DateTimeData)) {
    73     public boolean isIdentical(Object value1, Object value2) {
    78                         return false;
    74         if (!(value1 instanceof DateTimeData) || !(value2 instanceof DateTimeData)) {
       
    75             return false;
       
    76         }
       
    77 
       
    78         DateTimeData v1 = (DateTimeData) value1;
       
    79         DateTimeData v2 = (DateTimeData) value2;
       
    80 
       
    81         // original timezones must be the same in addition to date/time values
       
    82         // being 'equal'
       
    83         if ((v1.timezoneHr == v2.timezoneHr) && (v1.timezoneMin == v2.timezoneMin)) {
       
    84             return v1.equals(v2);
       
    85         }
       
    86 
       
    87         return false;
       
    88     }//isIdentical()
       
    89 
       
    90     // the parameters are in compiled form (from getActualValue)
       
    91     @Override
       
    92     public int compare(Object value1, Object value2) {
       
    93         return compareDates(((DateTimeData) value1),
       
    94                 ((DateTimeData) value2), true);
       
    95     }//compare()
       
    96 
       
    97     /**
       
    98      * Compare algorithm described in dateDime (3.2.7). Duration datatype
       
    99      * overwrites this method
       
   100      *
       
   101      * @param date1 normalized date representation of the first value
       
   102      * @param date2 normalized date representation of the second value
       
   103      * @param strict
       
   104      * @return less, greater, less_equal, greater_equal, equal
       
   105      */
       
   106     protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) {
       
   107         if (date1.utc == date2.utc) {
       
   108             return compareOrder(date1, date2);
       
   109         }
       
   110         short c1, c2;
       
   111 
       
   112         DateTimeData tempDate = new DateTimeData(null, this);
       
   113 
       
   114         if (date1.utc == 'Z') {
       
   115 
       
   116             //compare date1<=date1<=(date2 with time zone -14)
       
   117             //
       
   118             cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate
       
   119             tempDate.timezoneHr = 14;
       
   120             tempDate.timezoneMin = 0;
       
   121             tempDate.utc = '+';
       
   122             normalize(tempDate);
       
   123             c1 = compareOrder(date1, tempDate);
       
   124             if (c1 == LESS_THAN) {
       
   125                 return c1;
       
   126             }
       
   127 
       
   128             //compare date1>=(date2 with time zone +14)
       
   129             //
       
   130             cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate
       
   131             tempDate.timezoneHr = -14;
       
   132             tempDate.timezoneMin = 0;
       
   133             tempDate.utc = '-';
       
   134             normalize(tempDate);
       
   135             c2 = compareOrder(date1, tempDate);
       
   136             if (c2 == GREATER_THAN) {
       
   137                 return c2;
       
   138             }
       
   139 
       
   140             return INDETERMINATE;
       
   141         } else if (date2.utc == 'Z') {
       
   142 
       
   143             //compare (date1 with time zone -14)<=date2
       
   144             //
       
   145             cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
       
   146             tempDate.timezoneHr = -14;
       
   147             tempDate.timezoneMin = 0;
       
   148             tempDate.utc = '-';
       
   149             if (DEBUG) {
       
   150                 System.out.println("tempDate=" + dateToString(tempDate));
       
   151             }
       
   152             normalize(tempDate);
       
   153             c1 = compareOrder(tempDate, date2);
       
   154             if (DEBUG) {
       
   155                 System.out.println("date=" + dateToString(date2));
       
   156                 System.out.println("tempDate=" + dateToString(tempDate));
       
   157             }
       
   158             if (c1 == LESS_THAN) {
       
   159                 return c1;
       
   160             }
       
   161 
       
   162             //compare (date1 with time zone +14)<=date2
       
   163             //
       
   164             cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
       
   165             tempDate.timezoneHr = 14;
       
   166             tempDate.timezoneMin = 0;
       
   167             tempDate.utc = '+';
       
   168             normalize(tempDate);
       
   169             c2 = compareOrder(tempDate, date2);
       
   170             if (DEBUG) {
       
   171                 System.out.println("tempDate=" + dateToString(tempDate));
       
   172             }
       
   173             if (c2 == GREATER_THAN) {
       
   174                 return c2;
       
   175             }
       
   176 
       
   177             return INDETERMINATE;
       
   178         }
       
   179         return INDETERMINATE;
       
   180 
       
   181     }
       
   182 
       
   183     /**
       
   184      * Given normalized values, determines order-relation between give date/time
       
   185      * objects.
       
   186      *
       
   187      * @param date1 date/time object
       
   188      * @param date2 date/time object
       
   189      * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is
       
   190      * less than date2, a value greater than 0 if date1 is greater than date2
       
   191      */
       
   192     protected short compareOrder(DateTimeData date1, DateTimeData date2) {
       
   193         if (date1.position < 1) {
       
   194             if (date1.year < date2.year) {
       
   195                 return -1;
       
   196             }
       
   197             if (date1.year > date2.year) {
       
   198                 return 1;
       
   199             }
       
   200         }
       
   201         if (date1.position < 2) {
       
   202             if (date1.month < date2.month) {
       
   203                 return -1;
       
   204             }
       
   205             if (date1.month > date2.month) {
       
   206                 return 1;
       
   207             }
       
   208         }
       
   209         if (date1.day < date2.day) {
       
   210             return -1;
       
   211         }
       
   212         if (date1.day > date2.day) {
       
   213             return 1;
       
   214         }
       
   215         if (date1.hour < date2.hour) {
       
   216             return -1;
       
   217         }
       
   218         if (date1.hour > date2.hour) {
       
   219             return 1;
       
   220         }
       
   221         if (date1.minute < date2.minute) {
       
   222             return -1;
       
   223         }
       
   224         if (date1.minute > date2.minute) {
       
   225             return 1;
       
   226         }
       
   227         if (date1.second < date2.second) {
       
   228             return -1;
       
   229         }
       
   230         if (date1.second > date2.second) {
       
   231             return 1;
       
   232         }
       
   233         if (date1.utc < date2.utc) {
       
   234             return -1;
       
   235         }
       
   236         if (date1.utc > date2.utc) {
       
   237             return 1;
       
   238         }
       
   239         return 0;
       
   240     }
       
   241 
       
   242     /**
       
   243      * Parses time hh:mm:ss.sss and time zone if any
       
   244      *
       
   245      * @param start
       
   246      * @param end
       
   247      * @param data
       
   248      * @exception RuntimeException
       
   249      */
       
   250     protected void getTime(String buffer, int start, int end, DateTimeData data) throws RuntimeException {
       
   251 
       
   252         int stop = start + 2;
       
   253 
       
   254         //get hours (hh)
       
   255         data.hour = parseInt(buffer, start, stop);
       
   256 
       
   257         //get minutes (mm)
       
   258 
       
   259         if (buffer.charAt(stop++) != ':') {
       
   260             throw new RuntimeException("Error in parsing time zone");
       
   261         }
       
   262         start = stop;
       
   263         stop = stop + 2;
       
   264         data.minute = parseInt(buffer, start, stop);
       
   265 
       
   266         //get seconds (ss)
       
   267         if (buffer.charAt(stop++) != ':') {
       
   268             throw new RuntimeException("Error in parsing time zone");
       
   269         }
       
   270 
       
   271         //find UTC sign if any
       
   272         int sign = findUTCSign(buffer, start, end);
       
   273 
       
   274         //get seconds (ms)
       
   275         start = stop;
       
   276         stop = sign < 0 ? end : sign;
       
   277         data.second = parseSecond(buffer, start, stop);
       
   278 
       
   279         //parse UTC time zone (hh:mm)
       
   280         if (sign > 0) {
       
   281             getTimeZone(buffer, data, sign, end);
       
   282         }
       
   283     }
       
   284 
       
   285     /**
       
   286      * Parses date CCYY-MM-DD
       
   287      *
       
   288      * @param buffer
       
   289      * @param start start position
       
   290      * @param end end position
       
   291      * @param date
       
   292      * @exception RuntimeException
       
   293      */
       
   294     protected int getDate(String buffer, int start, int end, DateTimeData date) throws RuntimeException {
       
   295 
       
   296         start = getYearMonth(buffer, start, end, date);
       
   297 
       
   298         if (buffer.charAt(start++) != '-') {
       
   299             throw new RuntimeException("CCYY-MM must be followed by '-' sign");
       
   300         }
       
   301         int stop = start + 2;
       
   302         date.day = parseInt(buffer, start, stop);
       
   303         return stop;
       
   304     }
       
   305 
       
   306     /**
       
   307      * Parses date CCYY-MM
       
   308      *
       
   309      * @param buffer
       
   310      * @param start start position
       
   311      * @param end end position
       
   312      * @param date
       
   313      * @exception RuntimeException
       
   314      */
       
   315     protected int getYearMonth(String buffer, int start, int end, DateTimeData date) throws RuntimeException {
       
   316 
       
   317         if (buffer.charAt(0) == '-') {
       
   318             // REVISIT: date starts with preceding '-' sign
       
   319             //          do we have to do anything with it?
       
   320             //
       
   321             start++;
       
   322         }
       
   323         int i = indexOf(buffer, start, end, '-');
       
   324         if (i == -1) {
       
   325             throw new RuntimeException("Year separator is missing or misplaced");
       
   326         }
       
   327         int length = i - start;
       
   328         if (length < 4) {
       
   329             throw new RuntimeException("Year must have 'CCYY' format");
       
   330         } else if (length > 4 && buffer.charAt(start) == '0') {
       
   331             throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
       
   332         }
       
   333         date.year = parseIntYear(buffer, i);
       
   334         if (buffer.charAt(i) != '-') {
       
   335             throw new RuntimeException("CCYY must be followed by '-' sign");
       
   336         }
       
   337         start = ++i;
       
   338         i = start + 2;
       
   339         date.month = parseInt(buffer, start, i);
       
   340         return i; //fStart points right after the MONTH
       
   341     }
       
   342 
       
   343     /**
       
   344      * Shared code from Date and YearMonth datatypes. Finds if time zone sign is
       
   345      * present
       
   346      *
       
   347      * @param end
       
   348      * @param date
       
   349      * @exception RuntimeException
       
   350      */
       
   351     protected void parseTimeZone(String buffer, int start, int end, DateTimeData date) throws RuntimeException {
       
   352 
       
   353         //fStart points right after the date
       
   354 
       
   355         if (start < end) {
       
   356             if (!isNextCharUTCSign(buffer, start, end)) {
       
   357                 throw new RuntimeException("Error in month parsing");
       
   358             } else {
       
   359                 getTimeZone(buffer, date, start, end);
       
   360             }
       
   361         }
       
   362     }
       
   363 
       
   364     /**
       
   365      * Parses time zone: 'Z' or {+,-} followed by hh:mm
       
   366      *
       
   367      * @param data
       
   368      * @param sign
       
   369      * @exception RuntimeException
       
   370      */
       
   371     protected void getTimeZone(String buffer, DateTimeData data, int sign, int end) throws RuntimeException {
       
   372         data.utc = buffer.charAt(sign);
       
   373 
       
   374         if (buffer.charAt(sign) == 'Z') {
       
   375             if (end > (++sign)) {
       
   376                 throw new RuntimeException("Error in parsing time zone");
       
   377             }
       
   378             return;
       
   379         }
       
   380         if (sign <= (end - 6)) {
       
   381 
       
   382             int negate = buffer.charAt(sign) == '-' ? -1 : 1;
       
   383             //parse hr
       
   384             int stop = ++sign + 2;
       
   385             data.timezoneHr = negate * parseInt(buffer, sign, stop);
       
   386             if (buffer.charAt(stop++) != ':') {
       
   387                 throw new RuntimeException("Error in parsing time zone");
       
   388             }
       
   389 
       
   390             //parse min
       
   391             data.timezoneMin = negate * parseInt(buffer, stop, stop + 2);
       
   392 
       
   393             if (stop + 2 != end) {
       
   394                 throw new RuntimeException("Error in parsing time zone");
       
   395             }
       
   396             if (data.timezoneHr != 0 || data.timezoneMin != 0) {
       
   397                 data.normalized = false;
       
   398             }
       
   399         } else {
       
   400             throw new RuntimeException("Error in parsing time zone");
       
   401         }
       
   402         if (DEBUG) {
       
   403             System.out.println("time[hh]=" + data.timezoneHr + " time[mm]=" + data.timezoneMin);
       
   404         }
       
   405     }
       
   406 
       
   407     /**
       
   408      * Computes index of given char within StringBuffer
       
   409      *
       
   410      * @param start
       
   411      * @param end
       
   412      * @param ch character to look for in StringBuffer
       
   413      * @return index of ch within StringBuffer
       
   414      */
       
   415     protected int indexOf(String buffer, int start, int end, char ch) {
       
   416         for (int i = start; i < end; i++) {
       
   417             if (buffer.charAt(i) == ch) {
       
   418                 return i;
       
   419             }
       
   420         }
       
   421         return -1;
       
   422     }
       
   423 
       
   424     /**
       
   425      * Validates given date/time object accoring to W3C PR Schema [D.1 ISO 8601
       
   426      * Conventions]
       
   427      *
       
   428      * @param data
       
   429      */
       
   430     protected void validateDateTime(DateTimeData data) {
       
   431 
       
   432         //REVISIT: should we throw an exception for not valid dates
       
   433         //          or reporting an error message should be sufficient?
       
   434 
       
   435         /**
       
   436          * XML Schema 1.1 - RQ-123: Allow year 0000 in date related types.
       
   437          */
       
   438         if (!Constants.SCHEMA_1_1_SUPPORT && data.year == 0) {
       
   439             throw new RuntimeException("The year \"0000\" is an illegal year value");
       
   440 
       
   441         }
       
   442 
       
   443         if (data.month < 1 || data.month > 12) {
       
   444             throw new RuntimeException("The month must have values 1 to 12");
       
   445 
       
   446         }
       
   447 
       
   448         //validate days
       
   449         if (data.day > maxDayInMonthFor(data.year, data.month) || data.day < 1) {
       
   450             throw new RuntimeException("The day must have values 1 to 31");
       
   451         }
       
   452 
       
   453         //validate hours
       
   454         if (data.hour > 23 || data.hour < 0) {
       
   455             if (data.hour == 24 && data.minute == 0 && data.second == 0) {
       
   456                 data.hour = 0;
       
   457                 if (++data.day > maxDayInMonthFor(data.year, data.month)) {
       
   458                     data.day = 1;
       
   459                     if (++data.month > 12) {
       
   460                         data.month = 1;
       
   461                         if (Constants.SCHEMA_1_1_SUPPORT) {
       
   462                             ++data.year;
       
   463                         } else if (++data.year == 0) {
       
   464                             data.year = 1;
       
   465                         }
       
   466                     }
    79                 }
   467                 }
    80 
   468             } else {
    81                 DateTimeData v1 = (DateTimeData)value1;
   469                 throw new RuntimeException("Hour must have values 0-23, unless 24:00:00");
    82                 DateTimeData v2 = (DateTimeData)value2;
   470             }
    83 
   471         }
    84                 // original timezones must be the same in addition to date/time values
   472 
    85                 // being 'equal'
   473         //validate
    86                 if ((v1.timezoneHr == v2.timezoneHr) && (v1.timezoneMin == v2.timezoneMin)) {
   474         if (data.minute > 59 || data.minute < 0) {
    87                         return v1.equals(v2);
   475             throw new RuntimeException("Minute must have values 0-59");
    88                 }
   476         }
    89 
   477 
    90                 return false;
   478         //validate
    91         }//isIdentical()
   479         if (data.second >= 60 || data.second < 0) {
    92 
   480             throw new RuntimeException("Second must have values 0-59");
    93         // the parameters are in compiled form (from getActualValue)
   481 
    94         public int compare (Object value1, Object value2) {
   482         }
    95                 return compareDates(((DateTimeData)value1),
   483 
    96                                 ((DateTimeData)value2), true);
   484         //validate
    97         }//compare()
   485         if (data.timezoneHr > 14 || data.timezoneHr < -14) {
    98 
   486             throw new RuntimeException("Time zone should have range -14:00 to +14:00");
    99         /**
   487         } else {
   100          * Compare algorithm described in dateDime (3.2.7).
   488             if ((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0) {
   101          * Duration datatype overwrites this method
   489                 throw new RuntimeException("Time zone should have range -14:00 to +14:00");
   102          *
   490             } else if (data.timezoneMin > 59 || data.timezoneMin < -59) {
   103          * @param date1  normalized date representation of the first value
   491                 throw new RuntimeException("Minute must have values 0-59");
   104          * @param date2  normalized date representation of the second value
   492             }
   105          * @param strict
   493         }
   106          * @return less, greater, less_equal, greater_equal, equal
   494 
   107          */
   495     }
   108         protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) {
   496 
   109                 if (date1.utc == date2.utc) {
   497     /**
   110                         return compareOrder(date1, date2);
   498      * Return index of UTC char: 'Z', '+', '-'
   111                 }
   499      *
   112                 short c1, c2;
   500      * @param start
   113 
   501      * @param end
   114                 DateTimeData tempDate = new DateTimeData(null, this);
   502      * @return index of the UTC character that was found
   115 
   503      */
   116                 if ( date1.utc=='Z' ) {
   504     protected int findUTCSign(String buffer, int start, int end) {
   117 
   505         int c;
   118                         //compare date1<=date1<=(date2 with time zone -14)
   506         for (int i = start; i < end; i++) {
   119                         //
   507             c = buffer.charAt(i);
   120                         cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate
   508             if (c == 'Z' || c == '+' || c == '-') {
   121                         tempDate.timezoneHr=14;
   509                 return i;
   122                         tempDate.timezoneMin = 0;
   510             }
   123                         tempDate.utc='+';
   511 
   124                         normalize(tempDate);
   512         }
   125                         c1 = compareOrder(date1, tempDate);
   513         return -1;
   126                         if (c1 == LESS_THAN)
   514     }
   127                                 return c1;
   515 
   128 
   516     /**
   129                         //compare date1>=(date2 with time zone +14)
   517      * Returns
   130                         //
   518      * <code>true</code> if the character at start is 'Z', '+' or '-'.
   131                         cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate
       
   132                         tempDate.timezoneHr = -14;
       
   133                         tempDate.timezoneMin = 0;
       
   134                         tempDate.utc='-';
       
   135                         normalize(tempDate);
       
   136                         c2 = compareOrder(date1, tempDate);
       
   137                         if (c2 == GREATER_THAN)
       
   138                                 return c2;
       
   139 
       
   140                         return INDETERMINATE;
       
   141                 }
       
   142                 else if ( date2.utc=='Z' ) {
       
   143 
       
   144                         //compare (date1 with time zone -14)<=date2
       
   145                         //
       
   146                         cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
       
   147                         tempDate.timezoneHr = -14;
       
   148                         tempDate.timezoneMin = 0;
       
   149                         tempDate.utc='-';
       
   150                         if (DEBUG) {
       
   151                                 System.out.println("tempDate=" + dateToString(tempDate));
       
   152                         }
       
   153                         normalize(tempDate);
       
   154                         c1 = compareOrder(tempDate, date2);
       
   155                         if (DEBUG) {
       
   156                                 System.out.println("date=" + dateToString(date2));
       
   157                                 System.out.println("tempDate=" + dateToString(tempDate));
       
   158                         }
       
   159                         if (c1 == LESS_THAN)
       
   160                                 return c1;
       
   161 
       
   162                         //compare (date1 with time zone +14)<=date2
       
   163                         //
       
   164                         cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate
       
   165                         tempDate.timezoneHr = 14;
       
   166                         tempDate.timezoneMin = 0;
       
   167                         tempDate.utc='+';
       
   168                         normalize(tempDate);
       
   169                         c2 = compareOrder(tempDate, date2);
       
   170                         if (DEBUG) {
       
   171                                 System.out.println("tempDate=" + dateToString(tempDate));
       
   172                         }
       
   173                         if (c2 == GREATER_THAN)
       
   174                                 return c2;
       
   175 
       
   176                         return INDETERMINATE;
       
   177                 }
       
   178                 return INDETERMINATE;
       
   179 
       
   180         }
       
   181 
       
   182         /**
       
   183          * Given normalized values, determines order-relation
       
   184          * between give date/time objects.
       
   185          *
       
   186          * @param date1  date/time object
       
   187          * @param date2  date/time object
       
   188          * @return 0 if date1 and date2 are equal, a value less than 0 if date1 is less than date2, a value greater than 0 if date1 is greater than date2
       
   189          */
       
   190         protected short compareOrder(DateTimeData date1, DateTimeData date2) {
       
   191                 if(date1.position < 1) {
       
   192                         if (date1.year < date2.year)
       
   193                                 return -1;
       
   194                         if (date1.year > date2.year)
       
   195                                 return 1;
       
   196                 }
       
   197                 if(date1.position < 2) {
       
   198                         if (date1.month < date2.month)
       
   199                                 return -1;
       
   200                         if (date1.month > date2.month)
       
   201                                 return 1;
       
   202                 }
       
   203                 if (date1.day < date2.day)
       
   204                         return -1;
       
   205                 if (date1.day > date2.day)
       
   206                         return 1;
       
   207                 if (date1.hour < date2.hour)
       
   208                         return -1;
       
   209                 if (date1.hour > date2.hour)
       
   210                         return 1;
       
   211                 if (date1.minute < date2.minute)
       
   212                         return -1;
       
   213                 if (date1.minute > date2.minute)
       
   214                         return 1;
       
   215                 if (date1.second < date2.second)
       
   216                         return -1;
       
   217                 if (date1.second > date2.second)
       
   218                         return 1;
       
   219                 if (date1.utc < date2.utc)
       
   220                         return -1;
       
   221                 if (date1.utc > date2.utc)
       
   222                         return 1;
       
   223                 return 0;
       
   224         }
       
   225 
       
   226         /**
       
   227          * Parses time hh:mm:ss.sss and time zone if any
       
   228          *
       
   229          * @param start
       
   230          * @param end
       
   231          * @param data
       
   232          * @exception RuntimeException
       
   233          */
       
   234         protected  void getTime (String buffer, int start, int end, DateTimeData data) throws RuntimeException{
       
   235 
       
   236                 int stop = start+2;
       
   237 
       
   238                 //get hours (hh)
       
   239                 data.hour=parseInt(buffer, start,stop);
       
   240 
       
   241                 //get minutes (mm)
       
   242 
       
   243                 if (buffer.charAt(stop++)!=':') {
       
   244                         throw new RuntimeException("Error in parsing time zone" );
       
   245                 }
       
   246                 start = stop;
       
   247                 stop = stop+2;
       
   248                 data.minute=parseInt(buffer, start,stop);
       
   249 
       
   250                 //get seconds (ss)
       
   251                 if (buffer.charAt(stop++)!=':') {
       
   252                         throw new RuntimeException("Error in parsing time zone" );
       
   253                 }
       
   254 
       
   255                 //find UTC sign if any
       
   256                 int sign = findUTCSign(buffer, start, end);
       
   257 
       
   258                 //get seconds (ms)
       
   259                 start = stop;
       
   260                 stop = sign < 0 ? end : sign;
       
   261                 data.second = parseSecond(buffer, start, stop);
       
   262 
       
   263                 //parse UTC time zone (hh:mm)
       
   264                 if (sign > 0) {
       
   265                         getTimeZone(buffer, data, sign, end);
       
   266                 }
       
   267         }
       
   268 
       
   269         /**
       
   270          * Parses date CCYY-MM-DD
       
   271          *
       
   272          * @param buffer
       
   273          * @param start start position
       
   274          * @param end end position
       
   275          * @param date
       
   276          * @exception RuntimeException
       
   277          */
       
   278         protected int getDate (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
       
   279 
       
   280                 start = getYearMonth(buffer, start, end, date);
       
   281 
       
   282                 if (buffer.charAt(start++) !='-') {
       
   283                         throw new RuntimeException("CCYY-MM must be followed by '-' sign");
       
   284                 }
       
   285                 int stop = start + 2;
       
   286                 date.day=parseInt(buffer, start, stop);
       
   287                 return stop;
       
   288         }
       
   289 
       
   290         /**
       
   291          * Parses date CCYY-MM
       
   292          *
       
   293          * @param buffer
       
   294          * @param start start position
       
   295          * @param end end position
       
   296          * @param date
       
   297          * @exception RuntimeException
       
   298          */
       
   299         protected int getYearMonth (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
       
   300 
       
   301                 if ( buffer.charAt(0)=='-' ) {
       
   302                         // REVISIT: date starts with preceding '-' sign
       
   303                         //          do we have to do anything with it?
       
   304                         //
       
   305                         start++;
       
   306                 }
       
   307                 int i = indexOf(buffer, start, end, '-');
       
   308                 if ( i==-1 ) throw new RuntimeException("Year separator is missing or misplaced");
       
   309                 int length = i-start;
       
   310                 if (length<4) {
       
   311                         throw new RuntimeException("Year must have 'CCYY' format");
       
   312                 }
       
   313                 else if (length > 4 && buffer.charAt(start)=='0'){
       
   314                         throw new RuntimeException("Leading zeros are required if the year value would otherwise have fewer than four digits; otherwise they are forbidden");
       
   315                 }
       
   316                 date.year= parseIntYear(buffer, i);
       
   317                 if (buffer.charAt(i)!='-') {
       
   318                         throw new RuntimeException("CCYY must be followed by '-' sign");
       
   319                 }
       
   320                 start = ++i;
       
   321                 i = start +2;
       
   322                 date.month=parseInt(buffer, start, i);
       
   323                 return i; //fStart points right after the MONTH
       
   324         }
       
   325 
       
   326         /**
       
   327          * Shared code from Date and YearMonth datatypes.
       
   328          * Finds if time zone sign is present
       
   329          *
       
   330          * @param end
       
   331          * @param date
       
   332          * @exception RuntimeException
       
   333          */
       
   334         protected void parseTimeZone (String buffer, int start, int end, DateTimeData date) throws RuntimeException{
       
   335 
       
   336                 //fStart points right after the date
       
   337 
       
   338                 if ( start < end ) {
       
   339                         if (!isNextCharUTCSign(buffer, start, end)) {
       
   340                                 throw new RuntimeException ("Error in month parsing");
       
   341                         }
       
   342                         else {
       
   343                                 getTimeZone(buffer, date, start, end);
       
   344                         }
       
   345                 }
       
   346         }
       
   347 
       
   348         /**
       
   349          * Parses time zone: 'Z' or {+,-} followed by  hh:mm
       
   350          *
       
   351          * @param data
       
   352          * @param sign
       
   353          * @exception RuntimeException
       
   354          */
       
   355         protected void getTimeZone (String buffer, DateTimeData data, int sign, int end) throws RuntimeException{
       
   356                 data.utc=buffer.charAt(sign);
       
   357 
       
   358                 if ( buffer.charAt(sign) == 'Z' ) {
       
   359                         if (end>(++sign)) {
       
   360                                 throw new RuntimeException("Error in parsing time zone");
       
   361                         }
       
   362                         return;
       
   363                 }
       
   364                 if ( sign<=(end-6) ) {
       
   365 
       
   366                         int negate = buffer.charAt(sign) == '-'?-1:1;
       
   367                         //parse hr
       
   368                         int stop = ++sign+2;
       
   369                         data.timezoneHr = negate*parseInt(buffer, sign, stop);
       
   370                         if (buffer.charAt(stop++)!=':') {
       
   371                                 throw new RuntimeException("Error in parsing time zone" );
       
   372                         }
       
   373 
       
   374                         //parse min
       
   375                         data.timezoneMin = negate*parseInt(buffer, stop, stop+2);
       
   376 
       
   377                         if ( stop+2!=end ) {
       
   378                                 throw new RuntimeException("Error in parsing time zone");
       
   379                         }
       
   380             if(data.timezoneHr != 0 || data.timezoneMin != 0)
       
   381                 data.normalized = false;
       
   382                 }
       
   383                 else {
       
   384                         throw new RuntimeException("Error in parsing time zone");
       
   385                 }
       
   386                 if ( DEBUG ) {
       
   387                         System.out.println("time[hh]="+data.timezoneHr + " time[mm]=" +data.timezoneMin);
       
   388                 }
       
   389         }
       
   390 
       
   391         /**
       
   392          * Computes index of given char within StringBuffer
       
   393          *
       
   394          * @param start
       
   395          * @param end
       
   396          * @param ch     character to look for in StringBuffer
       
   397          * @return index of ch within StringBuffer
       
   398          */
       
   399         protected  int indexOf (String buffer, int start, int end, char ch) {
       
   400                 for ( int i=start;i<end;i++ ) {
       
   401                         if ( buffer.charAt(i) == ch ) {
       
   402                                 return i;
       
   403                         }
       
   404                 }
       
   405                 return -1;
       
   406         }
       
   407 
       
   408         /**
       
   409          * Validates given date/time object accoring to W3C PR Schema
       
   410          * [D.1 ISO 8601 Conventions]
       
   411          *
       
   412          * @param data
       
   413          */
       
   414         protected void validateDateTime (DateTimeData data) {
       
   415 
       
   416                 //REVISIT: should we throw an exception for not valid dates
       
   417                 //          or reporting an error message should be sufficient?
       
   418 
       
   419                 /**
       
   420                  * XML Schema 1.1 - RQ-123: Allow year 0000 in date related types.
       
   421                  */
       
   422                 if (!Constants.SCHEMA_1_1_SUPPORT && data.year==0 ) {
       
   423                         throw new RuntimeException("The year \"0000\" is an illegal year value");
       
   424 
       
   425                 }
       
   426 
       
   427                 if ( data.month<1 || data.month>12 ) {
       
   428                         throw new RuntimeException("The month must have values 1 to 12");
       
   429 
       
   430                 }
       
   431 
       
   432                 //validate days
       
   433                 if ( data.day>maxDayInMonthFor(data.year, data.month) || data.day<1 ) {
       
   434                         throw new RuntimeException("The day must have values 1 to 31");
       
   435                 }
       
   436 
       
   437                 //validate hours
       
   438                 if ( data.hour>23 || data.hour<0 ) {
       
   439                         if (data.hour == 24 && data.minute == 0 && data.second == 0) {
       
   440                                 data.hour = 0;
       
   441                                 if (++data.day > maxDayInMonthFor(data.year, data.month)) {
       
   442                                         data.day = 1;
       
   443                                         if (++data.month > 12) {
       
   444                                                 data.month = 1;
       
   445                                                 if (Constants.SCHEMA_1_1_SUPPORT) {
       
   446                                                         ++data.year;
       
   447                                                 }
       
   448                                                 else if (++data.year == 0) {
       
   449                                                         data.year = 1;
       
   450                                                 }
       
   451                                         }
       
   452                                 }
       
   453                         }
       
   454                         else {
       
   455                                 throw new RuntimeException("Hour must have values 0-23, unless 24:00:00");
       
   456                         }
       
   457                 }
       
   458 
       
   459                 //validate
       
   460                 if ( data.minute>59 || data.minute<0 ) {
       
   461                         throw new RuntimeException("Minute must have values 0-59");
       
   462                 }
       
   463 
       
   464                 //validate
       
   465                 if ( data.second>=60 || data.second<0 ) {
       
   466                         throw new RuntimeException("Second must have values 0-59");
       
   467 
       
   468                 }
       
   469 
       
   470                 //validate
       
   471                 if ( data.timezoneHr>14 || data.timezoneHr<-14 ) {
       
   472                         throw new RuntimeException("Time zone should have range -14:00 to +14:00");
       
   473                 }
       
   474                 else {
       
   475                         if((data.timezoneHr == 14 || data.timezoneHr == -14) && data.timezoneMin != 0)
       
   476                                 throw new RuntimeException("Time zone should have range -14:00 to +14:00");
       
   477                         else if(data.timezoneMin > 59 || data.timezoneMin < -59)
       
   478                                 throw new RuntimeException("Minute must have values 0-59");
       
   479                 }
       
   480 
       
   481         }
       
   482 
       
   483         /**
       
   484          * Return index of UTC char: 'Z', '+', '-'
       
   485          *
       
   486          * @param start
       
   487          * @param end
       
   488          * @return index of the UTC character that was found
       
   489          */
       
   490         protected int findUTCSign (String buffer, int start, int end) {
       
   491                 int c;
       
   492                 for ( int i=start;i<end;i++ ) {
       
   493                         c=buffer.charAt(i);
       
   494                         if ( c == 'Z' || c=='+' || c=='-' ) {
       
   495                                 return i;
       
   496                         }
       
   497 
       
   498                 }
       
   499                 return -1;
       
   500         }
       
   501 
       
   502     /**
       
   503      * Returns <code>true</code> if the character at start is 'Z', '+' or '-'.
       
   504      */
   519      */
   505     protected final boolean isNextCharUTCSign(String buffer, int start, int end) {
   520     protected final boolean isNextCharUTCSign(String buffer, int start, int end) {
   506         if (start < end) {
   521         if (start < end) {
   507             char c = buffer.charAt(start);
   522             char c = buffer.charAt(start);
   508             return (c == 'Z' || c == '+' || c == '-');
   523             return (c == 'Z' || c == '+' || c == '-');
   509         }
   524         }
   510         return false;
   525         return false;
   511     }
   526     }
   512 
   527 
   513         /**
   528     /**
   514          * Given start and end position, parses string value
   529      * Given start and end position, parses string value
   515          *
   530      *
   516          * @param buffer string to parse
   531      * @param buffer string to parse
   517          * @param start  start position
   532      * @param start start position
   518          * @param end    end position
   533      * @param end end position
   519          * @return  return integer representation of characters
   534      * @return return integer representation of characters
   520          */
   535      */
   521         protected  int parseInt (String buffer, int start, int end)
   536     protected int parseInt(String buffer, int start, int end)
   522         throws NumberFormatException{
   537             throws NumberFormatException {
   523                 //REVISIT: more testing on this parsing needs to be done.
   538         //REVISIT: more testing on this parsing needs to be done.
   524                 int radix=10;
   539         int radix = 10;
   525                 int result = 0;
   540         int result = 0;
   526                 int digit=0;
   541         int digit = 0;
   527                 int limit = -Integer.MAX_VALUE;
   542         int limit = -Integer.MAX_VALUE;
   528                 int multmin = limit / radix;
   543         int multmin = limit / radix;
   529                 int i = start;
   544         int i = start;
   530                 do {
   545         do {
   531                         digit = getDigit(buffer.charAt(i));
   546             digit = getDigit(buffer.charAt(i));
   532                         if ( digit < 0 ) throw new NumberFormatException("'" + buffer + "' has wrong format");
   547             if (digit < 0) {
   533                         if ( result < multmin ) throw new NumberFormatException("'" + buffer + "' has wrong format");
   548                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   534                         result *= radix;
   549             }
   535                         if ( result < limit + digit ) throw new NumberFormatException("'" + buffer + "' has wrong format");
   550             if (result < multmin) {
   536                         result -= digit;
   551                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   537 
   552             }
   538                 }while ( ++i < end );
   553             result *= radix;
   539                 return -result;
   554             if (result < limit + digit) {
   540         }
   555                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   541 
   556             }
   542         // parse Year differently to support negative value.
   557             result -= digit;
   543         protected int parseIntYear (String buffer, int end){
   558 
   544                 int radix=10;
   559         } while (++i < end);
   545                 int result = 0;
   560         return -result;
   546                 boolean negative = false;
   561     }
   547                 int i=0;
   562 
   548                 int limit;
   563     // parse Year differently to support negative value.
   549                 int multmin;
   564     protected int parseIntYear(String buffer, int end) {
   550                 int digit=0;
   565         int radix = 10;
   551 
   566         int result = 0;
   552                 if (buffer.charAt(0) == '-'){
   567         boolean negative = false;
   553                         negative = true;
   568         int i = 0;
   554                         limit = Integer.MIN_VALUE;
   569         int limit;
   555                         i++;
   570         int multmin;
   556 
   571         int digit = 0;
   557                 }
   572 
   558                 else{
   573         if (buffer.charAt(0) == '-') {
   559                         limit = -Integer.MAX_VALUE;
   574             negative = true;
   560                 }
   575             limit = Integer.MIN_VALUE;
   561                 multmin = limit / radix;
   576             i++;
   562                 while (i < end)
   577 
   563                 {
   578         } else {
   564                         digit = getDigit(buffer.charAt(i++));
   579             limit = -Integer.MAX_VALUE;
   565                         if (digit < 0) throw new NumberFormatException("'" + buffer + "' has wrong format");
   580         }
   566                         if (result < multmin) throw new NumberFormatException("'" + buffer + "' has wrong format");
   581         multmin = limit / radix;
   567                         result *= radix;
   582         while (i < end) {
   568                         if (result < limit + digit) throw new NumberFormatException("'" + buffer + "' has wrong format");
   583             digit = getDigit(buffer.charAt(i++));
   569                         result -= digit;
   584             if (digit < 0) {
   570                 }
   585                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   571 
   586             }
   572                 if (negative)
   587             if (result < multmin) {
   573                 {
   588                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   574                         if (i > 1) return result;
   589             }
   575                         else throw new NumberFormatException("'" + buffer + "' has wrong format");
   590             result *= radix;
   576                 }
   591             if (result < limit + digit) {
   577                 return -result;
   592                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   578 
   593             }
   579         }
   594             result -= digit;
   580 
   595         }
   581         /**
   596 
   582          * If timezone present - normalize dateTime  [E Adding durations to dateTimes]
   597         if (negative) {
   583          *
   598             if (i > 1) {
   584          * @param date   CCYY-MM-DDThh:mm:ss+03
   599                 return result;
   585          */
   600             } else {
   586         protected void normalize(DateTimeData date) {
   601                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   587 
   602             }
   588                 // REVISIT: we have common code in addDuration() for durations
   603         }
   589                 //          should consider reorganizing it.
   604         return -result;
   590                 //
   605 
   591 
   606     }
   592                 //add minutes (from time zone)
   607 
   593                 int negate = -1;
   608     /**
   594 
   609      * If timezone present - normalize dateTime [E Adding durations to
   595                 if ( DEBUG ) {
   610      * dateTimes]
   596                         System.out.println("==>date.minute"+date.minute);
   611      *
   597                         System.out.println("==>date.timezoneMin" +date.timezoneMin);
   612      * @param date CCYY-MM-DDThh:mm:ss+03
   598                 }
   613      */
   599                 int temp = date.minute + negate * date.timezoneMin;
   614     protected void normalize(DateTimeData date) {
   600                 int carry = fQuotient (temp, 60);
   615 
   601                 date.minute= mod(temp, 60, carry);
   616         // REVISIT: we have common code in addDuration() for durations
   602 
   617         //          should consider reorganizing it.
   603                 if ( DEBUG ) {
   618         //
   604                         System.out.println("==>carry: " + carry);
   619 
   605                 }
   620         //add minutes (from time zone)
   606                 //add hours
   621         int negate = -1;
   607                 temp = date.hour + negate * date.timezoneHr + carry;
   622 
   608                 carry = fQuotient(temp, 24);
   623         if (DEBUG) {
   609                 date.hour=mod(temp, 24, carry);
   624             System.out.println("==>date.minute" + date.minute);
   610                 if ( DEBUG ) {
   625             System.out.println("==>date.timezoneMin" + date.timezoneMin);
   611                         System.out.println("==>date.hour"+date.hour);
   626         }
   612                         System.out.println("==>carry: " + carry);
   627         int temp = date.minute + negate * date.timezoneMin;
   613                 }
   628         int carry = fQuotient(temp, 60);
   614 
   629         date.minute = mod(temp, 60, carry);
   615                 date.day=date.day+carry;
   630 
   616 
   631         if (DEBUG) {
   617                 while ( true ) {
   632             System.out.println("==>carry: " + carry);
   618                         temp=maxDayInMonthFor(date.year, date.month);
   633         }
   619                         if (date.day<1) {
   634         //add hours
   620                                 date.day = date.day + maxDayInMonthFor(date.year, date.month-1);
   635         temp = date.hour + negate * date.timezoneHr + carry;
   621                                 carry=-1;
   636         carry = fQuotient(temp, 24);
   622                         }
   637         date.hour = mod(temp, 24, carry);
   623                         else if ( date.day>temp ) {
   638         if (DEBUG) {
   624                                 date.day=date.day-temp;
   639             System.out.println("==>date.hour" + date.hour);
   625                                 carry=1;
   640             System.out.println("==>carry: " + carry);
   626                         }
   641         }
   627                         else {
   642 
   628                                 break;
   643         date.day = date.day + carry;
   629                         }
   644 
   630                         temp=date.month+carry;
   645         while (true) {
   631                         date.month=modulo(temp, 1, 13);
   646             temp = maxDayInMonthFor(date.year, date.month);
   632                         date.year=date.year+fQuotient(temp, 1, 13);
   647             if (date.day < 1) {
   633             if(date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) {
   648                 date.day = date.day + maxDayInMonthFor(date.year, date.month - 1);
   634                 date.year = (date.timezoneHr < 0 || date.timezoneMin < 0)?1:-1;
   649                 carry = -1;
   635             }
   650             } else if (date.day > temp) {
   636                 }
   651                 date.day = date.day - temp;
   637                 date.utc='Z';
   652                 carry = 1;
   638         }
   653             } else {
   639 
   654                 break;
   640 
   655             }
   641         /**
   656             temp = date.month + carry;
       
   657             date.month = modulo(temp, 1, 13);
       
   658             date.year = date.year + fQuotient(temp, 1, 13);
       
   659             if (date.year == 0 && !Constants.SCHEMA_1_1_SUPPORT) {
       
   660                 date.year = (date.timezoneHr < 0 || date.timezoneMin < 0) ? 1 : -1;
       
   661             }
       
   662         }
       
   663         date.utc = 'Z';
       
   664     }
       
   665 
       
   666     /**
   642      * @param date
   667      * @param date
   643      */
   668      */
   644     protected void saveUnnormalized(DateTimeData date) {
   669     protected void saveUnnormalized(DateTimeData date) {
   645         date.unNormYear = date.year;
   670         date.unNormYear = date.year;
   646         date.unNormMonth = date.month;
   671         date.unNormMonth = date.month;
   649         date.unNormMinute = date.minute;
   674         date.unNormMinute = date.minute;
   650         date.unNormSecond = date.second;
   675         date.unNormSecond = date.second;
   651     }
   676     }
   652 
   677 
   653     /**
   678     /**
   654          * Resets object representation of date/time
   679      * Resets object representation of date/time
   655          *
   680      *
   656          * @param data   date/time object
   681      * @param data date/time object
   657          */
   682      */
   658         protected void resetDateObj(DateTimeData data) {
   683     protected void resetDateObj(DateTimeData data) {
   659                 data.year = 0;
   684         data.year = 0;
   660                 data.month = 0;
   685         data.month = 0;
   661                 data.day = 0;
   686         data.day = 0;
   662                 data.hour = 0;
   687         data.hour = 0;
   663                 data.minute = 0;
   688         data.minute = 0;
   664                 data.second = 0;
   689         data.second = 0;
   665                 data.utc = 0;
   690         data.utc = 0;
   666                 data.timezoneHr = 0;
   691         data.timezoneHr = 0;
   667                 data.timezoneMin = 0;
   692         data.timezoneMin = 0;
   668         }
   693     }
   669 
   694 
   670         /**
   695     /**
   671          * Given {year,month} computes maximum
   696      * Given {year,month} computes maximum number of days for given month
   672          * number of days for given month
   697      *
   673          *
   698      * @param year
   674          * @param year
   699      * @param month
   675          * @param month
   700      * @return integer containg the number of days in a given month
   676          * @return integer containg the number of days in a given month
   701      */
   677          */
   702     protected int maxDayInMonthFor(int year, int month) {
   678         protected int maxDayInMonthFor(int year, int month) {
   703         //validate days
   679                 //validate days
   704         if (month == 4 || month == 6 || month == 9 || month == 11) {
   680                 if ( month==4 || month==6 || month==9 || month==11 ) {
   705             return 30;
   681                         return 30;
   706         } else if (month == 2) {
   682                 }
   707             if (isLeapYear(year)) {
   683                 else if ( month==2 ) {
   708                 return 29;
   684                         if ( isLeapYear(year) ) {
   709             } else {
   685                                 return 29;
   710                 return 28;
   686                         }
   711             }
   687                         else {
   712         } else {
   688                                 return 28;
   713             return 31;
   689                         }
   714         }
   690                 }
   715     }
   691                 else {
   716 
   692                         return 31;
   717     private boolean isLeapYear(int year) {
   693                 }
   718 
   694         }
   719         //REVISIT: should we take care about Julian calendar?
   695 
   720         return ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)));
   696         private boolean isLeapYear(int year) {
   721     }
   697 
   722 
   698                 //REVISIT: should we take care about Julian calendar?
   723     //
   699                 return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0)));
   724     // help function described in W3C PR Schema [E Adding durations to dateTimes]
   700         }
   725     //
   701 
   726     protected int mod(int a, int b, int quotient) {
   702         //
   727         //modulo(a, b) = a - fQuotient(a,b)*b
   703         // help function described in W3C PR Schema [E Adding durations to dateTimes]
   728         return (a - quotient * b);
   704         //
   729     }
   705         protected int mod (int a, int b, int quotient) {
   730 
   706                 //modulo(a, b) = a - fQuotient(a,b)*b
   731     //
   707                 return (a - quotient*b) ;
   732     // help function described in W3C PR Schema [E Adding durations to dateTimes]
   708         }
   733     //
   709 
   734     protected int fQuotient(int a, int b) {
   710         //
   735 
   711         // help function described in W3C PR Schema [E Adding durations to dateTimes]
   736         //fQuotient(a, b) = the greatest integer less than or equal to a/b
   712         //
   737         return (int) Math.floor((float) a / b);
   713         protected int fQuotient (int a, int b) {
   738     }
   714 
   739 
   715                 //fQuotient(a, b) = the greatest integer less than or equal to a/b
   740     //
   716                 return (int)Math.floor((float)a/b);
   741     // help function described in W3C PR Schema [E Adding durations to dateTimes]
   717         }
   742     //
   718 
   743     protected int modulo(int temp, int low, int high) {
   719         //
   744         //modulo(a - low, high - low) + low
   720         // help function described in W3C PR Schema [E Adding durations to dateTimes]
   745         int a = temp - low;
   721         //
   746         int b = high - low;
   722         protected int modulo (int temp, int low, int high) {
   747         return (mod(a, b, fQuotient(a, b)) + low);
   723                 //modulo(a - low, high - low) + low
   748     }
   724                 int a = temp - low;
   749 
   725                 int b = high - low;
   750     //
   726                 return (mod (a, b, fQuotient(a, b)) + low) ;
   751     // help function described in W3C PR Schema [E Adding durations to dateTimes]
   727         }
   752     //
   728 
   753     protected int fQuotient(int temp, int low, int high) {
   729         //
   754         //fQuotient(a - low, high - low)
   730         // help function described in W3C PR Schema [E Adding durations to dateTimes]
   755 
   731         //
   756         return fQuotient(temp - low, high - low);
   732         protected int fQuotient (int temp, int low, int high) {
   757     }
   733                 //fQuotient(a - low, high - low)
   758 
   734 
   759     protected String dateToString(DateTimeData date) {
   735                 return fQuotient(temp - low, high - low);
   760         StringBuffer message = new StringBuffer(25);
   736         }
   761         append(message, date.year, 4);
   737 
   762         message.append('-');
   738 
   763         append(message, date.month, 2);
   739         protected String dateToString(DateTimeData date) {
   764         message.append('-');
   740                 StringBuffer message = new StringBuffer(25);
   765         append(message, date.day, 2);
   741                 append(message, date.year, 4);
   766         message.append('T');
   742                 message.append('-');
   767         append(message, date.hour, 2);
   743                 append(message, date.month, 2);
   768         message.append(':');
   744                 message.append('-');
   769         append(message, date.minute, 2);
   745                 append(message, date.day, 2);
   770         message.append(':');
   746                 message.append('T');
   771         append(message, date.second);
   747                 append(message, date.hour, 2);
   772         append(message, (char) date.utc, 0);
   748                 message.append(':');
   773         return message.toString();
   749                 append(message, date.minute, 2);
   774     }
   750                 message.append(':');
   775 
   751                 append(message, date.second);
   776     protected final void append(StringBuffer message, int value, int nch) {
   752                 append(message, (char)date.utc, 0);
       
   753                 return message.toString();
       
   754         }
       
   755 
       
   756         protected final void append(StringBuffer message, int value, int nch) {
       
   757         if (value == Integer.MIN_VALUE) {
   777         if (value == Integer.MIN_VALUE) {
   758             message.append(value);
   778             message.append(value);
   759             return;
   779             return;
   760         }
   780         }
   761                 if (value < 0) {
   781         if (value < 0) {
   762                         message.append('-');
   782             message.append('-');
   763                         value = -value;
   783             value = -value;
   764                 }
   784         }
   765                 if (nch == 4) {
   785         if (nch == 4) {
   766                         if (value < 10)
   786             if (value < 10) {
   767                                 message.append("000");
   787                 message.append("000");
   768                         else if (value < 100)
   788             } else if (value < 100) {
   769                                 message.append("00");
   789                 message.append("00");
   770                         else if (value < 1000)
   790             } else if (value < 1000) {
   771                                 message.append('0');
   791                 message.append('0');
   772                         message.append(value);
   792             }
   773                 }
   793             message.append(value);
   774                 else if (nch == 2) {
   794         } else if (nch == 2) {
   775                         if (value < 10)
       
   776                                 message.append('0');
       
   777                         message.append(value);
       
   778                 }
       
   779                 else {
       
   780                         if (value != 0)
       
   781                                 message.append((char)value);
       
   782                 }
       
   783         }
       
   784 
       
   785         protected final void append(StringBuffer message, double value) {
       
   786             if (value < 0) {
       
   787                 message.append('-');
       
   788                 value = -value;
       
   789             }
       
   790             if (value < 10) {
   795             if (value < 10) {
   791                 message.append('0');
   796                 message.append('0');
   792             }
   797             }
   793             append2(message, value);
   798             message.append(value);
   794         }
   799         } else {
       
   800             if (value != 0) {
       
   801                 message.append((char) value);
       
   802             }
       
   803         }
       
   804     }
       
   805 
       
   806     protected final void append(StringBuffer message, double value) {
       
   807         if (value < 0) {
       
   808             message.append('-');
       
   809             value = -value;
       
   810         }
       
   811         if (value < 10) {
       
   812             message.append('0');
       
   813         }
       
   814         append2(message, value);
       
   815     }
   795 
   816 
   796     protected final void append2(StringBuffer message, double value) {
   817     protected final void append2(StringBuffer message, double value) {
   797         final int intValue = (int) value;
   818         final int intValue = (int) value;
   798         if (value == intValue) {
   819         if (value == intValue) {
   799             message.append(intValue);
   820             message.append(intValue);
   800         }
   821         } else {
   801         else {
       
   802             append3(message, value);
   822             append3(message, value);
   803         }
   823         }
   804     }
   824     }
   805 
   825 
   806     private void append3(StringBuffer message, double value) {
   826     private void append3(StringBuffer message, double value) {
   813         int exp;
   833         int exp;
   814         if (value < 1) {
   834         if (value < 1) {
   815             // Need to convert from scientific notation of the form
   835             // Need to convert from scientific notation of the form
   816             // n.nnn...E-N (N >= 4) to a normal decimal value.
   836             // n.nnn...E-N (N >= 4) to a normal decimal value.
   817             try {
   837             try {
   818                 exp = parseInt(d, eIndex+2, d.length());
   838                 exp = parseInt(d, eIndex + 2, d.length());
   819             }
   839             } // This should never happen.
   820             // This should never happen.
       
   821             // It's only possible if String.valueOf(double) is broken.
   840             // It's only possible if String.valueOf(double) is broken.
   822             catch (Exception e) {
   841             catch (Exception e) {
   823                 message.append(d);
   842                 message.append(d);
   824                 return;
   843                 return;
   825             }
   844             }
   841                 char c = d.charAt(i);
   860                 char c = d.charAt(i);
   842                 if (c != '.') {
   861                 if (c != '.') {
   843                     message.append(c);
   862                     message.append(c);
   844                 }
   863                 }
   845             }
   864             }
   846         }
   865         } else {
   847         else {
       
   848             // Need to convert from scientific notation of the form
   866             // Need to convert from scientific notation of the form
   849             // n.nnn...EN (N >= 7) to a normal decimal value.
   867             // n.nnn...EN (N >= 7) to a normal decimal value.
   850             try {
   868             try {
   851                 exp = parseInt(d, eIndex+1, d.length());
   869                 exp = parseInt(d, eIndex + 1, d.length());
   852             }
   870             } // This should never happen.
   853             // This should never happen.
       
   854             // It's only possible if String.valueOf(double) is broken.
   871             // It's only possible if String.valueOf(double) is broken.
   855             catch (Exception e) {
   872             catch (Exception e) {
   856                 message.append(d);
   873                 message.append(d);
   857                 return;
   874                 return;
   858             }
   875             }
   871                 message.append('0');
   888                 message.append('0');
   872             }
   889             }
   873         }
   890         }
   874     }
   891     }
   875 
   892 
   876         protected double parseSecond(String buffer, int start, int end)
   893     protected double parseSecond(String buffer, int start, int end)
   877         throws NumberFormatException {
   894             throws NumberFormatException {
   878                 int dot = -1;
   895         int dot = -1;
   879                 for (int i = start; i < end; i++) {
   896         for (int i = start; i < end; i++) {
   880                         char ch = buffer.charAt(i);
   897             char ch = buffer.charAt(i);
   881                         if (ch == '.')
   898             if (ch == '.') {
   882                                 dot = i;
   899                 dot = i;
   883                         else if (ch > '9' || ch < '0')
   900             } else if (ch > '9' || ch < '0') {
   884                                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   901                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   885                 }
   902             }
   886                 if (dot == -1) {
   903         }
   887                         if (start+2 != end)
   904         if (dot == -1) {
   888                                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   905             if (start + 2 != end) {
   889                 }
   906                 throw new NumberFormatException("'" + buffer + "' has wrong format");
   890                 else if (start+2 != dot || dot+1 == end) {
   907             }
   891                         throw new NumberFormatException("'" + buffer + "' has wrong format");
   908         } else if (start + 2 != dot || dot + 1 == end) {
   892                 }
   909             throw new NumberFormatException("'" + buffer + "' has wrong format");
   893                 return Double.parseDouble(buffer.substring(start, end));
   910         }
   894         }
   911         return Double.parseDouble(buffer.substring(start, end));
   895 
   912     }
   896         //
   913 
   897         //Private help functions
   914     //
   898         //
   915     //Private help functions
   899 
   916     //
   900         private void cloneDate (DateTimeData finalValue, DateTimeData tempDate) {
   917     private void cloneDate(DateTimeData finalValue, DateTimeData tempDate) {
   901                 tempDate.year = finalValue.year;
   918         tempDate.year = finalValue.year;
   902                 tempDate.month = finalValue.month;
   919         tempDate.month = finalValue.month;
   903                 tempDate.day = finalValue.day;
   920         tempDate.day = finalValue.day;
   904                 tempDate.hour = finalValue.hour;
   921         tempDate.hour = finalValue.hour;
   905                 tempDate.minute = finalValue.minute;
   922         tempDate.minute = finalValue.minute;
   906                 tempDate.second = finalValue.second;
   923         tempDate.second = finalValue.second;
   907                 tempDate.utc = finalValue.utc;
   924         tempDate.utc = finalValue.utc;
   908                 tempDate.timezoneHr = finalValue.timezoneHr;
   925         tempDate.timezoneHr = finalValue.timezoneHr;
   909                 tempDate.timezoneMin = finalValue.timezoneMin;
   926         tempDate.timezoneMin = finalValue.timezoneMin;
   910         }
   927     }
   911 
   928 
   912         /**
   929     /**
   913          * Represents date time data
   930      * Represents date time data
   914          */
   931      */
   915         static final class DateTimeData implements XSDateTime {
   932     static final class DateTimeData implements XSDateTime {
   916                 int year, month, day, hour, minute, utc;
   933 
   917                 double second;
   934         int year, month, day, hour, minute, utc;
   918                 int timezoneHr, timezoneMin;
   935         double second;
       
   936         int timezoneHr, timezoneMin;
   919         private String originalValue;
   937         private String originalValue;
   920         boolean normalized = true;
   938         boolean normalized = true;
   921 
       
   922         int unNormYear;
   939         int unNormYear;
   923         int unNormMonth;
   940         int unNormMonth;
   924         int unNormDay;
   941         int unNormDay;
   925         int unNormHour;
   942         int unNormHour;
   926         int unNormMinute;
   943         int unNormMinute;
   927         double unNormSecond;
   944         double unNormSecond;
   928 
   945         // used for comparisons - to decide the 'interesting' portions of
   929                 // used for comparisons - to decide the 'interesting' portions of
   946         // a date/time based data type.
   930                 // a date/time based data type.
   947         int position;
   931                 int position;
   948         // a pointer to the type that was used go generate this data
   932                 // a pointer to the type that was used go generate this data
   949         // note that this is not the actual simple type, but one of the
   933                 // note that this is not the actual simple type, but one of the
   950         // statically created XXXDV objects, so this won't cause any GC problem.
   934                 // statically created XXXDV objects, so this won't cause any GC problem.
   951         final AbstractDateTimeDV type;
   935                 final AbstractDateTimeDV type;
   952         private volatile String canonical;
   936                 private String canonical;
   953 
   937                 public DateTimeData(String originalValue, AbstractDateTimeDV type) {
   954         public DateTimeData(String originalValue, AbstractDateTimeDV type) {
   938             this.originalValue = originalValue;
   955             this.originalValue = originalValue;
   939                         this.type = type;
   956             this.type = type;
   940                 }
   957         }
   941                 public DateTimeData(int year, int month, int day, int hour, int minute,
   958 
   942                                 double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) {
   959         public DateTimeData(int year, int month, int day, int hour, int minute,
   943                         this.year = year;
   960                 double second, int utc, String originalValue, boolean normalized, AbstractDateTimeDV type) {
   944                         this.month = month;
   961             this.year = year;
   945                         this.day = day;
   962             this.month = month;
   946                         this.hour = hour;
   963             this.day = day;
   947                         this.minute = minute;
   964             this.hour = hour;
   948                         this.second = second;
   965             this.minute = minute;
   949                         this.utc = utc;
   966             this.second = second;
   950                         this.type = type;
   967             this.utc = utc;
       
   968             this.type = type;
   951             this.originalValue = originalValue;
   969             this.originalValue = originalValue;
   952                 }
   970         }
   953                 public boolean equals(Object obj) {
   971 
   954                         if (!(obj instanceof DateTimeData))
   972         @Override
   955                                 return false;
   973         public boolean equals(Object obj) {
   956                         return type.compareDates(this, (DateTimeData)obj, true)==0;
   974             if (!(obj instanceof DateTimeData)) {
   957                 }
   975                 return false;
   958                 public synchronized String toString() {
   976             }
   959                         if (canonical == null) {
   977             return type.compareDates(this, (DateTimeData) obj, true) == 0;
   960                                 canonical = type.dateToString(this);
   978         }
   961                         }
   979 
   962                         return canonical;
   980         // If two DateTimeData are equals - then they should have the same
   963                 }
   981         // hashcode. This means we need to convert the date to UTC before
   964                 /* (non-Javadoc)
   982         // we return its hashcode.
   965                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear()
   983         // The DateTimeData is unfortunately mutable - so we cannot
   966                  */
   984         // cache the result of the conversion...
   967                 public int getYears() {
   985         //
   968             if(type instanceof DurationDV)
   986         @Override
       
   987         public int hashCode() {
       
   988             final DateTimeData tempDate = new DateTimeData(null, type);
       
   989             type.cloneDate(this, tempDate);
       
   990             type.normalize(tempDate);
       
   991             return type.dateToString(tempDate).hashCode();
       
   992         }
       
   993 
       
   994         @Override
       
   995         public String toString() {
       
   996             if (canonical == null) {
       
   997                 canonical = type.dateToString(this);
       
   998             }
       
   999             return canonical;
       
  1000         }
       
  1001         /* (non-Javadoc)
       
  1002          * @see org.apache.xerces.xs.datatypes.XSDateTime#getYear()
       
  1003          */
       
  1004 
       
  1005         @Override
       
  1006         public int getYears() {
       
  1007             if (type instanceof DurationDV) {
   969                 return 0;
  1008                 return 0;
   970                         return normalized?year:unNormYear;
  1009             }
   971                 }
  1010             return normalized ? year : unNormYear;
   972                 /* (non-Javadoc)
  1011         }
   973                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth()
  1012         /* (non-Javadoc)
   974                  */
  1013          * @see org.apache.xerces.xs.datatypes.XSDateTime#getMonth()
   975                 public int getMonths() {
  1014          */
   976             if(type instanceof DurationDV) {
  1015 
   977                 return year*12 + month;
  1016         @Override
   978             }
  1017         public int getMonths() {
   979                         return normalized?month:unNormMonth;
  1018             if (type instanceof DurationDV) {
   980                 }
  1019                 return year * 12 + month;
   981                 /* (non-Javadoc)
  1020             }
   982                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay()
  1021             return normalized ? month : unNormMonth;
   983                  */
  1022         }
   984                 public int getDays() {
  1023         /* (non-Javadoc)
   985             if(type instanceof DurationDV)
  1024          * @see org.apache.xerces.xs.datatypes.XSDateTime#getDay()
       
  1025          */
       
  1026 
       
  1027         @Override
       
  1028         public int getDays() {
       
  1029             if (type instanceof DurationDV) {
   986                 return 0;
  1030                 return 0;
   987                         return normalized?day:unNormDay;
  1031             }
   988                 }
  1032             return normalized ? day : unNormDay;
   989                 /* (non-Javadoc)
  1033         }
   990                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour()
  1034         /* (non-Javadoc)
   991                  */
  1035          * @see org.apache.xerces.xs.datatypes.XSDateTime#getHour()
   992                 public int getHours() {
  1036          */
   993             if(type instanceof DurationDV)
  1037 
       
  1038         @Override
       
  1039         public int getHours() {
       
  1040             if (type instanceof DurationDV) {
   994                 return 0;
  1041                 return 0;
   995                         return normalized?hour:unNormHour;
  1042             }
   996                 }
  1043             return normalized ? hour : unNormHour;
   997                 /* (non-Javadoc)
  1044         }
   998                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes()
  1045         /* (non-Javadoc)
   999                  */
  1046          * @see org.apache.xerces.xs.datatypes.XSDateTime#getMinutes()
  1000                 public int getMinutes() {
  1047          */
  1001             if(type instanceof DurationDV)
  1048 
       
  1049         @Override
       
  1050         public int getMinutes() {
       
  1051             if (type instanceof DurationDV) {
  1002                 return 0;
  1052                 return 0;
  1003                         return normalized?minute:unNormMinute;
  1053             }
  1004                 }
  1054             return normalized ? minute : unNormMinute;
  1005                 /* (non-Javadoc)
  1055         }
  1006                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds()
  1056         /* (non-Javadoc)
  1007                  */
  1057          * @see org.apache.xerces.xs.datatypes.XSDateTime#getSeconds()
  1008                 public double getSeconds() {
  1058          */
  1009             if(type instanceof DurationDV) {
  1059 
  1010                 return day*24*60*60 + hour*60*60 + minute*60 + second;
  1060         @Override
  1011             }
  1061         public double getSeconds() {
  1012                         return normalized?second:unNormSecond;
  1062             if (type instanceof DurationDV) {
  1013                 }
  1063                 return day * 24 * 60 * 60 + hour * 60 * 60 + minute * 60 + second;
  1014                 /* (non-Javadoc)
  1064             }
  1015                  * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone()
  1065             return normalized ? second : unNormSecond;
  1016                  */
  1066         }
  1017                 public boolean hasTimeZone() {
  1067         /* (non-Javadoc)
  1018                         return utc != 0;
  1068          * @see org.apache.xerces.xs.datatypes.XSDateTime#hasTimeZone()
  1019                 }
  1069          */
  1020                 /* (non-Javadoc)
  1070 
  1021                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours()
  1071         @Override
  1022                  */
  1072         public boolean hasTimeZone() {
  1023                 public int getTimeZoneHours() {
  1073             return utc != 0;
  1024                         return timezoneHr;
  1074         }
  1025                 }
  1075         /* (non-Javadoc)
  1026                 /* (non-Javadoc)
  1076          * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneHours()
  1027                  * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes()
  1077          */
  1028                  */
  1078 
  1029                 public int getTimeZoneMinutes() {
  1079         @Override
  1030                         return timezoneMin;
  1080         public int getTimeZoneHours() {
  1031                 }
  1081             return timezoneHr;
       
  1082         }
       
  1083         /* (non-Javadoc)
       
  1084          * @see org.apache.xerces.xs.datatypes.XSDateTime#getTimeZoneMinutes()
       
  1085          */
       
  1086 
       
  1087         @Override
       
  1088         public int getTimeZoneMinutes() {
       
  1089             return timezoneMin;
       
  1090         }
  1032         /* (non-Javadoc)
  1091         /* (non-Javadoc)
  1033          * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue()
  1092          * @see org.apache.xerces.xs.datatypes.XSDateTime#getLexicalValue()
  1034          */
  1093          */
       
  1094 
       
  1095         @Override
  1035         public String getLexicalValue() {
  1096         public String getLexicalValue() {
  1036             return originalValue;
  1097             return originalValue;
  1037         }
  1098         }
  1038         /* (non-Javadoc)
  1099         /* (non-Javadoc)
  1039          * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize()
  1100          * @see org.apache.xerces.xs.datatypes.XSDateTime#normalize()
  1040          */
  1101          */
       
  1102 
       
  1103         @Override
  1041         public XSDateTime normalize() {
  1104         public XSDateTime normalize() {
  1042             if(!normalized) {
  1105             if (!normalized) {
  1043                 DateTimeData dt = (DateTimeData)this.clone();
  1106                 DateTimeData dt = (DateTimeData) this.clone();
  1044                 dt.normalized = true;
  1107                 dt.normalized = true;
  1045                 return dt;
  1108                 return dt;
  1046             }
  1109             }
  1047             return this;
  1110             return this;
  1048         }
  1111         }
  1049         /* (non-Javadoc)
  1112         /* (non-Javadoc)
  1050          * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized()
  1113          * @see org.apache.xerces.xs.datatypes.XSDateTime#isNormalized()
  1051          */
  1114          */
       
  1115 
       
  1116         @Override
  1052         public boolean isNormalized() {
  1117         public boolean isNormalized() {
  1053             return normalized;
  1118             return normalized;
  1054         }
  1119         }
  1055 
  1120 
       
  1121         @Override
  1056         public Object clone() {
  1122         public Object clone() {
  1057             DateTimeData dt = new DateTimeData(this.year, this.month, this.day, this.hour,
  1123             DateTimeData dt = new DateTimeData(this.year, this.month, this.day, this.hour,
  1058                         this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type);
  1124                     this.minute, this.second, this.utc, this.originalValue, this.normalized, this.type);
  1059             dt.canonical = this.canonical;
  1125             dt.canonical = this.canonical;
  1060             dt.position = position;
  1126             dt.position = position;
  1061             dt.timezoneHr = this.timezoneHr;
  1127             dt.timezoneHr = this.timezoneHr;
  1062             dt.timezoneMin = this.timezoneMin;
  1128             dt.timezoneMin = this.timezoneMin;
  1063             dt.unNormYear = this.unNormYear;
  1129             dt.unNormYear = this.unNormYear;
  1070         }
  1136         }
  1071 
  1137 
  1072         /* (non-Javadoc)
  1138         /* (non-Javadoc)
  1073          * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar()
  1139          * @see org.apache.xerces.xs.datatypes.XSDateTime#getXMLGregorianCalendar()
  1074          */
  1140          */
       
  1141         @Override
  1075         public XMLGregorianCalendar getXMLGregorianCalendar() {
  1142         public XMLGregorianCalendar getXMLGregorianCalendar() {
  1076             return type.getXMLGregorianCalendar(this);
  1143             return type.getXMLGregorianCalendar(this);
  1077         }
  1144         }
  1078         /* (non-Javadoc)
  1145         /* (non-Javadoc)
  1079          * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration()
  1146          * @see org.apache.xerces.xs.datatypes.XSDateTime#getDuration()
  1080          */
  1147          */
       
  1148 
       
  1149         @Override
  1081         public Duration getDuration() {
  1150         public Duration getDuration() {
  1082             return type.getDuration(this);
  1151             return type.getDuration(this);
  1083         }
  1152         }
  1084         }
  1153     }
  1085 
  1154 
  1086     protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData data) {
  1155     protected XMLGregorianCalendar getXMLGregorianCalendar(DateTimeData data) {
  1087         return null;
  1156         return null;
  1088     }
  1157     }
  1089 
  1158