update from Charles Bozeman for date and duration types updated too Daniel

* xmlschemas.c xmlschemastypes.c include/libxml/xmlschemas.h:
  update from Charles Bozeman for date and duration types
* test/schemas/date_0.* test/schemas/dur_0.*
  result/schemas/date_0.* result/schemas/dur_0.*: updated too
Daniel
diff --git a/ChangeLog b/ChangeLog
index 8fa14cf..bff2a75 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Apr  9 13:21:48 CEST 2003 Daniel Veillard <daniel@veillard.com>
+
+	* xmlschemas.c xmlschemastypes.c include/libxml/xmlschemas.h:
+	  update from Charles Bozeman for date and duration types
+	* test/schemas/date_0.* test/schemas/dur_0.*
+	  result/schemas/date_0.* result/schemas/dur_0.*: updated too
+
 Mon Apr  7 12:19:26 CEST 2003 Daniel Veillard <daniel@veillard.com>
 
 	* tree.c valid.c xpath.c include/libxml/tree.h include/libxml/valid.h:
diff --git a/include/libxml/xmlschemas.h b/include/libxml/xmlschemas.h
index 081d8a2..1fc525a 100644
--- a/include/libxml/xmlschemas.h
+++ b/include/libxml/xmlschemas.h
@@ -45,6 +45,7 @@
     XML_SCHEMAS_ERR_ATTRUNKNOWN,
     XML_SCHEMAS_ERR_ATTRINVALID,
     XML_SCHEMAS_ERR_VALUE,
+    XML_SCHEMAS_ERR_FACET,
     XML_SCHEMAS_ERR_,
     XML_SCHEMAS_ERR_XXX
 } xmlSchemaValidError;
diff --git a/result/schemas/date_0_0.err b/result/schemas/date_0_0.err
index 6a9efe5..7d8d225 100644
--- a/result/schemas/date_0_0.err
+++ b/result/schemas/date_0_0.err
@@ -17,13 +17,13 @@
 Type of restriction 19 : ./test/schemas/date_0.xsd:72 :empty
 Type of simpletype8 : ./test/schemas/date_0.xsd:30 :simple
 Type of simpletype18 : ./test/schemas/date_0.xsd:71 :simple
-Type of holidays : ./test/schemas/date_0.xsd:98 :simple
+Type of holidays : ./test/schemas/date_0.xsd:99 :simple
 Type of restriction 11 : ./test/schemas/date_0.xsd:39 :empty
 Type of simpletype16 : ./test/schemas/date_0.xsd:63 :simple
 Type of sequence 2 : ./test/schemas/date_0.xsd:10 :elements
 Type of choice 3 : ./test/schemas/date_0.xsd:11 :elements
 Type of restriction 17 : ./test/schemas/date_0.xsd:64 :empty
-Type of restriction 24 : ./test/schemas/date_0.xsd:102 :empty
+Type of restriction 24 : ./test/schemas/date_0.xsd:103 :empty
 Building content model for date
 xmlSchemaValidateCallback: time, time, time
 xmlSchemaValidateCallback: time1, time1, time1
@@ -40,10 +40,11 @@
 xmlSchemaValidateCallback: hol, hol, hol
 xmlSchemaValidateCallback: hol, hol, hol
 xmlSchemaValidateCallback: hol, hol, hol
-xmlSchemaValidateCallback: hol, hol, hol
 xmlSchemaValidateCallback: year1, year1, year1
 xmlSchemaValidateCallback: yearmon1, yearmon1, yearmon1
 xmlSchemaValidateCallback: mon1, mon1, mon1
 xmlSchemaValidateCallback: day1, day1, day1
+xmlSchemaValidateCallback: monthday1, monthday1, monthday1
+xmlSchemaValidateCallback: monthday1, monthday1, monthday1
 xmlSchemaValidateCallback: dt2, dt2, dt2
 Element date content check succeeded
diff --git a/result/schemas/dur_0_0.err b/result/schemas/dur_0_0.err
index 1aa3a82..d2d3138 100644
--- a/result/schemas/dur_0_0.err
+++ b/result/schemas/dur_0_0.err
@@ -1,17 +1,3 @@
-compilation error: file ./test/schemas/dur_0.xsd line 67 element minOccurs
-Restriction restriction 16 has unexpected content
-compilation error
-Schemas: element year1 have both type and subtype
-compilation error
-Schemas: element second2 have both type and subtype
-compilation error
-Schemas: element month1 have both type and subtype
-compilation error
-Schemas: element year2 have both type and subtype
-compilation error
-Schemas: element second1 have both type and subtype
-compilation error
-Schemas: element month2 have both type and subtype
 Type of restriction 7 : ./test/schemas/dur_0.xsd:22 :empty
 Type of restriction 9 : ./test/schemas/dur_0.xsd:30 :empty
 Type of simpletype14 : ./test/schemas/dur_0.xsd:54 :simple
diff --git a/test/schemas/date_0.xml b/test/schemas/date_0.xml
index 3099d5e..fbef1e5 100644
--- a/test/schemas/date_0.xml
+++ b/test/schemas/date_0.xml
@@ -2,23 +2,24 @@
 <date>
   <time>01:02:59</time>
   <time1>01:02:59</time1>
-  <time2>12:59:59</time2>
-  <time2>11:59:59.01</time2>
+  <time2>12:59:59.0001</time2>
+  <time2>12:00:00</time2>
+  <date1>1996-05-20</date1>
   <date1>2002-05-18</date1>
-  <date1>2002-05-19</date1>
   <date2>1996-05-19Z</date2>
-  <date2>1996-05</date2>
+  <date2>2002-05-19Z</date2>
   <date1>2002-05-18Z</date1>
   <date1>2000-05-18Z</date1>
-  <dt1>2000-05-18</dt1>
+  <dt1>2000-05-18T00:00:00</dt1>
   <dt2>2002-05-19T21:30:00.99</dt2>
   <hol>--01-01</hol>
   <hol>--07-04</hol>
   <hol>--12-25</hol>
-  <hol>--05-19</hol>
   <year1>2002</year1>
   <yearmon1>2002-05</yearmon1>
-  <mon1>--05--</mon1>
+  <mon1>--05Z</mon1>
   <day1>---31</day1>
+  <monthday1>--02-28Z</monthday1>
+  <monthday1>--12-31-06:00</monthday1>
   <dt2>2003-04-30T18:00:00-06:00</dt2>
 </date>
diff --git a/test/schemas/date_0.xsd b/test/schemas/date_0.xsd
index 8784212..7247394 100644
--- a/test/schemas/date_0.xsd
+++ b/test/schemas/date_0.xsd
@@ -78,19 +78,20 @@
           <xsd:element name="mon1">
             <xsd:simpleType>
               <xsd:restriction base="xsd:gMonth">
-                <xsd:maxInclusive value="--01Z"/>
-                <xsd:minInclusive value="--05Z"/>
+                <xsd:minInclusive value="--01Z"/>
+                <xsd:maxInclusive value="--05Z"/>
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
           <xsd:element name="day1">
             <xsd:simpleType>
               <xsd:restriction base="xsd:gDay">
-                <xsd:maxInclusive value="---28"/>
-                <xsd:minInclusive value="---31"/>
+                <xsd:minInclusive value="---28"/>
+                <xsd:maxInclusive value="---31"/>
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
+          <xsd:element name="monthday1" type="xsd:gMonthDay"/>
         </xsd:choice>
       </xsd:sequence>
     </xsd:complexType>
diff --git a/test/schemas/dur_0.xml b/test/schemas/dur_0.xml
index 9e3d2fa..be84943 100644
--- a/test/schemas/dur_0.xml
+++ b/test/schemas/dur_0.xml
@@ -6,8 +6,8 @@
   <month1>P0Y27D</month1>
   <month1>P27DT23H59M59S</month1>
   <month2>P0Y</month2>
-  <year1>P366DT23H59M59S</year1>
-  <year1>P12M</year1>
+  <year1>P367DT23H59M59S</year1>
+  <year1>P13M</year1>
   <year2>P12M</year2>
-  <month3>PT86400S</month3>
+  <month3>PT86399S</month3>
 </duration>
diff --git a/test/schemas/dur_0.xsd b/test/schemas/dur_0.xsd
index 5d33fba..374c038 100644
--- a/test/schemas/dur_0.xsd
+++ b/test/schemas/dur_0.xsd
@@ -9,7 +9,7 @@
     <xsd:complexType>
       <xsd:sequence>
         <xsd:choice minOccurs="1" maxOccurs="unbounded">
-          <xsd:element name="second1" type="xsd:duration">
+          <xsd:element name="second1">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxExclusive value="PT1S"/>
@@ -17,7 +17,7 @@
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
-          <xsd:element name="second2" type="xsd:duration">
+          <xsd:element name="second2">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxInclusive value="PT1S"/>
@@ -25,7 +25,7 @@
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
-          <xsd:element name="month1" type="xsd:duration">
+          <xsd:element name="month1">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxExclusive value="P1M"/>
@@ -33,7 +33,7 @@
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
-          <xsd:element name="month2" type="xsd:duration">
+          <xsd:element name="month2">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxInclusive value="P1M"/>
@@ -42,7 +42,7 @@
             </xsd:simpleType>
           </xsd:element>
           <xsd:element name="month3" type="MSD"/>
-          <xsd:element name="year1" type="xsd:duration">
+          <xsd:element name="year1">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxExclusive value="P2Y"/>
@@ -50,7 +50,7 @@
               </xsd:restriction>
             </xsd:simpleType>
           </xsd:element>
-          <xsd:element name="year2" type="xsd:duration">
+          <xsd:element name="year2">
             <xsd:simpleType>
               <xsd:restriction base="xsd:duration">
                 <xsd:maxInclusive value="P2Y"/>
@@ -64,7 +64,6 @@
   </xsd:element>
   <xsd:simpleType name="MSD">
     <xsd:restriction base="xsd:duration">
-      <xsd:minOccurs value="0"/>
       <xsd:maxExclusive value="PT24H"/>
       <xsd:minExclusive value="-PT24H"/>
     </xsd:restriction>
diff --git a/xmlschemas.c b/xmlschemas.c
index 6c9e2f4..55cdef5 100644
--- a/xmlschemas.c
+++ b/xmlschemas.c
@@ -4167,6 +4167,101 @@
     ctxt->userData = ctx;
 }
 
