xmldatetime.cpp

来自「IBM的解析xml的工具Xerces的源代码」· C++ 代码 · 共 1,784 行 · 第 1/4 页

CPP
1,784
字号
/* * Copyright 2001-2004 The Apache Software Foundation. *  * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *  *      http://www.apache.org/licenses/LICENSE-2.0 *  * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *//* * $Id: XMLDateTime.cpp,v 1.28 2004/09/08 13:56:24 peiyongz Exp $ * $Log: XMLDateTime.cpp,v $ * Revision 1.28  2004/09/08 13:56:24  peiyongz * Apache License Version 2.0 * * Revision 1.27  2004/09/02 15:03:50  peiyongz * To build on AIX * * Revision 1.26  2004/08/31 20:50:50  peiyongz * Parse/keep milisecond as double to retain precision. * * Revision 1.25  2004/01/29 11:48:47  cargilld * Code cleanup changes to get rid of various compiler diagnostic messages. * * Revision 1.24  2004/01/25 23:23:26  jberry * Step around CodeWarrior compiler warning * * Revision 1.23  2004/01/13 19:50:56  peiyongz * remove parseContent() * * Revision 1.22  2004/01/13 16:34:20  cargilld * Misc memory management changes. * * Revision 1.21  2004/01/03 00:03:18  peiyongz * parseContent * * Revision 1.20  2003/12/31 02:34:11  neilg * enable production of canonical representations for dates with negative years, or years >9999 * * Revision 1.19  2003/12/17 00:18:35  cargilld * Update to memory management so that the static memory manager (one used to call Initialize) is only for static data. * * Revision 1.18  2003/12/16 22:48:52  peiyongz * exception thrown upon invalid number, thanks Gareth Reakes. * * Revision 1.17  2003/12/11 21:38:12  peiyongz * support for Canonical Representation for Datatype * * Revision 1.16  2003/09/25 22:24:28  peiyongz * Using writeString/readString * * Revision 1.15  2003/09/25 15:22:54  peiyongz * Solve HP complier error * * Revision 1.14  2003/09/23 18:16:07  peiyongz * Inplementation for Serialization/Deserialization * * Revision 1.13  2003/08/14 02:57:27  knoaman * Code refactoring to improve performance of validation. * * Revision 1.12  2003/05/22 02:10:52  knoaman * Default the memory manager. * * Revision 1.11  2003/05/18 14:02:05  knoaman * Memory manager implementation: pass per instance manager. * * Revision 1.10  2003/05/15 19:07:46  knoaman * Partial implementation of the configurable memory manager. * * Revision 1.9  2003/05/15 16:32:19  gareth * We did not allow dateTimes with a timezone due to the last seconds fix. * * Revision 1.8  2003/03/23 22:54:49  peiyongz * invalid second values * * Revision 1.7  2003/02/22 22:49:09  peiyongz * Schema Errata E2-45 24:00:00 allowed * * Revision 1.6  2003/02/02 23:54:43  peiyongz * getFormattedString() added to return original and converted value. * * Revision 1.5  2003/01/30 21:55:22  tng * Performance: create getRawData which is similar to toString but return the internal data directly, user is not required to delete the returned memory. * * Revision 1.4  2002/11/28 20:39:27  peiyongz * Schema Errata: E2-23 seconds part shall have at least one digit after the dot *                           if it appears. * * Revision 1.3  2002/11/06 22:22:21  peiyongz * Schema-Errata: E2-12: gMonth * * Revision 1.2  2002/11/04 15:22:05  tng * C++ Namespace Support. * * Revision 1.1.1.1  2002/02/01 22:22:14  peiyongz * sane_include * * Revision 1.4  2001/11/14 22:04:03  peiyongz * Patch to apply check on Year and more rigorous on other fields as well. * * Revision 1.3  2001/11/12 20:36:54  peiyongz * SchemaDateTimeException defined * * Revision 1.2  2001/11/09 20:41:45  peiyongz * Fix: compilation error on Solaris and AIX. * * Revision 1.1  2001/11/07 19:16:03  peiyongz * DateTime Port * * */// ---------------------------------------------------------------------------//  Includes// ---------------------------------------------------------------------------#include <stdlib.h>#include <assert.h>#include <errno.h>#include <xercesc/util/XMLDateTime.hpp>#include <xercesc/util/XMLString.hpp>#include <xercesc/util/XMLUni.hpp>#include <xercesc/util/Janitor.hpp>#include <xercesc/util/NumberFormatException.hpp>XERCES_CPP_NAMESPACE_BEGIN//// 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-DDstatic const int YMONTH_MIN_SIZE = 7;    // CCYY_MMstatic const int TIME_MIN_SIZE   = 8;    // hh:mm:ssstatic const int TIMEZONE_SIZE   = 5;    // hh:mmstatic const int DAY_SIZE        = 5;    // ---DD//static const int MONTH_SIZE      = 6;    // --MM--static const int MONTHDAY_SIZE   = 7;    // --MM-DDstatic const int NOT_FOUND       = -1;//define constants to be used in assigning default values for//all date/time excluding durationstatic 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}static const int DATETIMES[][XMLDateTime::TOTAL_SIZE] ={    {1696, 9, 1, 0, 0, 0, 0, XMLDateTime::UTC_STD},	{1697, 2, 1, 0, 0, 0, 0, XMLDateTime::UTC_STD},	{1903, 3, 1, 0, 0, 0, 0, XMLDateTime::UTC_STD},	{1903, 7, 1, 0, 0, 0, 0, XMLDateTime::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(XMLPlatformUtils::fgMemoryManager), *pTempA = &tempA;    XMLDateTime tempB(XMLPlatformUtils::fgMemoryManager), *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(int resultA                             , int 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);    }    int 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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?