?? xmldatetime.cpp
字號:
/* * 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);
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -