Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
/*
* 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$
* $Log$
* 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.
*
PeiYong Zhang
committed
* 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 <xercesc/util/XMLDateTime.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLUni.hpp>
#include <xercesc/util/Janitor.hpp>
//
// constants used to process raw data (fBuffer)
//
// [-]{CCYY-MM-DD}'T'{HH:MM:SS.MS}['Z']
// [{+|-}hh:mm']
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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--
//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}
static const int DATETIMES[][XMLDateTime::TOTAL_SIZE] =
{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 modulo (int temp, int low, int high)
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)));
if ( month == 4 || month == 6 || month == 9 || month == 11 )
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);
return INDETERMINATE;
addDuration(pTempA, pDate1, 1);
addDuration(pTempB, pDate2, 1);
resultB = compareOrder(pTempA, pTempB);
resultA = compareResult(resultA, resultB, strict);
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
//
, 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;
{
temp = maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]);
{ //original fNewDate was negative
fNewDate->fValue[Day] += maxDayInMonthFor(fNewDate->fValue[CentYear], fNewDate->fValue[Month]-1);
carry = -1;
}
{
fNewDate->fValue[Day] -= temp;
carry = 1;
}
{
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)
{
{
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])
{
{
c1 = compareResult(pDate1, pDate2, false, UTC_POS);
c2 = compareResult(pDate1, pDate2, false, UTC_NEG);
return getRetVal(c1, c2);
}
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
{
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)
// we need to do something here.
//
XMLDateTime lTemp = *lValue;
XMLDateTime rTemp = *rValue;
lTemp.normalize();
rTemp.normalize();
{
return GREATER_THAN;
}
}
return EQUAL;
}
// ---------------------------------------------------------------------------
// ctor and dtor
// ---------------------------------------------------------------------------
XMLDateTime::~XMLDateTime()
{
if (fBuffer)
fMemoryManager->deallocate(fBuffer);//delete[] fBuffer;
: fBuffer(0)
, fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
reset();
}
XMLDateTime::XMLDateTime(const XMLCh* const aString)
: fBuffer(0)
, fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
setBuffer(aString);
}
// -----------------------------------------------------------------------
// Copy ctor and Assignment operators
// -----------------------------------------------------------------------
XMLDateTime::XMLDateTime(const XMLDateTime &toCopy)
: fBuffer(0)
, fMemoryManager(XMLPlatformUtils::fgMemoryManager)
{
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();
// Return data using global operator new
XMLCh* retBuf = XMLString::replicate(fBuffer);
return retBuf;
}
//
// We may simply return the handle to fBuffer
//
XMLCh* XMLDateTime::getRawData() const
{
assertBuffer();
return fBuffer;
}
const XMLCh* XMLDateTime::getFormattedString() const
{
return getRawData();
}
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
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)
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dt_missingT
, fBuffer);
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 )
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gDay_invalid
, fBuffer);
}
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gDay_invalid
, fBuffer);
}
{
getTimeZone(sign);
}
}
validateDateTime();
normalize();
}
//
// {--MM--}[TimeZone]
// 012345
//
void XMLDateTime::parseMonth()
{
initParser();
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gMth_invalid
, fBuffer);
}
//set constants
fValue[CentYear] = YEAR_DEFAULT;
fValue[Day] = DAY_DEFAULT;
fValue[Month] = parseInt(2, 4);
// REVISIT: allow both --MM and --MM-- now.
// need to remove the following lines to disallow --MM--
// when the errata is officially in the rec.
fStart = 4;
if ( fEnd >= fStart+2 && fBuffer[fStart] == DATE_SEPARATOR && fBuffer[fStart+1] == DATE_SEPARATOR )
{
fStart += 2;
}
//
// parse TimeZone if any
//
if ( fStart < fEnd )
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gMth_invalid
, fBuffer);
}
{
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);
{
fValue[CentYear] = parseIntYear(sign);
getTimeZone(sign);
}
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 )
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gMthDay_invalid
, fBuffer);
}
fValue[CentYear] = YEAR_DEFAULT;
fValue[Month] = parseInt(2, 4);
fValue[Day] = parseInt(5, 7);
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_gMthDay_invalid
, fBuffer);
}
{
getTimeZone(sign);
}
}
validateDateTime();
normalize();
}
void XMLDateTime::parseYearMonth()
{
initParser();
// get date
getYearMonth();
fValue[Day] = DAY_DEFAULT;
parseTimeZone();
validateDateTime();
normalize();
}
//
//
// [-]{'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++];
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_Start_dashP
, fBuffer);
}
// 'P' must ALWAYS be present in either case
(fBuffer[fStart++]!= DURATION_STARTER ))
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_noP
, fBuffer);
}
// java code
//date[utc]=(c=='-')?'-':0;
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)
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_DashNotFirst
, fBuffer);
}
//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 )
{
//scan year
fValue[CentYear] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, endDate, DURATION_M);
{
//scan month
fValue[Month] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, endDate, DURATION_D);
{
//scan day
fValue[Day] = negate * parseInt(fStart,end);
fStart = end+1;
designator = true;
}
if ( (fEnd == endDate) && // 'T' absent
(fStart != fEnd) ) // something after Day
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_inv_b4T
, fBuffer);
}
if ( fEnd != endDate ) // 'T' present
{
//scan hours, minutes, seconds
// skip 'T' first
end = indexOf(++fStart, fEnd, DURATION_H);
{
//scan hours
fValue[Hour] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, fEnd, DURATION_M);
{
//scan min
fValue[Minute] = negate * parseInt(fStart, end);
fStart = end+1;
designator = true;
}
end = indexOf(fStart, fEnd, DURATION_S);
{
//scan seconds
int mlsec = indexOf (fStart, end, MILISECOND_SEPARATOR);
PeiYong Zhang
committed
/***
* Schema Errata: E2-23
* at least one digit must follow the decimal point if it appears.
* That is, the value of the seconds component must conform
* to the following pattern: [0-9]+(.[0-9]+)?
*/
PeiYong Zhang
committed
/***
* make usure there is something after the '.' and before the end.
*/
if ( mlsec+1 == end )
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_inv_seconds
,fBuffer);
}
fValue[Second] = negate * parseInt(fStart, mlsec);
fValue[MiliSecond] = negate * parseInt(mlsec+1, end);
}
{
fValue[Second] = negate * parseInt(fStart,end);
}
fStart = end+1;
designator = true;
}
// no additional data should appear after last item
// P1Y1M1DT is illigal value as well
if ( (fStart != fEnd) ||
fBuffer[--fStart] == DATETIME_SEPARATOR )
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_NoTimeAfterT
,fBuffer);
}
}
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_dur_NoElementAtAll
, fBuffer);
}
}
// ---------------------------------------------------------------------------
// 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)
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_date_incomplete
, fBuffer);
getYearMonth(); // Scan YearMonth and
// fStart point to the next '-'
{
ThrowXML1(SchemaDateTimeException
, XMLExcepts::DateTime_date_invalid
, fBuffer);
//("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
//