+/**
+ * xmlSchemaFacetTypeToString:
+ * @type:  the facet type
+ *
+ * Convert the xmlSchemaTypeType to a char string.
+ *
+ * Returns the char string representation of the facet type if the
+ *     type is a facet and an "Internal Error" string otherwise.
+ */
+static const char *
+xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
+{
+    switch (type) {
+        case XML_SCHEMA_FACET_PATTERN:
+            return ("pattern");
+	case XML_SCHEMA_FACET_MAXEXCLUSIVE:
+            return ("maxExclusive");
+	case XML_SCHEMA_FACET_MAXINCLUSIVE:
+            return ("maxInclusive");
+	case XML_SCHEMA_FACET_MINEXCLUSIVE:
+            return ("minExclusive");
+	case XML_SCHEMA_FACET_MININCLUSIVE:
+            return ("minInclusive");
+	case XML_SCHEMA_FACET_WHITESPACE:
+            return ("whiteSpace");
+	case XML_SCHEMA_FACET_ENUMERATION:
+            return ("enumeration");
+	case XML_SCHEMA_FACET_LENGTH:
+            return ("length");
+	case XML_SCHEMA_FACET_MAXLENGTH:
+            return ("maxLength");
+	case XML_SCHEMA_FACET_MINLENGTH:
+            return ("minLength");
+	case XML_SCHEMA_FACET_TOTALDIGITS:
+            return ("totalDigits");
+	case XML_SCHEMA_FACET_FRACTIONDIGITS:
+            return ("fractionDigits");
+        default:
+            break;
+    }
+    return ("Internal Error");
+}
+
+/**
+ * xmlSchemaValidateFacets:
+ * @ctxt:  a schema validation context
+ * @base:  the base type
+ * @facets:  the list of facets to check
+ * @value:  the lexical repr of the value to validate
+ * @val:  the precomputed value
+ *
+ * Check a value against all facet conditions
+ *
+ * Returns 0 if the element is schemas valid, a positive error code
+ *     number otherwise and -1 in case of internal or API error.
+ */
+static int
+xmlSchemaValidateFacets(xmlSchemaValidCtxtPtr ctxt, 
+			     xmlSchemaTypePtr base,
+	                    xmlSchemaFacetPtr facets,
+	                             xmlChar *value) {
+    int ret = 0;
+    int tmp = 0;
+    xmlSchemaTypeType type;
+    xmlSchemaFacetPtr facet = facets;
+
+    while (facet != NULL) {
+        type = facet->type;
+        if (type == XML_SCHEMA_FACET_ENUMERATION) {
+	    tmp = 1;
+
+	    while (facet != NULL) {
+		tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
+		if (tmp == 0) {
+                    return 0;
+		}
+		facet = facet->next;
+	    }
+        } else
+	    tmp = xmlSchemaValidateFacet(base, facet, value, ctxt->value);
+
+        if (tmp != 0) {
+            ret = tmp;
+            if (ctxt->error != NULL)
+	        ctxt->error(ctxt->userData,
+	             "Failed to validate type with facet %s\n",
+                     xmlSchemaFacetTypeToString(type));
+	    ctxt->err = XML_SCHEMAS_ERR_FACET;
+        }
+        if (facet != NULL)
+            facet = facet->next;
+    }
+    return (ret);
+}
+
 /************************************************************************
  * 									*
  * 			Simple type validation				*
@@ -4203,10 +4298,15 @@
 	    ctxt->value = NULL;
 	}
 	ret = xmlSchemaValidatePredefinedType(type, value, &(ctxt->value));
+        if (ret != 0) {
+            if (ctxt->error != NULL)
+	        ctxt->error(ctxt->userData,
+		        "Failed to validate basic type %s\n", type->name);
+	    ctxt->err = XML_SCHEMAS_ERR_VALUE;
+        }
     } else if (type->type == XML_SCHEMA_TYPE_RESTRICTION) {
 	xmlSchemaTypePtr base;
 	xmlSchemaFacetPtr facet;
-	int tmp;
 
 	base = type->baseType;
 	if (base != NULL) {
@@ -4220,29 +4320,7 @@
 	if (ctxt->schema != NULL) {
 	    if (ret == 0) {
 		facet = type->facets;
-		if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) &&
-		    (facet != NULL) &&
-		    (facet->type == XML_SCHEMA_FACET_ENUMERATION)) {
-		    while (facet != NULL) {
-			ret = 1;
-
-			tmp = xmlSchemaValidateFacet(base, facet, value,
-						     ctxt->value);
-			if (tmp == 0) {
-			    ret = 0;
-			    break;
-			}
-			facet = facet->next;
-		    }
-		} else {
-		    while (facet != NULL) {
-			tmp = xmlSchemaValidateFacet(base, facet, value,
-						     ctxt->value);
-			if (tmp != 0)
-			    ret = tmp;
-			facet = facet->next;
-		    }
-		}
+                ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
 	    }
 	}
     } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
@@ -4391,7 +4469,7 @@
     xmlNodePtr child;
     xmlSchemaTypePtr type, base;
     xmlChar *value;
-    int ret = 0, tmp;
+    int ret = 0;
 
     child = ctxt->node;
     type = ctxt->type;
@@ -4413,13 +4491,7 @@
 	    }
 	    if (ret == 0) {
 		facet = type->facets;
-		while (facet != NULL) {
-		    tmp = xmlSchemaValidateFacet(base, facet, value,
-			                         ctxt->value);
-		    if (tmp != 0)
-			ret = tmp;
-		    facet = facet->next;
-		}
+                ret = xmlSchemaValidateFacets(ctxt, base, facet, value);
 	    }
 	    break;
 	}
@@ -4853,9 +4925,10 @@
     if (value != NULL)
 	xmlFree(value);
     if (ret != 0) {
-	ctxt->error(ctxt->userData,
-		"Element %s: failed to validate basic type %s\n",
-		    node->name, type->name);
+        if (ctxt->error != NULL)
+	    ctxt->error(ctxt->userData,
+		    "Element %s: failed to validate basic type %s\n",
+		        node->name, type->name);
 	ctxt->err = XML_SCHEMAS_ERR_VALUE;
     }
     return(ret);
diff --git a/xmlschemastypes.c b/xmlschemastypes.c
index 4a659a3..29b069b 100644
--- a/xmlschemastypes.c
+++ b/xmlschemastypes.c
@@ -903,19 +903,42 @@
 	if (ret != 0)
 	    goto error;
 
-	if (*cur != '-') {
-	    RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
-	    goto error;
-	}
-	if (type == XML_SCHEMAS_GMONTH)
-	    goto error;
-	/* it should be an xs:gMonthDay */
-	cur++;
-	ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
-	if (ret != 0)
-	    goto error;
+        /*
+         * a '-' char could indicate this type is xs:gMonthDay or
+         * a negative time zone offset. Check for xs:gMonthDay first.
+         * Also the first three char's of a negative tzo (-MM:SS) can
+         * appear to be a valid day; so even if the day portion
+         * of the xs:gMonthDay verifies, we must insure it was not
+         * a tzo.
+         */
+        if (*cur == '-') {
+            const xmlChar *rewnd = cur;
+            cur++;
 
-	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
+  	    ret = _xmlSchemaParseGDay(&(dt->value.date), &cur);
+            if ((ret == 0) && ((*cur == 0) || (*cur != ':'))) {
+
+                /*
+                 * we can use the VALID_MDAY macro to validate the month
+                 * and day because the leap year test will flag year zero
+                 * as a leap year (even though zero is an invalid year).
+                 */
+                if (VALID_MDAY((&(dt->value.date)))) {
+
+	            RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTHDAY);
+
+                    goto error;
+                }
+            }
+
+            /*
+             * not xs:gMonthDay so rewind and check if just xs:gMonth
+             * with an optional time zone.
+             */
+            cur = rewnd;
+        }
+
+	RETURN_TYPE_IF_VALID(XML_SCHEMAS_GMONTH);
 
 	goto error;
     }
