You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xerces.apache.org by pe...@apache.org on 2001/11/07 20:16:04 UTC

cvs commit: xml-xerces/c/src/util XMLDateTime.hpp XMLDateTime.cpp Makefile.in

peiyongz    01/11/07 11:16:04

  Modified:    c/src/util Makefile.in
  Added:       c/src/util XMLDateTime.hpp XMLDateTime.cpp
  Log:
  DateTime Port
  
  Revision  Changes    Path
  1.49      +5 -0      xml-xerces/c/src/util/Makefile.in
  
  Index: Makefile.in
  ===================================================================
  RCS file: /home/cvs/xml-xerces/c/src/util/Makefile.in,v
  retrieving revision 1.48
  retrieving revision 1.49
  diff -u -r1.48 -r1.49
  --- Makefile.in	2001/10/23 23:09:32	1.48
  +++ Makefile.in	2001/11/07 19:16:03	1.49
  @@ -55,6 +55,9 @@
   #
   #
   # $Log: Makefile.in,v $
  +# Revision 1.49  2001/11/07 19:16:03  peiyongz
  +# DateTime Port
  +#
   # Revision 1.48  2001/10/23 23:09:32  peiyongz
   # [Bug#880] patch to PlatformUtils:init()/term() and related. from Mark Weaver
   #
  @@ -363,6 +366,7 @@
       XMLBigDecimal.hpp \
       XMLBigInteger.hpp \
       XMLDouble.hpp \
  +    XMLDateTime.hpp \
       XMLChTranscoder.hpp \
       XMLInteger.hpp \
       XMLIBM1140Transcoder.hpp \
  @@ -431,6 +435,7 @@
       XMLBigDecimal.$(TO) \
       XMLBigInteger.$(TO) \
       XMLDouble.$(TO) \
  +    XMLDateTime.$(TO) \
       XMLChTranscoder.$(TO) \
       XMLIBM1140Transcoder.$(TO) \
       XMLEBCDICTranscoder.$(TO) \
  
  
  
  1.1                  xml-xerces/c/src/util/XMLDateTime.hpp
  
  Index: XMLDateTime.hpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 2001, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Id: XMLDateTime.hpp,v 1.1 2001/11/07 19:16:03 peiyongz Exp $
   * $Log: XMLDateTime.hpp,v $
   * Revision 1.1  2001/11/07 19:16:03  peiyongz
   * DateTime Port
   *
   */
  
  #ifndef XML_DATETIME_HPP
  #define XML_DATETIME_HPP
  
  #include <util/XercesDefs.hpp>
  #include <util/XMLNumber.hpp>
  #include <util/XMLString.hpp>
  #include <util/XMLUniDefs.hpp>
  #include <util/RuntimeException.hpp>
  
  class XMLUTIL_EXPORT XMLDateTime : public XMLNumber
  {
  public:
  
      // to be moved to XMLNumber
      enum 
      {
          LESS_THAN     = -1,
          EQUAL         = 0,
          GREATER_THAN  = 1,
          INDETERMINATE = 2
      };
  
      // -----------------------------------------------------------------------
      // ctors and dtor
      // -----------------------------------------------------------------------
  
      XMLDateTime();
  
      XMLDateTime(const XMLCh* const);
  
      ~XMLDateTime();
  
      inline void           setBuffer(const XMLCh* const);
  
      // -----------------------------------------------------------------------
      // Copy ctor and Assignment operators
      // -----------------------------------------------------------------------
  
      XMLDateTime(const XMLDateTime&);
  
      XMLDateTime&          operator=(const XMLDateTime&);   
  
      // -----------------------------------------------------------------------
      // Implementation of Abstract Interface
      // -----------------------------------------------------------------------
  
      virtual XMLCh*        toString() const;
  
      virtual int           getSign() const;
  
      // -----------------------------------------------------------------------
      // parsers
      // -----------------------------------------------------------------------
  
      void                  parseDateTime();       //DateTime
  
      void                  parseDate();           //Date
  
      void                  parseTime();           //Time
  
      void                  parseDay();            //gDay
  
      void                  parseMonth();          //gMonth
  
      void                  parseYear();           //gYear
  
      void                  parseMonthDay();       //gMonthDay
  
      void                  parseYearMonth();      //gYearMonth
  
      void                  parseDuration();       //duration
  
      // -----------------------------------------------------------------------
      // Comparison 
      // -----------------------------------------------------------------------
      static int            compare(const XMLDateTime* const 
                                  , const XMLDateTime* const);
  
      static int            compare(const XMLDateTime* const 
                                  , const XMLDateTime* const
                                  , bool                    );
  
      static int            compareOrder(const XMLDateTime* const
                                       , const XMLDateTime* const);
  
  private:
  
      // -----------------------------------------------------------------------
      // Constant data
      // -----------------------------------------------------------------------
  	//
  	enum valueIndex
      {
          CentYear   = 0,
          Month      = 1,
          Day        = 2,
          Hour       = 3,
          Minute     = 4,
          Second     = 5,
          MiliSecond = 6,
          utc        = 7,
          TOTAL_SIZE = 8   
      };
  
      enum timezoneIndex 
      {
          hh = 0,
          mm = 1,
          TIMEZONE_ARRAYSIZE = 2
      };
  
      enum utcType 
      {
          UTC_UNKNOWN = 0,
          UTC_STD = 1,          // set in parse() or normalize()
          UTC_POS = 2,          // set in parse()
          UTC_NEG = 3           // set in parse()
      };
  
      static const int      DATETIMES[4][TOTAL_SIZE];
  
      // -----------------------------------------------------------------------
      // Comparison 
      // -----------------------------------------------------------------------
      static int            compareResult(short 
                                        , short 
                                        , bool);
  
      static void           addDuration(XMLDateTime*             pDuration
                                      , const XMLDateTime* const pBaseDate
                                      , int                      index);
  
  
      static int            compareResult(const XMLDateTime* const
                                        , const XMLDateTime* const
                                        , bool
                                        , int);
  
      static inline int     getRetVal(int, int);
  
      // -----------------------------------------------------------------------
      // helper
      // -----------------------------------------------------------------------
  
      inline  void          reset();
  
      inline  void          assertBuffer()               const;
     
      inline  void          copy(const XMLDateTime&);
  
      // allow multiple parsing
      inline  void          initParser();
  
      inline  bool          isNormalized()               const;
  
      // -----------------------------------------------------------------------
      // scaners 
      // -----------------------------------------------------------------------
  
      void                  getDate();
  
      void                  getTime();
  
      void                  getYearMonth();
  
      void                  getTimeZone(const int);
  
      void                  parseTimeZone();
  
      // -----------------------------------------------------------------------
      // locator and converter
      // -----------------------------------------------------------------------
  
      int                   findUTCSign(int start);
  
      int                   indexOf(const int start
                                  , const int end
                                  , const XMLCh ch)     const;
  
      int                   parseInt(const int start
                                   , const int end)     const;
  
      int                   parseIntYear(const int end) const;
  
      // -----------------------------------------------------------------------
      // validator and normalizer
      // -----------------------------------------------------------------------
  
      void                  validateDateTime()          const;
  
      void                  normalize();
  
      // -----------------------------------------------------------------------
      // Unimplemented operator ==
      // -----------------------------------------------------------------------
  	bool operator==(const XMLDateTime& toCompare) const;
  
  
      // -----------------------------------------------------------------------
      //  Private data members
      //
      //     fValue[]
      //          object representation of date time.
      //
      //     fTimeZone[]
      //          temporary storage for normalization
      //
      //     fStart, fEnd
      //          pointers to the portion of fBuffer being parsed
      //
      //     fBuffer
      //          raw data to be parsed, own it.
      //
      // -----------------------------------------------------------------------
  
      int          fValue[TOTAL_SIZE];    
      int          fTimeZone[TIMEZONE_ARRAYSIZE];
      int          fStart;
      int          fEnd;
  
      XMLCh*       fBuffer;
  
  };
  
  void XMLDateTime::setBuffer(const XMLCh* const aString)
  {
      reset();
      fBuffer = XMLString::replicate(aString);
      fEnd    = XMLString::stringLen(fBuffer);
  
  }
  
  void XMLDateTime::reset()
  {
      for ( int i=0; i < TOTAL_SIZE; i++ ) 
          fValue[i] = 0;
  
      fTimeZone[hh] = fTimeZone[mm] = 0;
      fStart = fEnd = 0;
  
      if (fBuffer)
      {
          delete[] fBuffer;
          fBuffer = 0;
      }
  
  }
  
  void XMLDateTime::copy(const XMLDateTime& rhs)
  {
      for ( int i = 0; i < TOTAL_SIZE; i++ ) 
          fValue[i] = rhs.fValue[i];
  
      fTimeZone[hh] = rhs.fTimeZone[hh];
      fTimeZone[mm] = rhs.fTimeZone[mm];
      fStart = rhs.fStart;
      fEnd   = rhs.fEnd;
  
      if (fBuffer)
      {
          delete[] fBuffer;
          fBuffer = 0;
      }
  
      if (rhs.fBuffer)
          fBuffer = XMLString::replicate(rhs.fBuffer);
  
  }
  
  void XMLDateTime::assertBuffer() const
  {
      if ( ( !fBuffer )            || 
           ( fBuffer[0] == chNull ) )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //" buffer not set properly"
      }
  
  }
  
  void XMLDateTime::initParser()
  {
      assertBuffer();
      fStart = 0;   // to ensure scan from the very first beginning
                    // in case the pointer is updated accidentally by someone else.
  }
  
  bool XMLDateTime::isNormalized() const
  {
      return ( fValue[utc] == UTC_STD ? true : false );
  }
  
  int XMLDateTime::getRetVal(int c1, int c2)
  {
      if ((c1 == LESS_THAN    && c2 == GREATER_THAN) ||
          (c1 == GREATER_THAN && c2 == LESS_THAN)      ) 
      {
          return INDETERMINATE; 
      }
  
      return ( c1 != INDETERMINATE ) ? c1 : c2;
  }
  
  #endif
  
  
  
  1.1                  xml-xerces/c/src/util/XMLDateTime.cpp
  
  Index: XMLDateTime.cpp
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Xerces" and "Apache Software Foundation" must
   *    not be used to endorse or promote products derived from this
   *    software without prior written permission. For written
   *    permission, please contact apache\@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    nor may "Apache" appear in their name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation, and was
   * originally based on software copyright (c) 2001, International
   * Business Machines, Inc., http://www.ibm.com .  For more information
   * on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  /*
   * $Id: XMLDateTime.cpp,v 1.1 2001/11/07 19:16:03 peiyongz Exp $
   * $Log: XMLDateTime.cpp,v $
   * Revision 1.1  2001/11/07 19:16:03  peiyongz
   * DateTime Port
   *
   *
   */
  
  // ---------------------------------------------------------------------------
  //  Includes
  // ---------------------------------------------------------------------------
  #include <stdlib.h>
  #include <util/XMLDateTime.hpp>
  #include <util/XMLString.hpp>
  #include <util/XMLUni.hpp>
  #include <util/Janitor.hpp>
  
  //
  // constants used to process raw data (fBuffer)
  //
  // [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}['Z']
  //                                [{+|-}hh:mm']
  //                                  
  
  static const XMLCh DURATION_STARTER     = chLatin_P;              // 'P'
  static const XMLCh DURATION_Y           = chLatin_Y;              // 'Y'
  static const XMLCh DURATION_M           = chLatin_M;              // 'M'
  static const XMLCh DURATION_D           = chLatin_D;              // 'D'
  static const XMLCh DURATION_H           = chLatin_H;              // 'H'
  static const XMLCh DURATION_S           = chLatin_S;              // 'S'
  
  static const XMLCh DATE_SEPARATOR       = chDash;                 // '-'
  static const XMLCh TIME_SEPARATOR       = chColon;                // ':'
  static const XMLCh TIMEZONE_SEPARATOR   = chColon;                // ':'
  static const XMLCh DATETIME_SEPARATOR   = chLatin_T;              // 'T'
  static const XMLCh MILISECOND_SEPARATOR = chPeriod;               // '.'
  
  static const XMLCh UTC_STD_CHAR         = chLatin_Z;              // 'Z'
  static const XMLCh UTC_POS_CHAR         = chPlus;                 // '+'
  static const XMLCh UTC_NEG_CHAR         = chDash;                 // '-'
  
  static const XMLCh UTC_SET[]            = {UTC_STD_CHAR           //"Z+-"
                                           , UTC_POS_CHAR
                                           , UTC_NEG_CHAR
                                           , chNull};
  
  static const int YMD_MIN_SIZE    = 10;   // CCYY-MM-DD
  static const int YMONTH_MIN_SIZE = 7;    // CCYY_MM
  static const int TIME_MIN_SIZE   = 8;    // hh:mm:ss
  static const int TIMEZONE_SIZE   = 5;    // hh:mm
  static const int DAY_SIZE        = 5;    // ---DD
  static const int MONTH_SIZE      = 6;    // --MM--
  static const int MONTHDAY_SIZE   = 7;    // --MM-DD
  static const int NOT_FOUND       = -1;   
  
  //define constants to be used in assigning default values for 
  //all date/time excluding duration
  static const int YEAR_DEFAULT  = 2000;
  static const int MONTH_DEFAULT = 01;
  static const int DAY_DEFAULT   = 15;
  
  // order-relation on duration is a partial order. The dates below are used to 
  // for comparison of 2 durations, based on the fact that
  // duration x and y is x<=y iff s+x<=s+y
  // see 3.2.6 duration W3C schema datatype specs
  //
  // the dates are in format: {CCYY,MM,DD, H, S, M, MS, timezone}  
  const int XMLDateTime::DATETIMES[4][TOTAL_SIZE] = 
  {
      {1696, 9, 1, 0, 0, 0, 0, UTC_STD},     
  	{1697, 2, 1, 0, 0, 0, 0, UTC_STD},
  	{1903, 3, 1, 0, 0, 0, 0, UTC_STD},
  	{1903, 7, 1, 0, 0, 0, 0, UTC_STD}
  };
  
  // ---------------------------------------------------------------------------
  //  local methods
  // ---------------------------------------------------------------------------
  static inline int fQuotient(int a, int b)
  {
      div_t div_result = div(a, b);
      return div_result.quot;
  }
  
  static inline int fQuotient(int temp, int low, int high) 
  {
      return fQuotient(temp - low, high - low);
  }
  
  static inline int mod(int a, int b, int quotient) 
  {
  	return (a - quotient*b) ;
  }
  
  static inline int modulo (int temp, int low, int high) 
  {
      //modulo(a - low, high - low) + low 
      int a = temp - low;
      int b = high - low;
      return (mod (a, b, fQuotient(a, b)) + low) ;
  }
  
  static inline bool isLeapYear(int year)
  {
      return((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))); 
  }
  
  static int maxDayInMonthFor(int year, int month) 
  {
  
      if ( month == 4 || month == 6 || month == 9 || month == 11 ) 
      {
          return 30;
      }
      else if ( month==2 ) 
      {
          if ( isLeapYear(year) ) 
              return 29;
          else 
              return 28;
      }
      else
      {
          return 31;
      }
  
  }
  
  // ---------------------------------------------------------------------------
  //  static methods : for duration
  // ---------------------------------------------------------------------------
  /**
   * Compares 2 given durations. (refer to W3C Schema Datatypes "3.2.6 duration")
   *
   * 3.2.6.2 Order relation on duration
   *
   *     In general, the order-relation on duration is a partial order since there is no 
   *  determinate relationship between certain durations such as one month (P1M) and 30 days (P30D). 
   *  The order-relation of two duration values x and y is x < y iff s+x < s+y for each qualified 
   *  dateTime s in the list below. 
   *
   *     These values for s cause the greatest deviations in the addition of dateTimes and durations
   * 
   **/
  int XMLDateTime::compare(const XMLDateTime* const pDate1
                         , const XMLDateTime* const pDate2
                         , bool  strict)
  {
      //REVISIT: this is unoptimazed vs of comparing 2 durations
      //         Algorithm is described in 3.2.6.2 W3C Schema Datatype specs
      //
  
      int resultA, resultB = INDETERMINATE;
  
      //try and see if the objects are equal
      if ( (resultA = compareOrder(pDate1, pDate2)) == EQUAL)
          return EQUAL;
  
      //long comparison algorithm is required
      XMLDateTime tempA, *pTempA = &tempA;
      XMLDateTime tempB, *pTempB = &tempB;
  
      addDuration(pTempA, pDate1, 0);
      addDuration(pTempB, pDate2, 0);
      resultA = compareOrder(pTempA, pTempB);
      if ( resultA == INDETERMINATE )  
          return INDETERMINATE;
  
      addDuration(pTempA, pDate1, 1);
      addDuration(pTempB, pDate2, 1);
      resultB = compareOrder(pTempA, pTempB);
      resultA = compareResult(resultA, resultB, strict);
      if ( resultA == INDETERMINATE ) 
          return INDETERMINATE;
  
      addDuration(pTempA, pDate1, 2);
      addDuration(pTempB, pDate2, 2);
      resultB = compareOrder(pTempA, pTempB);
      resultA = compareResult(resultA, resultB, strict);
      if ( resultA == INDETERMINATE )
          return INDETERMINATE;
  
      addDuration(pTempA, pDate1, 3);
      addDuration(pTempB, pDate2, 3);
      resultB = compareOrder(pTempA, pTempB);
      resultA = compareResult(resultA, resultB, strict);
  
      return resultA;
  
  }
  
  //
  // Form a new XMLDateTime with duration and baseDate array
  // Note: C++        Java
  //       fNewDate   duration
  //       fDuration  date
  //
  
  void XMLDateTime::addDuration(XMLDateTime*             fNewDate 
                              , const XMLDateTime* const fDuration
                              , int index)
  
  {
  
      //REVISIT: some code could be shared between normalize() and this method,
      //         however is it worth moving it? The structures are different...
      //
  
      fNewDate->reset();
      //add months (may be modified additionaly below)
      int temp = DATETIMES[index][Month] + fDuration->fValue[Month];
      fNewDate->fValue[Month] = modulo(temp, 1, 13);
      int carry = fQuotient(temp, 1, 13);
  
      //add years (may be modified additionaly below)
      fNewDate->fValue[CentYear] = DATETIMES[index][CentYear] + fDuration->fValue[CentYear] + carry;
  
      //add seconds
      temp = DATETIMES[index][Second] + fDuration->fValue[Second];
      carry = fQuotient (temp, 60);
      fNewDate->fValue[Second] =  mod(temp, 60, carry);
  		
      //add minutes 
      temp = DATETIMES[index][Minute] + fDuration->fValue[Minute] + carry; 
      carry = fQuotient(temp, 60); 
      fNewDate->fValue[Minute] = mod(temp, 60, carry);         
  
      //add hours
      temp = DATETIMES[index][Hour] + fDuration->fValue[Hour] + carry;
      carry = fQuotient(temp, 24);
      fNewDate->fValue[Hour] = mod(temp, 24, carry);
  		
      fNewDate->fValue[Day] = DATETIMES[index][Day] + fDuration->fValue[Day] + carry;
  
      while ( true ) 
      {
          temp = maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]);
          if ( fNewDate->fValue[Day] < 1 ) 
          { //original fNewDate was negative
              fNewDate->fValue[Day] += maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]-1);
              carry = -1;
          }
          else if ( fNewDate->fValue[Day] > temp ) 
          {
              fNewDate->fValue[Day] -= temp;
              carry = 1;
          }
          else 
          {
              break;
          }
  
          temp = fNewDate->fValue[Month] + carry;
          fNewDate->fValue[Month] = modulo(temp, 1, 13);
          fNewDate->fValue[CentYear] += fQuotient(temp, 1, 13);
      }
  
      //fNewDate->fValue[utc] = UTC_STD_CHAR;
      fNewDate->fValue[utc] = UTC_STD;
  }
  
  int XMLDateTime::compareResult(short resultA
                               , short resultB
                               , bool strict)
  {
  
      if ( resultB == INDETERMINATE ) 
      {
          return INDETERMINATE;
      }
      else if ( (resultA != resultB) && 
                strict                ) 
      {
          return INDETERMINATE;
      }
      else if ( (resultA != resultB) && 
                !strict               ) 
      {
          if ( (resultA != EQUAL) && 
               (resultB != EQUAL)  ) 
          {
              return INDETERMINATE;
          }
          else 
          {
              return (resultA != EQUAL)? resultA : resultB;
          }
      }
  
      return resultA;
  	
  }
  
  // ---------------------------------------------------------------------------
  //  static methods : for others
  // ---------------------------------------------------------------------------
  int XMLDateTime::compare(const XMLDateTime* const pDate1
                         , const XMLDateTime* const pDate2)
  {
  
      if (pDate1->fValue[utc] == pDate2->fValue[utc])
      {
          return XMLDateTime::compareOrder(pDate1, pDate2);    
      }
  
      short c1, c2;
  
      if ( pDate1->isNormalized()) 
      {
          c1 = compareResult(pDate1, pDate2, false, UTC_POS);
          c2 = compareResult(pDate1, pDate2, false, UTC_NEG);
          return getRetVal(c1, c2);
      }
      else if ( pDate2->isNormalized()) 
      {
          c1 = compareResult(pDate1, pDate2, true, UTC_POS);
          c2 = compareResult(pDate1, pDate2, true, UTC_NEG);
          return getRetVal(c1, c2);
      }
  
      return INDETERMINATE;	
  }
  
  int XMLDateTime::compareResult(const XMLDateTime* const pDate1
                               , const XMLDateTime* const pDate2
                               , bool  set2Left
                               , int   utc_type)
  {
      XMLDateTime tmpDate = (set2Left ? *pDate1 : *pDate2);
  
      tmpDate.fTimeZone[hh] = 14;
      tmpDate.fTimeZone[mm] = 0;
      tmpDate.fValue[utc] = utc_type;
      tmpDate.normalize();
  
      return (set2Left? XMLDateTime::compareOrder(&tmpDate, pDate2) :
                        XMLDateTime::compareOrder(pDate1, &tmpDate));
  }
  
  int XMLDateTime::compareOrder(const XMLDateTime* const lValue
                              , const XMLDateTime* const rValue)
  {  
      //
      // If any of the them is not normalized() yet, 
      // we need to do something here.
      //
      XMLDateTime lTemp = *lValue;
      XMLDateTime rTemp = *rValue;
  
      lTemp.normalize();
      rTemp.normalize();
  
      for ( int i = 0 ; i < TOTAL_SIZE; i++ ) 
      {
          if ( lTemp.fValue[i] < rTemp.fValue[i] ) 
          {
              return LESS_THAN;
          }
          else if ( lTemp.fValue[i] > rTemp.fValue[i] ) 
          {
              return GREATER_THAN;
          }
      }
  
      return EQUAL;
  }
  
  // ---------------------------------------------------------------------------
  //  ctor and dtor
  // ---------------------------------------------------------------------------
  XMLDateTime::~XMLDateTime()
  {
      if (fBuffer)
          delete[] fBuffer;
  }
  
  XMLDateTime::XMLDateTime()
  :fBuffer(0)
  {
      reset();
  }
  
  XMLDateTime::XMLDateTime(const XMLCh* const aString)
  :fBuffer(0)
  {
      setBuffer(aString);
  }
  
  // -----------------------------------------------------------------------
  // Copy ctor and Assignment operators
  // -----------------------------------------------------------------------
  
  XMLDateTime::XMLDateTime(const XMLDateTime &toCopy)
  :fBuffer(0)
  {
      copy(toCopy);
  }
  
  XMLDateTime& XMLDateTime::operator=(const XMLDateTime& rhs)
  {
      if (this == &rhs)
          return *this;
  
      copy(rhs);
      return *this;
  }
  
  // -----------------------------------------------------------------------
  // Implementation of Abstract Interface
  // -----------------------------------------------------------------------
  
  //
  // We may simply return the handle to fBuffer, but
  // for the sake of consistency, we return a duplicated copy 
  // and the caller is responsible for the release of the buffer
  // just like any other things in the XMLNumber family.
  //
  XMLCh*  XMLDateTime::toString() const
  {
      assertBuffer();
  
      XMLCh* retBuf = XMLString::replicate(fBuffer);
      return retBuf;
  }
  
  int XMLDateTime::getSign() const
  {
      return 0;
  }
  
  // ---------------------------------------------------------------------------
  //  Parsers
  // ---------------------------------------------------------------------------
  
  //
  // [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}[TimeZone]
  //
  void XMLDateTime::parseDateTime()
  {
      initParser();
      getDate();
  
      //fStart is supposed to point to 'T'
      if (fBuffer[fStart++] != DATETIME_SEPARATOR)
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("CCYY-MM must be followed by '-' sign");
  
      getTime();
      validateDateTime();
      normalize();
  }
  
  //
  // [-]{CCYY-MM-DD}[TimeZone]
  //
  void XMLDateTime::parseDate()
  {
      initParser();
      getDate();
      parseTimeZone();
      validateDateTime();
      normalize();
  }
  
  void XMLDateTime::parseTime()
  {
      initParser();
  
      // time initialize to default values
      fValue[CentYear]= YEAR_DEFAULT;
      fValue[Month]   = MONTH_DEFAULT;
      fValue[Day]     = DAY_DEFAULT;
  
      getTime();
  
      validateDateTime();
      normalize();
  }
  
  //
  // {---DD}[TimeZone]
  //  01234
  //
  void XMLDateTime::parseDay()
  {
      initParser();
  
      if (fBuffer[0] != DATE_SEPARATOR || 
          fBuffer[1] != DATE_SEPARATOR || 
          fBuffer[2] != DATE_SEPARATOR  ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
  			//"Error in day parsing");
      }
  
      //initialize values 
      fValue[CentYear] = YEAR_DEFAULT;
      fValue[Month]    = MONTH_DEFAULT;  
      fValue[Day]      = parseInt(fStart+3, fStart+5);
  
      if ( DAY_SIZE < fEnd ) 
      {
          int sign = findUTCSign(DAY_SIZE);
          if ( sign < 0 ) 
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
  			//"Error in day parsing");
          }
          else 
          {
              getTimeZone(sign);
          }
      }
  
      validateDateTime();
      normalize();
  }
  
  //
  // {--MM--}[TimeZone]
  //  012345
  //
  void XMLDateTime::parseMonth()
  {
      initParser();
  
      if (fBuffer[0] != DATE_SEPARATOR || 
          fBuffer[1] != DATE_SEPARATOR || 
          fBuffer[4] != DATE_SEPARATOR ||
          fBuffer[5] != DATE_SEPARATOR  )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Invalid format for gMonth: "+str);
      }
  
      //set constants
      fValue[CentYear] = YEAR_DEFAULT;
      fValue[Day]      = DAY_DEFAULT;
      fValue[Month]    = parseInt(2, 4);
  
      if ( MONTH_SIZE < fEnd ) 
      {
          int sign = findUTCSign(MONTH_SIZE);
          if ( sign < 0 ) 
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //"Error in month parsing: "+str);
          }
          else 
          {
              getTimeZone(sign);
          }
      }
  
      validateDateTime();
      normalize();
  }
  
  //
  //[-]{CCYY}[TimeZone]
  // 0  1234
  //
  void XMLDateTime::parseYear()
  {
      initParser();
  
      // skip the first '-' and search for timezone
      //
      int sign = findUTCSign((fBuffer[0] == chDash) ? 1 : 0);
  
      if (sign == -1) 
      {
          fValue[CentYear] = parseIntYear(fEnd);
      }
      else 
      {
          fValue[CentYear] = parseIntYear(sign);
          getTimeZone (sign);
      }
  
      //initialize values 
      fValue[Month] = MONTH_DEFAULT;
      fValue[Day]   = DAY_DEFAULT;   //java is 1
  
      validateDateTime();
      normalize();
  }
  
  //
  //{--MM-DD}[TimeZone]
  // 0123456
  //
  void XMLDateTime::parseMonthDay()
  {
      initParser();
  
      if (fBuffer[0] != DATE_SEPARATOR || 
          fBuffer[1] != DATE_SEPARATOR || 
          fBuffer[4] != DATE_SEPARATOR )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Invalid format for gMonthDay: "+str);
      }
  
  
      //initialize 
      fValue[CentYear] = YEAR_DEFAULT;
      fValue[Month]    = parseInt(2, 4);	
      fValue[Day]      = parseInt(5, 7);
  
      if ( MONTHDAY_SIZE < fEnd ) 
      {
          int sign = findUTCSign(MONTHDAY_SIZE);
          if ( sign<0 ) 
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //"Error in month parsing: "+str);
          }
          else 
          {
              getTimeZone(sign);
          }
      }
  
      validateDateTime();
      normalize();
  }
  
  void XMLDateTime::parseYearMonth()
  {
      initParser();
  
      // get date
      getYearMonth();
      parseTimeZone();
  
      validateDateTime();
      normalize();
  }
  
  //
  //PnYn MnDTnH nMnS: -P1Y2M3DT10H30M        
  //
  // [-]{'P'{[n'Y'][n'M'][n'D']['T'][n'H'][n'M'][n'S']}}
  //
  //  Note: the n above shall be >= 0
  //        if no time element found, 'T' shall be absent
  //
  void XMLDateTime::parseDuration()
  {
      initParser();
  
      // must start with '-' or 'P'
      //
      XMLCh c = fBuffer[fStart++];
      if ( (c != DURATION_STARTER) && 
           (c != chDash)            ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Error in month parsing: "+str);
          //SchemaDateTimeException();
      }
  
      // 'P' must ALWAYS be present in either case
      if ( (c == chDash) && 
           (fBuffer[fStart++]!= DURATION_STARTER ))
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //SchemaDateTimeException();
      }
  
      // java code
      //date[utc]=(c=='-')?'-':0;
      //fValue[utc] = UTC_STD; 
      fValue[utc] = (fBuffer[0] == chDash? UTC_NEG : UTC_STD);
  
      int negate = ( fBuffer[0] == chDash ? -1 : 1);
  
      // 
      // No negative value is allowed after 'P'
      //
      // eg P-1234, invalid
      //
      if (indexOf(fStart, fEnd, chDash) != NOT_FOUND)
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //SchemaDateTimeException();
      }
  
      //at least one number and designator must be seen after P
      bool designator = false;
  
      int endDate = indexOf(fStart, fEnd, DATETIME_SEPARATOR); 
      if ( endDate == NOT_FOUND ) 
      {
          endDate = fEnd;  // 'T' absent
      }
  
      //find 'Y'        
      int end = indexOf(fStart, endDate, DURATION_Y);
      if ( end != NOT_FOUND ) 
      {
          //scan year
          fValue[CentYear] = negate * parseInt(fStart, end);
          fStart = end+1;
          designator = true;
      }
  
      end = indexOf(fStart, endDate, DURATION_M);
      if ( end != NOT_FOUND ) 
      {
          //scan month
          fValue[Month] = negate * parseInt(fStart, end);
          fStart = end+1;
          designator = true;
      }
  
      end = indexOf(fStart, endDate, DURATION_D);
      if ( end != NOT_FOUND ) 
      {
          //scan day
          fValue[Day] = negate * parseInt(fStart,end);
          fStart = end+1;
          designator = true;
      }
  
      if ( (fEnd == endDate) &&   // 'T' absent
           (fStart != fEnd)   )   // something after Day
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //SchemaDateTimeException();
      }
  
      if ( fEnd != endDate ) // 'T' present
      {
          //scan hours, minutes, seconds
          //         
  
          // skip 'T' first
          end = indexOf(++fStart, fEnd, DURATION_H);
          if ( end != NOT_FOUND ) 
          {
              //scan hours
              fValue[Hour] = negate * parseInt(fStart, end);
              fStart = end+1;
              designator = true;
          }
  
          end = indexOf(fStart, fEnd, DURATION_M);
          if ( end != NOT_FOUND ) 
          {
              //scan min
              fValue[Minute] = negate * parseInt(fStart, end);
              fStart = end+1;
              designator = true;
          }
  
          end = indexOf(fStart, fEnd, DURATION_S);
          if ( end != NOT_FOUND ) 
          {
              //scan seconds
              int mlsec = indexOf (fStart, end, MILISECOND_SEPARATOR);
              if ( mlsec != NOT_FOUND ) 
              {
                  fValue[Second]     = negate * parseInt(fStart, mlsec);
                  fValue[MiliSecond] = negate * parseInt(mlsec+1, end);
              }
              else 
              {
                  fValue[Second] = negate * parseInt(fStart,end);
              }
     
              fStart = end+1;
              designator = true;
          }
  
          // no additional data shouls appear after last item
          // P1Y1M1DT is illigal value as well
          if ( (fStart != fEnd) || 
                fBuffer[--fStart] == DATETIME_SEPARATOR ) 
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //SchemaDateTimeException();
          }
      }
  
      if ( !designator ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //SchemaDateTimeException();
      }
  
  }
  
  // ---------------------------------------------------------------------------
  //  Scanners
  // ---------------------------------------------------------------------------
  
  //
  // [-]{CCYY-MM-DD}
  //
  // Note: CCYY could be more than 4 digits
  //       Assuming fStart point to the beginning of the Date Section
  //       fStart updated to point to the position right AFTER the second 'D'
  //       Since the lenght of CCYY might be variable, we can't check format upfront
  //
  void XMLDateTime::getDate()
  {
  
      // Ensure enough chars in buffer
      if ( (fStart+YMD_MIN_SIZE) > fEnd)
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Imcomplete Date Format";
  
      getYearMonth();    // Scan YearMonth and 
                         // fStart point to the next '-' 
  
      if (fBuffer[fStart++] != DATE_SEPARATOR) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("CCYY-MM must be followed by '-' sign");
      }
  
      fValue[Day] = parseInt(fStart, fStart+2);
      fStart += 2 ;  //fStart points right after the Day
  
      return;
  }
  
  //
  // hh:mm:ss[.msssss]['Z']
  // hh:mm:ss[.msssss][['+'|'-']hh:mm]
  // 012345678
  //
  // Note: Assuming fStart point to the beginning of the Time Section
  //       fStart updated to point to the position right AFTER the second 's'
  //                                                  or ms if any
  //
  void XMLDateTime::getTime()
  {
  
      // Ensure enough chars in buffer
      if ( (fStart+TIME_MIN_SIZE) > fEnd)
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Imcomplete Time Format"
  
      // check (fixed) format first
      if ((fBuffer[fStart + 2] != TIME_SEPARATOR) ||
          (fBuffer[fStart + 5] != TIME_SEPARATOR)  )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Error in parsing time" );
      }
  
      //
      // get hours, minute and second
      //
      fValue[Hour]   = parseInt(fStart + 0, fStart + 2);
      fValue[Minute] = parseInt(fStart + 3, fStart + 5);            
      fValue[Second] = parseInt(fStart + 6, fStart + 8);
      fStart += 8;
  
      // to see if any ms and/or utc part after that
      if (fStart >= fEnd)
          return;
  
      //find UTC sign if any
      int sign = findUTCSign(fStart);
  
      //parse miliseconds 
      int milisec = (fBuffer[fStart] == MILISECOND_SEPARATOR)? fStart : NOT_FOUND;
      if ( milisec != NOT_FOUND )
      {
          fStart++;   // skip the '.'
          // make sure we have some thing between the '.' and fEnd
          if (fStart >= fEnd)
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //("ms shall be present once '.' is present" );
          }
  
          if ( sign == NOT_FOUND ) 
          {
              fValue[MiliSecond] = parseInt(fStart, fEnd);  //get ms between '.' and fEnd
              fStart = fEnd;
          }
          else 
          {
              fValue[MiliSecond] = parseInt(fStart, sign);  //get ms between UTC sign and fEnd
          }
  	}
  
      //parse UTC time zone (hh:mm)        
      if ( sign > 0 ) {
          getTimeZone(sign);
      }
  
  }
  
  //
  // [-]{CCYY-MM}
  //
  // Note: CCYY could be more than 4 digits
  //       fStart updated to point AFTER the second 'M' (probably meet the fEnd)
  //
  void XMLDateTime::getYearMonth()
  {
  
      // Ensure enough chars in buffer
      if ( (fStart+YMONTH_MIN_SIZE) > fEnd)
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Imcomplete YearMonth Format";
  
      // skip the first leading '-'
      int start = ( fBuffer[0] == chDash ) ? fStart + 1 : fStart;
  
      //
      // search for year separator '-'
      //
      int yearSeparator = indexOf(start, fEnd, DATE_SEPARATOR);
      if ( yearSeparator == NOT_FOUND) 
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Year separator is missing or misplaced");
  
      int length = yearSeparator - start;
      if (length < 4) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Year must have 'CCYY' format");
      }
      else if (length > 4 && 
               fBuffer[start] == chDigit_0)
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Leading zeros are required if the year value would otherwise have fewer than four digits; 
          // otherwise they are forbidden");
      }
  
      fValue[CentYear] = parseIntYear(yearSeparator);
      fStart = yearSeparator + 1;  //skip the '-' and point to the first M
  
      //
      //gonna check we have enough byte for month
      //
      if ((fStart + 2) > fEnd )
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"no month in buffer"
  
      fValue[Month] = parseInt(fStart, yearSeparator + 3);
      fStart += 2;  //fStart points right after the MONTH
  
      return;
  }
  
  void XMLDateTime::parseTimeZone()
  {
      if ( fStart < fEnd ) 
      {
          int sign = findUTCSign(fStart);
          if ( sign < 0 ) 
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //("Error in month parsing");
          }
          else 
          {
              getTimeZone(sign);
          }
      }
  
      return;
  }
  
  //
  // 'Z'
  // ['+'|'-']hh:mm
  //
  // Note: Assuming fStart points to the beginning of TimeZone section
  //       fStart updated to meet fEnd
  //
  void XMLDateTime::getTimeZone(const int sign)
  {
  
      if ( fBuffer[sign] == UTC_STD_CHAR )
      {
          if ((sign + 1) != fEnd )
          {
              ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
              //"Error in parsing time zone");
          }		
  
          return;	
      }
  
      //
      // otherwise, it has to be this format
      // '[+|-]'hh:mm
      //    1   23456 7
      //   sign      fEnd
      //
      if ( ( ( sign + TIMEZONE_SIZE + 1) != fEnd )      ||
           ( fBuffer[sign + 3] != TIMEZONE_SEPARATOR ) )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Error in parsing time zone");
      }
  
      fTimeZone[hh] = parseInt(sign+1, sign+3);		
      fTimeZone[mm] = parseInt(sign+4, fEnd);
          		
      return;
  }
  
  // ---------------------------------------------------------------------------
  //  Validator and normalizer
  // ---------------------------------------------------------------------------
  
  /**
   * If timezone present - normalize dateTime  [E Adding durations to dateTimes]
   * 
   * @param date   CCYY-MM-DDThh:mm:ss+03
   * @return CCYY-MM-DDThh:mm:ssZ
   */
  void XMLDateTime::normalize()
  {  
  
      if ((fValue[utc] == UTC_UNKNOWN) ||
          (fValue[utc] == UTC_STD)      )
          return;
  
      int negate = (fValue[utc] == UTC_POS)? -1: 1;
  
      // add mins
      int temp = fValue[Minute] + negate * fTimeZone[mm];
      int carry = fQuotient(temp, 60);
      fValue[Minute] = mod(temp, 60, carry);
         
      //add hours
      temp = fValue[Hour] + negate * fTimeZone[hh] + carry;
      carry = fQuotient(temp, 24);
      fValue[Hour] = mod(temp, 24, carry);
  
      fValue[Day] += carry;
  
      while (1)
      {
          temp = maxDayInMonthFor(fValue[CentYear], fValue[Month]);
          if (fValue[Day] < 1) 
          {
              fValue[Day] += maxDayInMonthFor(fValue[CentYear], fValue[Month] - 1);
              carry = -1;
          }
          else if ( fValue[Day] > temp ) 
          {
              fValue[Day] -= temp;
              carry = 1;
          }
          else 
          {
              break;
          }
  
          temp = fValue[Month] + carry;
          fValue[Month] = modulo(temp, 1, 13);
          fValue[CentYear] += fQuotient(temp, 1, 13);
      }
  
      // set to normalized
      fValue[utc] = UTC_STD;
  
      return;
  }
  
  void XMLDateTime::validateDateTime() const
  {
  
      //REVISIT: should we throw an exception for not valid dates
      //          or reporting an error message should be sufficient?  
      if ( fValue[CentYear] == 0 ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"The year \"0000\" is an illegal year value");
      }
  
      if ( fValue[Month] < 1  || 
           fValue[Month] > 12  ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
  		//"The month must have values 1 to 12");
      }
  
      //validate days
      if ( fValue[Day] > maxDayInMonthFor( fValue[CentYear], fValue[Month])) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"The day must have values 1 to 31");
      }
  
      //validate hours
      if ( fValue[Hour] < 0  ||
           fValue[Hour] > 23  ) 
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Hour must have values 0-23");
      }
  
      //validate
      if ( fValue[Minute] < 0 ||
           fValue[Minute] > 59 )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Minute must have values 0-59");
      }
  
      //validate
      if ( fValue[Second] < 0 ||
           fValue[Second] > 60 )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Second must have values 0-60");
      }
  
      //validate
      if ( fTimeZone[hh] < -14 || 
           fTimeZone[hh] > 14 )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //"Time zone should have range -14..+14");
      }
  
      //validate
      if ( fTimeZone[mm] < -59 || 
           fTimeZone[mm] > 59   )
      {
          ThrowXML(RuntimeException, XMLExcepts::SubGrpComparator_NGR);
          //("Minute must have values 0-59");
      }
  	
      return;
  }
  
  // -----------------------------------------------------------------------
  // locator and converter
  // -----------------------------------------------------------------------
  int XMLDateTime::indexOf(const int start, const int end, const XMLCh ch) const
  {
      for ( int i = start; i < end; i++ ) 
          if ( fBuffer[i] == ch ) 
              return i;
  
      return NOT_FOUND;
  }
  
  int XMLDateTime::findUTCSign (const int start)
  {
      int  pos;
      for ( int index = start; index < fEnd; index++ ) 
      {
          pos = XMLString::indexOf(UTC_SET, fBuffer[index]);
          if ( pos != NOT_FOUND)
          {
              fValue[utc] = pos+1;   // refer to utcType, there is 1 diff
              return index;
          }
      }
  
      return NOT_FOUND;
  }
  
  //
  // Note:
  //    start: starting point in fBuffer
  //    end:   ending point in fBuffer (exclusive)
  //    fStart NOT updated
  //
  int XMLDateTime::parseInt(const int start, const int end) const
  {
  
      XMLCh* strToScan = new XMLCh[end - start + 1];
      ArrayJanitor<XMLCh>  jname(strToScan);
      XMLString::subString(strToScan, fBuffer, start, end);
  
      unsigned int retVal;
      XMLString::textToBin(strToScan, retVal);
  
      return (int) retVal;
  }
  
  //
  // [-]CCYY
  // 
  // Note: start from fStart
  //       end (exclusive)
  //       fStart NOT updated
  //
  int XMLDateTime::parseIntYear(const int end) const
  {
      bool negative = (fBuffer[0] == chDash);
      int  yearVal = parseInt((negative ? 1 : 0), end);
      return ( negative ? (-1) * yearVal : yearVal );
  }
  
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: xerces-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xerces-cvs-help@xml.apache.org