Index: AbstractDateTimeDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/AbstractDateTimeDV.java,v retrieving revision 1.16 diff -u -r1.16 AbstractDateTimeDV.java --- AbstractDateTimeDV.java 20 Sep 2004 22:51:08 -0000 1.16 +++ AbstractDateTimeDV.java 28 Sep 2004 19:08:41 -0000 @@ -46,10 +46,10 @@ protected final static int hh=0, mm=1; //define constants to be used in assigning default values for - //all date/time excluding duration - protected final static int YEAR=2000; - protected final static int MONTH=01; - protected final static int DAY = 15; + //all date/time excluding duration (specified in XML Schema 1.1) + protected final static int YEAR=1971; + protected final static int MONTH=12; + protected final static int DAY = 31; public short getAllowedFacets(){ return ( XSSimpleTypeDecl.FACET_PATTERN | XSSimpleTypeDecl.FACET_WHITESPACE | XSSimpleTypeDecl.FACET_ENUMERATION |XSSimpleTypeDecl.FACET_MAXINCLUSIVE |XSSimpleTypeDecl.FACET_MININCLUSIVE | XSSimpleTypeDecl.FACET_MAXEXCLUSIVE | XSSimpleTypeDecl.FACET_MINEXCLUSIVE ); @@ -57,134 +57,108 @@ // the parameters are in compiled form (from getActualValue) public int compare (Object value1, Object value2) { - return compareDates(((DateTimeData)value1), - ((DateTimeData)value2), true); + if (this instanceof DurationDV) { + return ((DurationDV)this).compareDates(((DateTimeData)value1), ((DateTimeData)value2), true); + } + + //date/time datatypes (except for duration types) are compared using their timeOnTimeline values + return compareTimeOnTimeline((DateTimeData)value1, (DateTimeData)value2); + }//compare() - - /** - * Compare algorithm described in dateDime (3.2.7). - * Duration datatype overwrites this method - * - * @param date1 normalized date representation of the first value - * @param date2 normalized date representation of the second value - * @param strict - * @return less, greater, less_equal, greater_equal, equal - */ - protected short compareDates(DateTimeData date1, DateTimeData date2, boolean strict) { - if (date1.utc == date2.utc) { - return compareOrder(date1, date2); - } - short c1, c2; - - DateTimeData tempDate = new DateTimeData(this); - int[] timeZone = new int[2]; - - if ( date1.utc=='Z' ) { - - //compare date1<=date1<=(date2 with time zone -14) - // - cloneDate(date2, tempDate); //clones date1 value to global temporary storage: fTempDate - timeZone[hh]=14; - timeZone[mm]=0; - tempDate.utc='+'; - normalize(tempDate, timeZone); - c1 = compareOrder(date1, tempDate); - if (c1 == LESS_THAN) - return c1; - - //compare date1>=(date2 with time zone +14) - // - cloneDate(date2, tempDate); //clones date1 value to global temporary storage: tempDate - timeZone[hh]=14; - timeZone[mm]=0; - tempDate.utc='-'; - normalize(tempDate, timeZone); - c2 = compareOrder(date1, tempDate); - if (c2 == GREATER_THAN) - return c2; - - return INDETERMINATE; - } - else if ( date2.utc=='Z' ) { - - //compare (date1 with time zone -14)<=date2 - // - cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate - timeZone[hh]=14; - timeZone[mm]=0; - tempDate.utc='-'; - if (DEBUG) { - System.out.println("tempDate=" + dateToString(tempDate)); - } - normalize(tempDate, timeZone); - c1 = compareOrder(tempDate, date2); - if (DEBUG) { - System.out.println("date=" + dateToString(date2)); - System.out.println("tempDate=" + dateToString(tempDate)); - } - if (c1 == LESS_THAN) - return c1; - - //compare (date1 with time zone +14)<=date2 - // - cloneDate(date1, tempDate); //clones date1 value to global temporary storage: tempDate - timeZone[hh]=14; - timeZone[mm]=0; - tempDate.utc='+'; - normalize(tempDate, timeZone); - c2 = compareOrder(tempDate, date2); - if (DEBUG) { - System.out.println("tempDate=" + dateToString(tempDate)); - } - if (c2 == GREATER_THAN) - return c2; - - return INDETERMINATE; - } - return INDETERMINATE; - + + + /** + * XML Schema 1.1 (and also used to compare Schema 1.0 date/time values) + * Compare timeOnTimeline values - discussed in Schema 1.1 - 3.2.8.4 Order relation on dateTime + * + * @param date1 normalized date representation of the first value + * @param date2 normalized date representation of the second value + * @return INDETERMINATE if the order relationship between date1 and date2 is indeterminate. + * EQUAL if the order relation between date1 and date2 is EQUAL. + * LESS_THAN if date1 is less than date2 and return GREATER_THAN if date1 is greater than date2. + */ + protected int compareTimeOnTimeline(DateTimeData date1, DateTimeData date2) { + + // both do or don't have timezone + if (date1.utc == date2.utc) { + //are timeOnTimeline values equal? + if (date1.timeOnTimeline == date2.timeOnTimeline) { + return EQUAL; + } + return (date1.timeOnTimeline < date2.timeOnTimeline? -1:1); + } + + double difference = date1.timeOnTimeline - date2.timeOnTimeline; + + //if timeOnTimeline values differ by 14 hours or less, incomparable + if (difference <= 50400 && difference >= -50400) + return INDETERMINATE; + + //date1 has timezone; date2 does not + if (date1.utc == 'Z') { + //add timezone -14:00 to date2 + date2.timeOnTimeline+=50400; + } + else { + //add timezone -14:00 to date1 + date1.timeOnTimeline+=50400; + } + + return (date1.timeOnTimeline < date2.timeOnTimeline? -1:1); + + } + + + + /** + * Compute timeOnTimeline value for a DateTimeData structure + * calculate timeOnTimeline algorithm described in Schema 1.1 - E.3 Time on Timeline + * + * @param data normalized date representation + * @return a value dimensioned in seconds computed using the Gregorian algorithm as + * modified for leap-seconds; the timeline origin point, 0001-01-01T00:00:00, is represented by 0 + */ + protected void calcTimeOnTimeline (DateTimeData data) { + double totl; + int yr, da; + + //adjust day value to value needed for algorithm + da = data.day - 1; + + //set values of tempDate's fields to those specified in timeOnTimeline algorithm + //algorithm is based on Schema 1.1 which includes year 0000. If Schema 1.0 is in use + //and date.year is negative, timeOnTimeline value will be off by one year so + //account for this by keeping the yr value the same + if (Constants.SCHEMA_1_1_SUPPORT || data.year > 0 ) { + yr = data.year - 1; + } + else { //SCHEMA 1.0 with a negative year - don't adjust yr value + yr = data.year; + } + + + //year calculation (# of complete years (all taken to be non leap year) * # seconds/year) + totl = (double)yr * 31536000; + + //leap-year days, months and days + + int temp = fQuotient(yr, 400) - fQuotient(yr, 100) + fQuotient(yr, 4); + totl+= (86400 * temp); + + //when computing the total number of days in months less than data.month + // for a given year, we must pass the actual year + totl+= 86400 * NumDaysLessThanMonthFor (yr + 1, data.month); + totl+= 86400 * da; + + //hour, minute and second + totl+= 3600 * data.hour + 60 * data.minute + data.second; + + + data.timeOnTimeline = totl; + } - - /** - * Given normalized values, determines order-relation - * between give date/time objects. - * - * @param date1 date/time object - * @param date2 date/time object - * @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 - */ - protected short compareOrder(DateTimeData date1, DateTimeData date2) { - if (date1.year < date2.year) - return -1; - if (date1.year > date2.year) - return 1; - if (date1.month < date2.month) - return -1; - if (date1.month > date2.month) - return 1; - if (date1.day < date2.day) - return -1; - if (date1.day > date2.day) - return 1; - if (date1.hour < date2.hour) - return -1; - if (date1.hour > date2.hour) - return 1; - if (date1.minute < date2.minute) - return -1; - if (date1.minute > date2.minute) - return 1; - if (date1.second < date2.second) - return -1; - if (date1.second > date2.second) - return 1; - if (date1.utc < date2.utc) - return -1; - if (date1.utc > date2.utc) - return 1; - return 0; - } - + + /** * Parses time hh:mm:ss.sss and time zone if any * @@ -346,6 +320,8 @@ System.out.println("time[hh]="+timeZone[hh] + " time[mm]=" +timeZone[mm]); } } + + /** * Computes index of given char within StringBuffer @@ -580,7 +556,14 @@ date.month=modulo(temp, 1, 13); date.year=date.year+fQuotient(temp, 1, 13); } + + //if Schema 1.0 is in use, year 0000 is not allowed + //if date.month is 1, year must be 0001 + if (!Constants.SCHEMA_1_1_SUPPORT && date.year == 0) { + date.year = (date.month == 1? 1:-1); + } date.utc='Z'; + } @@ -631,6 +614,21 @@ return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); } + + // help function: given a month and a year, returns the total number of days + // in months less than the month argument + private int NumDaysLessThanMonthFor (int year, int month) { + final int [] nonLeapYear = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}; + final int [] LeapYear = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}; + + if (isLeapYear(year)) { + return LeapYear[month - 1]; + } + + return nonLeapYear[month - 1]; + } + + // // help function described in W3C PR Schema [E Adding durations to dateTimes] // @@ -759,7 +757,7 @@ */ static final class DateTimeData { int year, month, day, hour, minute, utc; - double second; + double second, timeOnTimeline; // a pointer to the type that was used go generate this data // note that this is not the actual simple type, but one of the // statically created XXXDV objects, so this won't cause any GC problem. @@ -782,7 +780,7 @@ public boolean equals(Object obj) { if (!(obj instanceof DateTimeData)) return false; - return type.compareDates(this, (DateTimeData)obj, true)==0; + return type.compare(this, (DateTimeData)obj)==0; } public synchronized String toString() { if (canonical == null) { Index: DateTimeDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/DateTimeDV.java,v retrieving revision 1.9 diff -u -r1.9 DateTimeDV.java --- DateTimeDV.java 26 Aug 2004 02:14:40 -0000 1.9 +++ DateTimeDV.java 28 Sep 2004 19:10:15 -0000 @@ -18,6 +18,8 @@ import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; +import org.apache.xerces.impl.Constants; + /** * Validator for datatype (W3C Schema Datatypes) @@ -68,10 +70,14 @@ //REVISIT: do we need SchemaDateTimeException? validateDateTime(date, timeZone); - + if (date.utc!=0 && date.utc!='Z') { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + return date; } Index: DateDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/DateDV.java,v retrieving revision 1.11 diff -u -r1.11 DateDV.java --- DateDV.java 26 Aug 2004 02:14:40 -0000 1.11 +++ DateDV.java 28 Sep 2004 19:11:00 -0000 @@ -17,6 +17,8 @@ package org.apache.xerces.impl.dv.xs; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; +import org.apache.xerces.impl.Constants; + /** * Validator for datatype (W3C Schema datatypes) @@ -49,7 +51,7 @@ DateTimeData date = new DateTimeData(this); int len = str.length(); int[] timeZone = new int[2]; - + int end = getDate(str, 0, len, date); parseTimeZone (str, end, len, date, timeZone); @@ -60,6 +62,10 @@ if (date.utc!=0 && date.utc!='Z') { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + return date; } Index: DayDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/DayDV.java,v retrieving revision 1.9 diff -u -r1.9 DayDV.java --- DayDV.java 26 Aug 2004 02:14:40 -0000 1.9 +++ DayDV.java 28 Sep 2004 19:11:37 -0000 @@ -16,9 +16,11 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; + /** * Validator for datatype (W3C Schema datatypes) * @@ -50,7 +52,7 @@ * @exception SchemaDateTimeException Invalid lexical representation */ protected DateTimeData parse(String str) throws SchemaDateTimeException { - DateTimeData date = new DateTimeData(this); + DateTimeData date = new DateTimeData(this); int len = str.length(); int[] timeZone = new int[2]; @@ -80,6 +82,10 @@ if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + return date; } Index: DurationDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/DurationDV.java,v retrieving revision 1.11 diff -u -r1.11 DurationDV.java --- DurationDV.java 15 Sep 2004 05:12:23 -0000 1.11 +++ DurationDV.java 28 Sep 2004 19:12:08 -0000 @@ -18,6 +18,7 @@ import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; +import org.apache.xerces.impl.dv.xs.AbstractDateTimeDV.DateTimeData; /** * Validator for datatype (W3C Schema Datatypes) @@ -243,6 +244,48 @@ return resultA; } + + /** + * Given normalized values, determines order-relation + * between give date/time objects. + * + * @param date1 date/time object + * @param date2 date/time object + * @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 + */ + private short compareOrder(DateTimeData date1, DateTimeData date2) { + if (date1.year < date2.year) + return -1; + if (date1.year > date2.year) + return 1; + if (date1.month < date2.month) + return -1; + if (date1.month > date2.month) + return 1; + if (date1.day < date2.day) + return -1; + if (date1.day > date2.day) + return 1; + if (date1.hour < date2.hour) + return -1; + if (date1.hour > date2.hour) + return 1; + if (date1.minute < date2.minute) + return -1; + if (date1.minute > date2.minute) + return 1; + if (date1.second < date2.second) + return -1; + if (date1.second > date2.second) + return 1; + if (date1.utc < date2.utc) + return -1; + if (date1.utc > date2.utc) + return 1; + return 0; + } + + private short compareResults(short resultA, short resultB, boolean strict){ if ( resultB == INDETERMINATE ) { Index: MonthDayDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/MonthDayDV.java,v retrieving revision 1.9 diff -u -r1.9 MonthDayDV.java --- MonthDayDV.java 26 Aug 2004 02:14:40 -0000 1.9 +++ MonthDayDV.java 28 Sep 2004 19:12:47 -0000 @@ -16,9 +16,11 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; + /** * Validator for datatype (W3C Schema Datatypes) * @@ -92,6 +94,11 @@ if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + + return date; } Index: MonthDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/MonthDV.java,v retrieving revision 1.11 diff -u -r1.11 MonthDV.java --- MonthDV.java 26 Aug 2004 02:14:40 -0000 1.11 +++ MonthDV.java 28 Sep 2004 19:13:29 -0000 @@ -16,9 +16,11 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; + /** * Validator for datatype (W3C Schema Datatypes) * @@ -58,15 +60,19 @@ int len = str.length(); int[] timeZone = new int[2]; - //set constants - date.year=YEAR; - date.day=DAY; + + if (str.charAt(0)!='-' || str.charAt(1)!='-') { throw new SchemaDateTimeException("Invalid format for gMonth: "+str); } int stop = 4; date.month=parseInt(str,2,stop); + //set constants + date.year=YEAR; + date.day= maxDayInMonthFor(date.year, date.month); + + // REVISIT: allow both --MM and --MM-- now. // need to remove the following 4 lines to disallow --MM-- // when the errata is offically in the rec. @@ -83,12 +89,18 @@ getTimeZone(str, date, sign, len, timeZone); } } + //validate and normalize validateDateTime(date, timeZone); if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + + return date; } Index: TimeDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/TimeDV.java,v retrieving revision 1.9 diff -u -r1.9 TimeDV.java --- TimeDV.java 26 Aug 2004 02:14:40 -0000 1.9 +++ TimeDV.java 28 Sep 2004 19:14:20 -0000 @@ -16,6 +16,7 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; @@ -69,9 +70,14 @@ validateDateTime(date, timeZone); - if ( date.utc!=0 ) { + if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + + return date; } Index: YearDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/YearDV.java,v retrieving revision 1.9 diff -u -r1.9 YearDV.java --- YearDV.java 26 Aug 2004 02:14:41 -0000 1.9 +++ YearDV.java 28 Sep 2004 19:14:47 -0000 @@ -16,9 +16,11 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; + /** * Validator for datatype (W3C Schema Datatypes) * @@ -74,7 +76,7 @@ //initialize values date.month=MONTH; - date.day=1; + date.day=DAY; //validate and normalize validateDateTime(date, timeZone); @@ -82,6 +84,11 @@ if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + + return date; } Index: YearMonthDV.java =================================================================== RCS file: /home/cvspublic/xml-xerces/java/src/org/apache/xerces/impl/dv/xs/YearMonthDV.java,v retrieving revision 1.9 diff -u -r1.9 YearMonthDV.java --- YearMonthDV.java 26 Aug 2004 02:14:41 -0000 1.9 +++ YearMonthDV.java 28 Sep 2004 19:15:21 -0000 @@ -16,9 +16,11 @@ package org.apache.xerces.impl.dv.xs; +import org.apache.xerces.impl.Constants; import org.apache.xerces.impl.dv.InvalidDatatypeValueException; import org.apache.xerces.impl.dv.ValidationContext; + /** * Validator for datatype (W3C Schema Datatypes) * @@ -59,7 +61,7 @@ // get date int end = getYearMonth(str, 0, len, date); - date.day = DAY; + date.day = maxDayInMonthFor(date.year, date.month ); parseTimeZone (str, end, len, date, timeZone); //validate and normalize @@ -69,6 +71,11 @@ if ( date.utc!=0 && date.utc!='Z' ) { normalize(date, timeZone); } + + //setting of timeOnTimeline value + calcTimeOnTimeline(date); + + return date; }