@@ -981,9 +1004,37 @@
     dt->type = XML_SCHEMAS_DATETIME;
 
 done:
-#if 0
-    if ((type != XML_SCHEMAS_UNKNOWN) && (type != XML_SCHEMAS_DATETIME))
-	goto error;
+#if 1
+    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type))
+        goto error;
+#else
+    /*
+     * insure the parsed type is equal to or less significant (right
+     * truncated) than the desired type.
+     */
+    if ((type != XML_SCHEMAS_UNKNOWN) && (type != dt->type)) {
+
+        /* time only matches time */
+        if ((type == XML_SCHEMAS_TIME) && (dt->type == XML_SCHEMAS_TIME))
+            goto error;
+
+        if ((type == XML_SCHEMAS_DATETIME) &&
+            ((dt->type != XML_SCHEMAS_DATE) ||
+             (dt->type != XML_SCHEMAS_GYEARMONTH) ||
+             (dt->type != XML_SCHEMAS_GYEAR)))
+            goto error;
+
+        if ((type == XML_SCHEMAS_DATE) &&
+            ((dt->type != XML_SCHEMAS_GYEAR) ||
+             (dt->type != XML_SCHEMAS_GYEARMONTH)))
+            goto error;
+
+        if ((type == XML_SCHEMAS_GYEARMONTH) && (dt->type != XML_SCHEMAS_GYEAR))
+            goto error;
+
+        if ((type == XML_SCHEMAS_GMONTHDAY) && (dt->type != XML_SCHEMAS_GMONTH))
+            goto error;
+    }
 #endif
 
     if (val != NULL)
@@ -1018,6 +1069,10 @@
     xmlSchemaValPtr dur;
     int isneg = 0;
     unsigned int seq = 0;
+    double         num;
+    int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
+    const xmlChar  desig[]  = {'Y', 'M', 'D', 'H', 'M', 'S'};
+    const double   multi[]  = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
 
     if (duration == NULL)
 	return -1;
@@ -1039,10 +1094,6 @@
 	return -1;
 
     while (*cur != 0) {
-        double         num;
-        int            num_type = 0;  /* -1 = invalid, 0 = int, 1 = floating */
-        const xmlChar  desig[] = {'Y', 'M', 'D', 'H', 'M', 'S'};
-        const double   multi[] = { 0.0, 0.0, 86400.0, 3600.0, 60.0, 1.0, 0.0};
 
         /* input string should be empty or invalid date/time item */
         if (seq >= sizeof(desig))
@@ -1328,7 +1379,7 @@
 	               xmlSchemaValPtr *val, xmlNodePtr node, int flags) {
     xmlSchemaValPtr v;
     xmlChar *norm = NULL;
-    int ret;
+    int ret = 0;
 
     if (xmlSchemaTypesInitialized == 0)
 	return(-1);