Update copyright.
[shibboleth/cpp-xmltooling.git] / xmltooling / util / DateTime.h
1 /*
2  *  Copyright 2001-2007 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file xmltooling/util/DateTime.h
19  * 
20  * Manipulation of XML date/time data. 
21  */
22
23 #ifndef __xmltool_datetime_h__
24 #define __xmltool_datetime_h__
25
26 #include <xmltooling/base.h>
27
28 #if defined (_MSC_VER)
29     #pragma warning( push )
30     #pragma warning( disable : 4244 )
31 #endif
32
33 #include <xercesc/util/XMLDateTime.hpp>
34
35 #if defined (_MSC_VER)
36     #pragma warning( pop )
37 #endif
38
39 namespace xmltooling
40 {
41     /**
42      * Class for manipulating XML date/time information.
43      * 
44      * This is mostly copied from Xerces-C, but they haven't produced a usable date/time
45      * class, so we had to incorporate a version of it for now. It can't be inherited
46      * since the fields needed are private.
47      */
48     class XMLTOOL_API DateTime
49     {
50     public:
51         /// @cond OFF
52         DateTime();
53         DateTime(const XMLCh* const);
54         DateTime(time_t epoch);
55         DateTime(const DateTime&);
56         DateTime& operator=(const DateTime&);
57         ~DateTime();
58     
59         inline void setBuffer(const XMLCh* const);
60     
61         const XMLCh* getRawData() const;
62         const XMLCh* getFormattedString() const;
63         int getSign() const;
64     
65         XMLCh* getDateTimeCanonicalRepresentation() const;
66         XMLCh* getTimeCanonicalRepresentation() const;
67     
68         void parseDateTime();
69         void parseDate();
70         void parseTime();
71         void parseDay();
72         void parseMonth();
73         void parseYear();
74         void parseMonthDay();
75         void parseYearMonth();
76         void parseDuration();
77     
78         static int compare(const DateTime* const, const DateTime* const);
79         static int compare(const DateTime* const, const DateTime* const, bool);
80         static int compareOrder(const DateTime* const, const DateTime* const);                                    
81     
82         int getYear() const {return fValue[CentYear];}
83         int getMonth() const {return fValue[Month];}
84         int getDay() const {return fValue[Day];}
85         int getHour() const {return fValue[Hour];}
86         int getMinute() const {return fValue[Minute];}
87         int getSecond() const {return fValue[Second];}
88         time_t getEpoch() const;
89     
90         /// @endcond
91     private:
92         enum valueIndex {
93             CentYear   = 0,
94             Month      ,
95             Day        ,
96             Hour       ,
97             Minute     ,
98             Second     ,
99             MiliSecond ,  //not to be used directly
100             utc        ,
101             TOTAL_SIZE
102         };
103     
104         enum utcType {
105             UTC_UNKNOWN = 0,
106             UTC_STD        ,          // set in parse() or normalize()
107             UTC_POS        ,          // set in parse()
108             UTC_NEG                   // set in parse()
109         };
110     
111         enum timezoneIndex {
112             hh = 0,
113             mm ,
114             TIMEZONE_ARRAYSIZE
115         };
116     
117         static int compareResult(int, int, bool);
118         static void addDuration(DateTime* pDuration, const DateTime* const pBaseDate, int index);
119         static int compareResult(const DateTime* const, const DateTime* const, bool, int);
120         static inline int getRetVal(int, int);
121     
122         inline void reset();
123         //inline void assertBuffer() const;
124         inline void copy(const DateTime&);
125         
126         inline void initParser();
127         inline bool isNormalized() const;
128     
129         void getDate();
130         void getTime();
131         void getYearMonth();
132         void getTimeZone(const int);
133         void parseTimeZone();
134     
135         int findUTCSign(const int start);
136         int indexOf(const int start, const int end, const XMLCh ch) const;
137         int parseInt(const int start, const int end) const;
138         int parseIntYear(const int end) const;
139         double parseMiliSecond(const int start, const int end) const;
140     
141         void validateDateTime() const;
142         void normalize();
143         void fillString(XMLCh*& ptr, valueIndex ind, int expLen) const;
144         int  fillYearString(XMLCh*& ptr, valueIndex ind) const;
145         void searchMiliSeconds(XMLCh*& miliStartPtr, XMLCh*& miliEndPtr) const;
146     
147         bool operator==(const DateTime& toCompare) const;
148     
149         static const int DATETIMES[][TOTAL_SIZE];
150         int fValue[TOTAL_SIZE];
151         int fTimeZone[TIMEZONE_ARRAYSIZE];
152         int fStart;
153         int fEnd;
154         int fBufferMaxLen;
155         XMLCh* fBuffer;
156     
157         double fMiliSecond;
158         bool fHasTime;
159     };
160
161     inline void DateTime::setBuffer(const XMLCh* const aString)
162     {
163         reset();
164         fEnd = XMLString::stringLen(aString);
165         if (fEnd > 0) {
166             if (fEnd > fBufferMaxLen) {
167                 delete[] fBuffer;
168                 fBufferMaxLen = fEnd + 8;
169                 fBuffer = new XMLCh[fBufferMaxLen+1];
170             }
171             memcpy(fBuffer, aString, (fEnd+1) * sizeof(XMLCh));
172         }
173     }
174     
175     inline void DateTime::reset()
176     {
177         for ( int i=0; i < XMLDateTime::TOTAL_SIZE; i++ )
178             fValue[i] = 0;
179     
180         fMiliSecond   = 0;
181         fHasTime      = false;
182         fTimeZone[hh] = fTimeZone[mm] = 0;
183         fStart = fEnd = 0;
184     
185         if (fBuffer)
186             *fBuffer = 0;
187     }
188     
189     inline void DateTime::copy(const DateTime& rhs)
190     {
191         for ( int i = 0; i < XMLDateTime::TOTAL_SIZE; i++ )
192             fValue[i] = rhs.fValue[i];
193     
194         fMiliSecond   = rhs.fMiliSecond;
195         fHasTime      = rhs.fHasTime;
196         fTimeZone[hh] = rhs.fTimeZone[hh];
197         fTimeZone[mm] = rhs.fTimeZone[mm];
198         fStart = rhs.fStart;
199         fEnd   = rhs.fEnd;
200     
201         if (fEnd > 0) {
202             if (fEnd > fBufferMaxLen) {
203                 delete[] fBuffer;
204                 fBufferMaxLen = rhs.fBufferMaxLen;
205                 fBuffer = new XMLCh[fBufferMaxLen+1];
206             }
207             memcpy(fBuffer, rhs.fBuffer, (fEnd+1) * sizeof(XMLCh));
208         }
209     }
210     
211     inline void DateTime::initParser()
212     {
213         fStart = 0;   // to ensure scan from the very first beginning
214                       // in case the pointer is updated accidentally by someone else.
215     }
216     
217     inline bool DateTime::isNormalized() const
218     {
219         return (fValue[XMLDateTime::utc] == XMLDateTime::UTC_STD ? true : false);
220     }
221     
222     inline int DateTime::getRetVal(int c1, int c2)
223     {
224         if ((c1 == XMLDateTime::LESS_THAN && c2 == XMLDateTime::GREATER_THAN) ||
225             (c1 == XMLDateTime::GREATER_THAN && c2 == XMLDateTime::LESS_THAN))
226             return XMLDateTime::INDETERMINATE;
227     
228         return (c1 != XMLDateTime::INDETERMINATE) ? c1 : c2;
229     }
230
231 }
232
233 #endif /* __xmltool_datetime_h__ */