1 /* "CodeWorker":	a scripting language for parsing and generating text.
2 
3 Copyright (C) 1996-1997, 1999-2002 C�dric Lemaire
4 
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9 
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 Lesser General Public License for more details.
14 
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 
19 To contact the author: codeworker@free.fr
20 */
21 
22 #ifdef WIN32
23 #pragma warning (disable : 4786)
24 #endif
25 
26 #include <stdio.h>
27 #include <math.h>
28 #include <time.h>
29 
30 #ifdef WIN32
31 #	include <windows.h>
32 #endif
33 
34 #include "UtlException.h"
35 #include "UtlDate.h"
36 #include "UtlString.h"
37 
38 const double WINGZ_INFINITY = 1.0e300;
39 const int INFINITE_YEAR = 2000000000;
40 
41 namespace CodeWorker {
42 	class UtlInternalDate {
43 	public:
44 		static const char* _tsWeekDays[7];
45 		static const char* _tsMonths[12];
46 		static int _tNbDays[12];
47 
48 	private:
49 		int _iDay;
50 		int _iMonth;
51 		int _iYear;
52 		int _iHour;
53 		int _iMin;
54 		int _iSec;
55 		int _iMillis;
56 		std::string _sComment;
57 
58 	private:
formatInteger(int iNumber,unsigned int iDigits)59 		static std::string formatInteger(int iNumber, unsigned int iDigits) {
60 			char sNumber[32];
61 			sprintf(sNumber, "%d", iNumber);
62 			std::string sResult = sNumber;
63 			while (sResult.size() < iDigits) sResult = "0" + sResult;
64 			return sResult;
65 		}
66 
67 	public:
UtlInternalDate()68 		UtlInternalDate() {
69 #ifdef WIN32
70 			SYSTEMTIME mySystemTime;
71 			GetLocalTime(&mySystemTime);
72 			_iDay = mySystemTime.wDay;
73 			_iMonth = mySystemTime.wMonth;
74 			_iYear = mySystemTime.wYear;
75 			_iHour = mySystemTime.wHour;
76 			_iMin = mySystemTime.wMinute;
77 			_iSec = mySystemTime.wSecond;
78 			_iMillis = mySystemTime.wMilliseconds;
79 #else
80 			time_t timeInSecSince1970;
81 			time(&timeInSecSince1970);
82 			struct tm* today;
83 			struct tm xTIME;
84 			today = localtime_r(&timeInSecSince1970, &xTIME);
85 			_iDay = today->tm_mday;
86 			_iMonth = today->tm_mon + 1;
87 			_iYear = today->tm_year + 1900;
88 			_iHour = today->tm_hour;
89 			_iMin = today->tm_min;
90 			_iSec = today->tm_sec;
91 			_iMillis = 0;
92 #endif
93 		}
UtlInternalDate(double dWINGZDate)94 		UtlInternalDate(double dWINGZDate) {
95 			setWINGZDate(dWINGZDate);
96 		}
UtlInternalDate(int iWinfrontDate)97 		UtlInternalDate(int iWinfrontDate) {
98 			setWinfrontDate(iWinfrontDate);
99 		}
UtlInternalDate(int iDay,int iMonth,int iYear,int iHour,int iMin,int iSec,int iMillis,const std::string & sComment)100 		UtlInternalDate(int iDay, int iMonth, int iYear, int iHour, int iMin, int iSec, int iMillis, const std::string& sComment) : _iDay(iDay), _iMonth(iMonth), _iYear(iYear), _iHour(iHour), _iMin(iMin), _iSec(iSec), _iMillis(iMillis), _sComment(sComment) {}
~UtlInternalDate()101 		virtual ~UtlInternalDate() {}
102 
copyInstance() const103 		virtual UtlInternalDate* copyInstance() const { return new UtlInternalDate(_iDay, _iMonth, _iYear, _iHour, _iMin, _iSec, _iMillis, _sComment); }
104 
isInfinite() const105 		bool isInfinite() const {
106 			return (getYear() >= INFINITE_YEAR);
107 		}
108 
getComment() const109 		const std::string& getComment() const { return _sComment; }
setComment(const std::string & sComment)110 		void setComment(const std::string& sComment) { _sComment = sComment; }
111 
isAFixedDate() const112 		virtual bool isAFixedDate() const { return true; }
isAVariableDate() const113 		virtual bool isAVariableDate() const { return false; }
114 
getWeekDay() const115 		virtual int getWeekDay() const { return (getDayWINGZDate() + 6) % 7; }
getDay() const116 		virtual int getDay() const { return _iDay; }
getMonth() const117 		virtual int getMonth() const { return _iMonth; }
getYear() const118 		virtual int getYear() const { return _iYear; }
119 
setDay(int iDay)120 		virtual void setDay(int iDay) { _iDay = iDay; }
setMonth(int iMonth)121 		virtual void setMonth(int iMonth) { _iMonth = iMonth; }
setYear(int iYear)122 		virtual void setYear(int iYear) { _iYear = iYear; }
123 
addDay(int iDay)124 		void addDay(int iDay) {
125 			_iDay += iDay;
126 			if (_iDay > 0) {
127 				do {
128 					int iNbDays = getNbDaysInMonth(_iMonth, _iYear);
129 					if (_iDay > iNbDays) {
130 						_iDay -= iNbDays;
131 						_iMonth++;
132 						if (_iMonth > 12) {
133 							_iMonth = 1;
134 							_iYear++;
135 						}
136 					} else break;
137 				} while (true);
138 			} else {
139 				while (_iDay < 1) {
140 					_iMonth--;
141 					if (_iMonth <= 0) {
142 						_iMonth = 12;
143 						_iYear--;
144 					}
145 					int iNbDays = getNbDaysInMonth(_iMonth, _iYear);
146 					_iDay += iNbDays;
147 				}
148 			}
149 		}
150 
addMonth(int iMonth)151 		void addMonth(int iMonth) {
152 			_iMonth += iMonth;
153 			if (_iMonth <= 0) {
154 				_iYear += ((_iMonth - 1) / 12) - 1;
155 				_iMonth = (12 - ((1-_iMonth)%12))%12;
156 			} else {
157 				_iYear += ((_iMonth - 1) / 12);
158 				_iMonth = (_iMonth - 1) % 12;
159 			}
160 			_iMonth++;
161 			int iDaysOfMonth = getNbDaysInMonth(_iMonth, _iYear);
162 			if (iDaysOfMonth < _iDay) _iDay = iDaysOfMonth;
163 		}
164 
addYear(int iYear)165 		void addYear(int iYear) {
166 			_iYear += iYear;
167 			int iDaysOfMonth = getNbDaysInMonth(_iMonth, _iYear);
168 			if (iDaysOfMonth < _iDay) _iDay = iDaysOfMonth;
169 		}
170 
setTime(int iHour,int iMin,int iSec,int iMillis)171 		void setTime(int iHour, int iMin, int iSec, int iMillis) {
172 			_iHour = iHour;
173 			_iMin = iMin;
174 			_iSec = iSec;
175 			_iMillis = iMillis;
176 		}
177 
getHour() const178 		inline int getHour() const { return _iHour; }
setHour(int iHour)179 		inline void setHour(int iHour) { _iHour = iHour; }
getMin() const180 		inline int getMin() const { return _iMin; }
setMin(int iMin)181 		inline void setMin(int iMin) { _iMin = iMin; }
getSec() const182 		inline int getSec() const { return _iSec; }
setSec(int iSec)183 		inline void setSec(int iSec) { _iSec = iSec; }
getMillis() const184 		inline int getMillis() const { return _iMillis; }
setMillis(int iMillis)185 		inline void setMillis(int iMillis) { _iMillis = iMillis; }
instanceOf(const char * pName)186 		virtual bool instanceOf(const char *pName) {
187 			if (!strcmp(pName, "UtlInternalDate") ) return true ;
188 				else return false;
189 		}
190 
addHour(int iHour)191 		void addHour(int iHour) {
192 			_iHour += iHour;
193 			int iNbDays = _iHour / 24;
194 			_iHour = _iHour % 24;
195 			if (_iHour < 0) {
196 				_iHour += 24;
197 				iNbDays--;
198 			}
199 			addDay(iNbDays);
200 		}
201 
addMin(int iMin)202 		void addMin(int iMin) {
203 			_iMin += iMin;
204 			int iNbHours = _iMin / 60;
205 			_iMin = _iMin % 60;
206 			if (_iMin < 0) {
207 				_iMin += 60;
208 				iNbHours--;
209 			}
210 			addHour(iNbHours);
211 		}
212 
addSec(int iSec)213 		void addSec(int iSec) {
214 			_iSec += iSec;
215 			int iNbMins = _iSec / 60;
216 			_iSec = _iSec % 60;
217 			if (_iSec < 0) {
218 				_iSec += 60;
219 				iNbMins--;
220 			}
221 			addMin(iNbMins);
222 		}
223 
addMillis(int iMillis)224 		void addMillis(int iMillis) {
225 			_iMillis += iMillis;
226 			int iNbSecs = _iMillis / 1000;
227 			_iMillis = _iMillis % 1000;
228 			if (_iMillis < 0) {
229 				_iMillis += 1000;
230 				iNbSecs--;
231 			}
232 			addSec(iNbSecs);
233 		}
234 
isLastDayOfMonth() const235 		virtual bool isLastDayOfMonth() const {
236 			int iDaysOfMonth = getNbDaysInMonth(_iMonth, _iYear);
237 			return (getDay() == iDaysOfMonth);
238 		}
239 
setLastDayOfMonth()240 		virtual void setLastDayOfMonth() {
241 			int iDaysOfMonth = getNbDaysInMonth(_iMonth, _iYear);
242 			setDay(iDaysOfMonth);
243 		}
244 
getString() const245 		virtual std::string getString() const {
246 			char tcString[32];
247 			std::string sMonth = _tsMonths[_iMonth - 1];
248 			sMonth = sMonth.substr(0, 3);
249 			if ((_iHour > 0) || (_iMin > 0) || (_iSec > 0) || (_iMillis > 0)) {
250 				sprintf(tcString, "%02d%s%d %02d:%02d:%02d.%03d", _iDay, sMonth.c_str(), _iYear, _iHour, _iMin, _iSec, _iMillis);
251 			} else {
252 				sprintf(tcString, "%02d%s%d", _iDay, sMonth.c_str(), _iYear);
253 			}
254 			return tcString;
255 		}
256 
getMCLDate() const257 		std::string getMCLDate() const {
258 			char sMCLString[16];
259 			std::string sMonth = _tsMonths[_iMonth - 1];
260 			sMonth = sMonth.substr(0, 3);
261 			sprintf(sMCLString, "%d%s%d", _iDay, sMonth.c_str(), _iYear);
262 			return sMCLString;
263 		}
264 
getFormattedDate(const std::string & sFormat) const265 		std::string getFormattedDate(const std::string& sFormat) const {
266 			std::string sDate;
267 			std::string::size_type i = 0;
268 			while (i < sFormat.size()) {
269 				if (sFormat[i] == '%') {
270 					i++;
271 					switch(sFormat[i]) {
272 						case 'Y': sDate += formatInteger(_iYear, 4);break;
273 						case 'y': sDate += formatInteger(_iYear % 100, 2);break;
274 						case 'b': sDate += std::string(_tsMonths[_iMonth - 1]).substr(0, 3);break;
275 						case 'B': sDate += _tsMonths[_iMonth - 1];break;
276 						case 'm': sDate += formatInteger(_iMonth, 2);break;
277 						case 'd': sDate += formatInteger(_iDay, 2);break;
278 						case 'e': sDate += formatInteger(_iDay, 1);break;
279 						case 't': {
280 									char sNumber[300];
281 									double dWingz = getWINGZDate();
282 									if (dWingz == floor(dWingz)) sprintf(sNumber, "%d", (int) dWingz);
283 									else sprintf(sNumber, "%f", dWingz);
284 									sDate += sNumber;
285 									break;
286 								  }
287 						case 'w': sDate += formatInteger(getWeekDay(), 1);break;
288 						case 'W': sDate += std::string(_tsWeekDays[getWeekDay()]);break;
289 						case 'H': sDate += formatInteger(_iHour, 2);break;
290 						case 'I': sDate += formatInteger(((_iHour > 12) ? _iHour - 12: _iHour), 2);break;
291 						case 'p': sDate += ((_iHour > 12) ? "PM": "AM");break;
292 						case 'Q':
293 								sDate += formatInteger(_iYear, 4) + "-" + formatInteger(_iMonth, 2) + "-" + formatInteger(_iDay, 2) + " " + formatInteger(_iHour, 2) + ":" + formatInteger(_iMin, 2) + ":" + formatInteger(_iSec, 2);
294 								if (_iMillis != 0) sDate += "." + formatInteger(_iMillis,  3);
295 								break;
296 						case 'M': sDate += formatInteger(_iMin,  2);break;
297 						case 'S': sDate += formatInteger(_iSec,  2);break;
298 						case 'L': sDate += formatInteger(_iMillis,  3);break;
299 						case '%': sDate += "%";break;
300 						case 'j':
301 							{
302 								int iDays = _iDay;
303 								int iMonth = 1;
304 								while (iMonth < _iMonth) iDays += getNbDaysInMonth(iMonth++, _iYear);
305 								sDate += formatInteger(iDays, 1);
306 							}
307 							break;
308 						case 'D': sDate += formatInteger(_iMonth, 2) + "/" + formatInteger(_iDay, 2) + "/" + formatInteger(_iYear % 100, 2);break;
309 						case 'r': sDate += formatInteger(((_iHour > 12) ? _iHour - 12: _iHour), 2) + ":" + formatInteger(_iMin, 2) + ":" + formatInteger(_iSec, 2) + ((_iHour > 12) ? " PM": " AM");break;
310 						case 'T': sDate += formatInteger(_iHour, 2) + ":" + formatInteger(_iMin, 2) + ":" + formatInteger(_iSec, 2);break;
311 						default:
312 							throw UtlException("syntax error on date format \"" + sFormat + "\"");
313 					}
314 				} else sDate += sFormat[i];
315 				i++;
316 			}
317 			return sDate;
318 		}
319 
getDayWINGZDate() const320 		int getDayWINGZDate() const { return (int) getWINGZDate(); }
321 
getWINGZDate() const322 		double getWINGZDate() const {
323 			if (isInfinite()) return WINGZ_INFINITY;
324 			int iWingzDate = 2;
325 			int iDateYear = getYear();
326 			if (iDateYear < 1900) return -1.0;
327 
328 			int iYear = 1900;
329 			while (iYear < iDateYear) {
330 				bool b366 = isLeapYear(iYear);
331 				if (b366) iWingzDate += 366;
332 				else iWingzDate += 365;
333 				iYear++;
334 			}
335 
336 	  		int iMonth = 1;
337 			int iDateMonth = getMonth();
338 	  		while (iMonth < iDateMonth) {
339 				int iNbDays = getNbDaysInMonth(iMonth, iYear);
340 				iWingzDate += iNbDays;
341 				iMonth++;
342 	  		}
343 
344 	  		iWingzDate += (getDay() - 1);
345 			double dMillis = _iMillis;
346 			double dSeconds = (dMillis / 1000.0) + _iSec + 60 * (_iMin + 60*_iHour);
347 			double dWingzDate = iWingzDate;
348 			dWingzDate += dSeconds / 86400.0;
349 
350 			return dWingzDate;
351 		}
352 
setWINGZDate(double dWINGZDate)353 		void setWINGZDate(double dWINGZDate) {
354 			if (dWINGZDate == WINGZ_INFINITY) {
355 				_iYear = INFINITE_YEAR;
356 			} else {
357 				_iDay = 1;
358 				_iMonth = 1;
359 				_iYear =1900;
360 				addDay((int) (dWINGZDate - 2.0));
361 				double dRemaining = dWINGZDate - floor(dWINGZDate);
362 				dRemaining *= 24.0;
363 				double dFloor = floor(dRemaining);
364 				_iHour = (int) dFloor;
365 				dRemaining -= dFloor;
366 				dRemaining *= 60.0;
367 				dFloor = floor(dRemaining);
368 				_iMin = (int) dFloor;
369 				dRemaining -= dFloor;
370 				dRemaining *= 60.0;
371 				dFloor = floor(dRemaining);
372 				_iSec = (int) dFloor;
373 				dRemaining -= dFloor;
374 				dRemaining *= 1000.0;
375 				double dMillis = dRemaining;
376 				_iMillis = (int) floor(dMillis);
377 				if (dMillis - _iMillis >= 0.5) {
378 					_iMillis++;
379 					if (_iMillis == 1000) {
380 						_iMillis = 0;
381 						_iSec++;
382 						if (_iSec == 60) {
383 							_iSec = 0;
384 							_iMin++;
385 							if (_iMin == 60) {
386 								_iMin = 0;
387 								_iHour++;
388 								if (_iHour == 24) {
389 									_iHour = 0;
390 									_iDay++;
391 									if (getNbDaysInMonth(_iMonth, _iYear) < _iDay) {
392 										_iDay = 1;
393 										_iMonth++;
394 										if (_iMonth > 12) {
395 											_iMonth = 1;
396 											_iYear++;
397 										}
398 									}
399 								}
400 							}
401 						}
402 					}
403 				}
404 			}
405 		}
406 
getWinfrontDate() const407 		int getWinfrontDate() const {
408 			return getYear() * 10000 + getMonth() * 100 + getDay();
409 		}
410 
setWinfrontDate(int iWinfrontDate)411 		void setWinfrontDate(int iWinfrontDate) {
412 			setDay(iWinfrontDate % 100);
413 			iWinfrontDate /= 100;
414 			setMonth(iWinfrontDate % 100);
415 			iWinfrontDate /= 100;
416 			setYear(iWinfrontDate);
417 			_iHour   = 0;
418 			_iMin    = 0;
419 			_iSec    = 0;
420 			_iMillis = 0;
421 		}
422 
getNbDaysInMonth(int iMonth,int iYear)423 		static int getNbDaysInMonth(int iMonth, int iYear) {
424 			int iNbDays = _tNbDays[iMonth - 1];
425 			if ((iMonth == 2) && isLeapYear(iYear)) iNbDays = 29;
426 			return iNbDays;
427 		}
428 
isLeapYear(int iYear)429 		static bool isLeapYear(int iYear) { return (iYear%4 == 0) && ((iYear%100 != 0) || (iYear%400 == 0)); }
430 	};
431 
432 
433 	const char* UtlInternalDate::_tsWeekDays[7] = {"sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
434 	const char* UtlInternalDate::_tsMonths[12] = {"january", "february", "march", "april", "may", "june", "july", "august", "september", "october", "november", "december"};
435 	int UtlInternalDate::_tNbDays[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
436 
437 	class UtlVariableDate : public UtlInternalDate {
438 	private:
439 		int  _iFrequency;
440 		char _cUnit;
441 
442 	public:
UtlVariableDate(int iFrequency,char cUnit)443 		UtlVariableDate(int iFrequency, char cUnit) : _iFrequency(iFrequency), _cUnit(cUnit) {
444 			char sErrorMessage[128];
445 			switch(_cUnit) {
446 				case 'd':
447 				case 'w':
448 				case 'm':
449 				case 'y':
450 					_cUnit -= ' ';
451 				case 'D':
452 				case 'W':
453 				case 'M':
454 				case 'Y':
455 					break;
456 				default:
457 					sprintf(sErrorMessage, "Undefined unit of variable date: '%c' for \"%d%c\"", cUnit, iFrequency, cUnit);
458 					throw UtlException(sErrorMessage);
459 			}
460 		}
~UtlVariableDate()461 		virtual ~UtlVariableDate() {}
462 
copyInstance() const463 		virtual UtlInternalDate* copyInstance() const { return new UtlVariableDate(_iFrequency, _cUnit); }
464 
isAFixedDate() const465 		virtual bool isAFixedDate() const { return false; }
isAVariableDate() const466 		virtual bool isAVariableDate() const { return true; }
467 
getWeekDay() const468 		virtual int getWeekDay() const {
469 			UtlInternalDate date(UtlInternalDate::getDay(), UtlInternalDate::getMonth(), UtlInternalDate::getYear(), 0, 0, 0, 0, "");
470 			switch (_cUnit) {
471 				case 'D': date.addDay(_iFrequency);break;
472 				case 'W': date.addDay(7*_iFrequency);break;
473 				case 'M': date.addMonth(_iFrequency);break;
474 				case 'Y': date.addYear(_iFrequency);break;
475 			}
476 			return date.getWeekDay();
477 		}
478 
getDay() const479 		virtual int getDay() const {
480 			UtlInternalDate date(UtlInternalDate::getDay(), UtlInternalDate::getMonth(), UtlInternalDate::getYear(), 0, 0, 0, 0, "");
481 			switch (_cUnit) {
482 				case 'D': date.addDay(_iFrequency);break;
483 				case 'W': date.addDay(7*_iFrequency);break;
484 				case 'M': date.addMonth(_iFrequency);break;
485 				case 'Y': date.addYear(_iFrequency);break;
486 			}
487 			return date.getDay();
488 		}
489 
getMonth() const490 		virtual int getMonth() const {
491 			UtlInternalDate date(UtlInternalDate::getDay(), UtlInternalDate::getMonth(), UtlInternalDate::getYear(), 0, 0, 0, 0, "");
492 			switch (_cUnit) {
493 				case 'D': date.addDay(_iFrequency);break;
494 				case 'W': date.addDay(7*_iFrequency);break;
495 				case 'M': date.addMonth(_iFrequency);break;
496 				case 'Y': date.addYear(_iFrequency);break;
497 			}
498 			return date.getMonth();
499 		}
500 
getYear() const501 		virtual int getYear() const {
502 			UtlInternalDate date(UtlInternalDate::getDay(), UtlInternalDate::getMonth(), UtlInternalDate::getYear(), 0, 0, 0, 0, "");
503 			switch (_cUnit) {
504 				case 'D': date.addDay(_iFrequency);break;
505 				case 'W': date.addDay(7*_iFrequency);break;
506 				case 'M': date.addMonth(_iFrequency);break;
507 				case 'Y': date.addYear(_iFrequency);break;
508 			}
509 			return date.getYear();
510 		}
511 
getString() const512 		virtual std::string getString() const {
513 			char sString[16];
514 			sprintf(sString, "%d%c", _iFrequency, _cUnit);
515 			return sString;
516 		}
517 
getFrequency() const518 		virtual int getFrequency() const {
519 			return _iFrequency	;
520 		}
521 
getUnit() const522 		virtual char getUnit() const {
523 			return _cUnit	;
524 		}
525 
instanceOf(const char * pName)526 		virtual bool instanceOf(const char *pName) {
527 			if (!strcmp(pName, "UtlVariableDate") ) return true ;
528 				else return false;
529 		}
530 	};
531 
532 
UtlDate()533 	UtlDate::UtlDate() {
534 		_pInternalDate = new UtlInternalDate();
535 	}
536 
UtlDate(const UtlDate & date)537 	UtlDate::UtlDate(const UtlDate& date) {
538 		if (date._pInternalDate == NULL) _pInternalDate = NULL;
539 		else _pInternalDate = date._pInternalDate->copyInstance();
540 	}
541 
UtlDate(double dWINGZDate)542 	UtlDate::UtlDate(double dWINGZDate) {
543 		if (dWINGZDate <= 0.0) _pInternalDate = NULL;
544 		else _pInternalDate = new UtlInternalDate(dWINGZDate);
545 	}
546 
UtlDate(int iWinfrontDate)547 	UtlDate::UtlDate(int iWinfrontDate) {
548 		_pInternalDate = new UtlInternalDate(iWinfrontDate);
549 	}
550 
UtlDate(int iDay,int iMonth,int iYear,int iHour,int iMin,int iSec,int iMillis)551 	UtlDate::UtlDate(int iDay, int iMonth, int iYear, int iHour, int iMin, int iSec, int iMillis) {
552 		_pInternalDate = new UtlInternalDate(iDay, iMonth, iYear, iHour, iMin, iSec, iMillis, "");
553 	}
554 
UtlDate(int iFrequency,char cUnit)555 	UtlDate::UtlDate(int iFrequency, char cUnit) {
556 		_pInternalDate = new UtlVariableDate(iFrequency, cUnit);
557 	}
558 
~UtlDate()559 	UtlDate::~UtlDate() {
560 		delete _pInternalDate;
561 	}
562 
isNull() const563 	bool UtlDate::isNull() const {
564 		return (_pInternalDate == NULL);
565 	}
566 
nullify()567 	void UtlDate::nullify() {
568 		if (_pInternalDate != NULL) delete _pInternalDate;
569 		_pInternalDate = NULL;
570 	}
571 
isInfinite() const572 	bool UtlDate::isInfinite() const {
573 		if (_pInternalDate == NULL) return false;
574 		return _pInternalDate->isInfinite();
575 	}
576 
infinity()577 	void UtlDate::infinity() {
578 		if (_pInternalDate != NULL) delete _pInternalDate;
579 		_pInternalDate = new UtlInternalDate(WINGZ_INFINITY);
580 	}
581 
copyInstance() const582 	UtlDate* UtlDate::copyInstance() const {
583 		return new UtlDate(*this);
584 	}
585 
operator =(const UtlDate & date)586 	UtlDate& UtlDate::operator =(const UtlDate& date) {
587 		if (&date == this) throw UtlException("a date can't assign itself");
588 		if (_pInternalDate != NULL) delete _pInternalDate;
589 		if (date._pInternalDate == NULL) _pInternalDate = NULL;
590 		else _pInternalDate = date._pInternalDate->copyInstance();
591 		return *this;
592 	}
593 
operator <(const UtlDate & date) const594 	bool UtlDate::operator <(const UtlDate& date) const {
595 		if (isNull() || date.isNull()) return false;
596 		int iYear1 = getYear();
597 		int iYear2 = date.getYear();
598 		if (iYear1 == iYear2) {
599 			int iMonth1 = getMonth();
600 			int iMonth2 = date.getMonth();
601 			if (iMonth1 != iMonth2) return (iMonth1 < iMonth2);
602 			int iDay1 = getDay();
603 			int iDay2 = date.getDay();
604 			if (iDay1 != iDay2) return (iDay1 < iDay2);
605 			int iHour1 = getHour();
606 			int iHour2 = date.getHour();
607 			if (iHour1 != iHour2) return (iHour1 < iHour2);
608 			int iMin1 = getMin();
609 			int iMin2 = date.getMin();
610 			if (iMin1 != iMin2) return (iMin1 < iMin2);
611 			int iSec1 = getSec();
612 			int iSec2 = date.getSec();
613 			if (iSec1 != iSec2) return (iSec1 < iSec2);
614 		} else return (iYear1 < iYear2);
615 		return getMillis() < date.getMillis();
616 	}
617 
operator <=(const UtlDate & date) const618 	bool UtlDate::operator <=(const UtlDate& date) const {
619 		if (isNull() || date.isNull()) return false;
620 		int iYear1 = getYear();
621 		int iYear2 = date.getYear();
622 		if (iYear1 == iYear2) {
623 			int iMonth1 = getMonth();
624 			int iMonth2 = date.getMonth();
625 			if (iMonth1 != iMonth2) return (iMonth1 < iMonth2);
626 			int iDay1 = getDay();
627 			int iDay2 = date.getDay();
628 			if (iDay1 != iDay2) return (iDay1 < iDay2);
629 			int iHour1 = getHour();
630 			int iHour2 = date.getHour();
631 			if (iHour1 != iHour2) return (iHour1 < iHour2);
632 			int iMin1 = getMin();
633 			int iMin2 = date.getMin();
634 			if (iMin1 != iMin2) return (iMin1 < iMin2);
635 			int iSec1 = getSec();
636 			int iSec2 = date.getSec();
637 			if (iSec1 != iSec2) return (iSec1 < iSec2);
638 		} else return (iYear1 < iYear2);
639 		return getMillis() <= date.getMillis();
640 	}
641 
operator ==(const UtlDate & date) const642 	bool UtlDate::operator ==(const UtlDate& date) const {
643 		if (isNull() || date.isNull()) return false;
644 		return (getDay() == date.getDay()) && (getMonth() == date.getMonth()) && (getYear() == date.getYear()) && (getHour() == date.getHour()) && (getMin() == date.getMin()) && (getSec() == date.getSec()) && (getMillis() == date.getMillis());
645 	}
646 
operator !=(const UtlDate & date) const647 	bool UtlDate::operator !=(const UtlDate& date) const {
648 		if (isNull() || date.isNull()) return false;
649 		return (getDay() != date.getDay()) || (getMonth() != date.getMonth()) || (getYear() != date.getYear()) || (getHour() != date.getHour()) || (getMin() != date.getMin()) || (getSec() != date.getSec()) || (getMillis() != date.getMillis());
650 	}
651 
operator >=(const UtlDate & date) const652 	bool UtlDate::operator >=(const UtlDate& date) const {
653 		if (isNull() || date.isNull()) return false;
654 		int iYear1 = getYear();
655 		int iYear2 = date.getYear();
656 		if (iYear1 == iYear2) {
657 			int iMonth1 = getMonth();
658 			int iMonth2 = date.getMonth();
659 			if (iMonth1 != iMonth2) return (iMonth1 > iMonth2);
660 			int iDay1 = getDay();
661 			int iDay2 = date.getDay();
662 			if (iDay1 != iDay2) return (iDay1 > iDay2);
663 			int iHour1 = getHour();
664 			int iHour2 = date.getHour();
665 			if (iHour1 != iHour2) return (iHour1 > iHour2);
666 			int iMin1 = getMin();
667 			int iMin2 = date.getMin();
668 			if (iMin1 != iMin2) return (iMin1 > iMin2);
669 			int iSec1 = getSec();
670 			int iSec2 = date.getSec();
671 			if (iSec1 != iSec2) return (iSec1 > iSec2);
672 		} else return (iYear1 > iYear2);
673 		return getMillis() >= date.getMillis();
674 	}
675 
operator >(const UtlDate & date) const676 	bool UtlDate::operator >(const UtlDate& date) const {
677 		if (isNull() || date.isNull()) return false;
678 		int iYear1 = getYear();
679 		int iYear2 = date.getYear();
680 		if (iYear1 == iYear2) {
681 			int iMonth1 = getMonth();
682 			int iMonth2 = date.getMonth();
683 			if (iMonth1 != iMonth2) return (iMonth1 > iMonth2);
684 			int iDay1 = getDay();
685 			int iDay2 = date.getDay();
686 			if (iDay1 != iDay2) return (iDay1 > iDay2);
687 			int iHour1 = getHour();
688 			int iHour2 = date.getHour();
689 			if (iHour1 != iHour2) return (iHour1 > iHour2);
690 			int iMin1 = getMin();
691 			int iMin2 = date.getMin();
692 			if (iMin1 != iMin2) return (iMin1 > iMin2);
693 			int iSec1 = getSec();
694 			int iSec2 = date.getSec();
695 			if (iSec1 != iSec2) return (iSec1 > iSec2);
696 		} else return (iYear1 > iYear2);
697 		return getMillis() > date.getMillis();
698 	}
699 
operator -(const UtlDate & date) const700 	double UtlDate::operator -(const UtlDate& date) const {
701 		if (isNull() || date.isNull()) return 0.0;
702 		return getWINGZDate() - date.getWINGZDate();
703 	}
704 
today()705 	void UtlDate::today() {
706 		if (_pInternalDate != NULL) delete _pInternalDate;
707 		_pInternalDate = new UtlInternalDate();
708 	}
709 
isAFixedDate() const710 	bool UtlDate::isAFixedDate() const {
711 		if (isNull()) return false;
712 		return _pInternalDate->isAFixedDate();
713 	}
isAVariableDate() const714 	bool UtlDate::isAVariableDate() const {
715 		if (isNull()) return false;
716 		return _pInternalDate->isAVariableDate();
717 	}
718 
getDay() const719 	int UtlDate::getDay() const {
720 		return _pInternalDate->getDay();
721 	}
722 
getMonth() const723 	int UtlDate::getMonth() const {
724 		return _pInternalDate->getMonth();
725 	}
726 
getYear() const727 	int UtlDate::getYear() const {
728 		return _pInternalDate->getYear();
729 	}
730 
setDay(int iDay)731 	void UtlDate::setDay(int iDay) {
732 		_pInternalDate->setDay(iDay);
733 	}
734 
setMonth(int iMonth)735 	void UtlDate::setMonth(int iMonth) {
736 		_pInternalDate->setMonth(iMonth);
737 	}
738 
setYear(int iYear)739 	void UtlDate::setYear(int iYear) {
740 		_pInternalDate->setYear(iYear);
741 	}
742 
addDay(int iDay)743 	void UtlDate::addDay(int iDay) {
744 		_pInternalDate->addDay(iDay);
745 	}
746 
addMonth(int iMonth)747 	void UtlDate::addMonth(int iMonth) {
748 		_pInternalDate->addMonth(iMonth);
749 	}
750 
addYear(int iYear)751 	void UtlDate::addYear(int iYear) {
752 		_pInternalDate->addYear(iYear);
753 	}
754 
getHour() const755 	int UtlDate::getHour() const {
756 		return _pInternalDate->getHour();
757 	}
758 
getMin() const759 	int UtlDate::getMin() const {
760 		return _pInternalDate->getMin();
761 	}
762 
getSec() const763 	int UtlDate::getSec() const {
764 		return _pInternalDate->getSec();
765 	}
766 
getMillis() const767 	int UtlDate::getMillis() const {
768 		return _pInternalDate->getMillis();
769 	}
770 
isLastDayOfMonth() const771 	bool UtlDate::isLastDayOfMonth() const {
772 		return _pInternalDate->isLastDayOfMonth();
773 	}
774 
setLastDayOfMonth()775 	void UtlDate::setLastDayOfMonth() {
776 		_pInternalDate->setLastDayOfMonth();
777 	}
778 
ignoreHours()779 	void UtlDate::ignoreHours() {
780 		_pInternalDate->setHour(0);
781 		_pInternalDate->setMin(0);
782 		_pInternalDate->setSec(0);
783 		_pInternalDate->setMillis(0);
784 	}
785 
setTime(int iHour,int iMin,int iSec,int iMillis)786 	void UtlDate::setTime(int iHour, int iMin, int iSec, int iMillis) {
787 		_pInternalDate->setTime(iHour, iMin, iSec, iMillis);
788 	}
789 
compareTime(const UtlDate & date) const790 	int UtlDate::compareTime(const UtlDate& date) const {
791 		int iHour1 = getHour();
792 		int iHour2 = date.getHour();
793 		if (iHour1 != iHour2) return (iHour1 - iHour2);
794 		int iMin1 = getMin();
795 		int iMin2 = date.getMin();
796 		if (iMin1 != iMin2) return (iMin1 - iMin2);
797 		int iSec1 = getSec();
798 		int iSec2 = date.getSec();
799 		if (iSec1 != iSec2) return (iSec1 - iSec2);
800 		return getMillis() - date.getMillis();
801 	}
802 
setHour(int iHour)803 	void UtlDate::setHour(int iHour) {
804 		_pInternalDate->setHour(iHour);
805 	}
806 
setMin(int iMin)807 	void UtlDate::setMin(int iMin) {
808 		_pInternalDate->setMin(iMin);
809 	}
810 
setSec(int iSec)811 	void UtlDate::setSec(int iSec) {
812 		_pInternalDate->setSec(iSec);
813 	}
814 
setMillis(int iMillis)815 	void UtlDate::setMillis(int iMillis) {
816 		_pInternalDate->setMillis(iMillis);
817 	}
818 
addHour(int iHour)819 	void UtlDate::addHour(int iHour) {
820 		_pInternalDate->addHour(iHour);
821 	}
822 
addMin(int iMin)823 	void UtlDate::addMin(int iMin) {
824 		_pInternalDate->addMin(iMin);
825 	}
826 
addSec(int iSec)827 	void UtlDate::addSec(int iSec) {
828 		_pInternalDate->addSec(iSec);
829 	}
830 
addMillis(int iMillis)831 	void UtlDate::addMillis(int iMillis) {
832 		_pInternalDate->addMillis(iMillis);
833 	}
834 
getString() const835 	std::string UtlDate::getString() const {
836 		if (isNull()) return "undated";
837 		return _pInternalDate->getString();
838 	}
839 
getMCLDate() const840 	std::string UtlDate::getMCLDate() const {
841 		if (isNull()) return "undated";
842 		return _pInternalDate->getMCLDate();
843 	}
844 
getFormattedDate(const std::string & sFormat) const845 	std::string UtlDate::getFormattedDate(const std::string& sFormat) const {
846 		return _pInternalDate->getFormattedDate(sFormat);
847 	}
848 
getDateFromFormat(const std::string & sDate,const std::string & sFormat)849 	UtlDate UtlDate::getDateFromFormat(const std::string& sDate, const std::string& sFormat) {
850 		UtlDate today;
851 		today.ignoreHours();
852 		std::string::size_type i = 0;
853 		std::string::size_type j = 0;
854 		std::string sNumber;
855 		while ((i < sFormat.size()) && (j < sDate.size())) {
856 			if (sFormat[i] == '%') {
857 				i++;
858 				switch(sFormat[i]) {
859 					case 'Y':
860 						if (j + 4 > sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Y'");
861 						sNumber = sDate.substr(j, 4);
862 						today.setYear(atoi(sNumber.c_str()));
863 						j += 4;
864 						break;
865 					case 'y':
866 						{
867 							int iYear = getInteger(sDate, 2, j);
868 							int iTodayShortYear = today.getYear() % 100;
869 							if (iTodayShortYear > iYear) {
870 								if (iTodayShortYear - iYear > 50) iYear += 100;
871 							} else {
872 								if (iYear - iTodayShortYear > 50) iYear -= 100;
873 							}
874 							iYear += (today.getYear() - iTodayShortYear);
875 							today.setYear(iYear);
876 						}
877 						break;
878 					case 'm':
879 						today.setMonth(getInteger(sDate, 2, j));
880 						if ((today.getMonth() < 1) || (today.getMonth() > 12)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%m'");
881 						break;
882 					case 'd':
883 						today.setDay(getInteger(sDate, 2, j));
884 						if ((today.getDay() < 1) || (today.getDay() > 31)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%d'");
885 						break;
886 					case 'H':
887 						today.setHour(getInteger(sDate, 2, j));
888 						if ((today.getHour() < 0) || (today.getHour() > 23)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%H'");
889 						break;
890 					case 'I':
891 						if (j + 2 > sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%I'");
892 						sNumber = sDate.substr(j, 2);
893 						today.setHour(atoi(sNumber.c_str()));
894 						j += 2;
895 						break;
896 					case 'M':
897 						today.setMin(getInteger(sDate, 2, j));
898 						if ((today.getMin() < 0) || (today.getMin() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%M'");
899 						break;
900 					case 'S':
901 						today.setSec(getInteger(sDate, 2, j));
902 						if ((today.getSec() < 0) || (today.getSec() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%S'");
903 						break;
904 					case '%': break;
905 					case 'D':
906 						today.setMonth(getInteger(sDate, 2, j));
907 						if ((today.getMonth() < 1) || (today.getMonth() > 12)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> %m'");
908 						if (sDate[j++] != '/') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> '/' expected after %m'");
909 						today.setDay(getInteger(sDate, 2, j));
910 						if ((today.getDay() < 1) || (today.getDay() > 31)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> %d'");
911 						if (sDate[j++] != '/') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> '/' expected after %d'");
912 						{
913 							int iYear = getInteger(sDate, 2, j);
914 							if (iYear > 70) iYear += 1900;
915 							else iYear += 2000;
916 							today.setYear(iYear);
917 						}
918 						break;
919 					case 'Q':
920 						today.setYear(getInteger(sDate, 4, j));
921 						if (sDate[j++] != '-') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> '-' expected after %Y'");
922 						today.setMonth(getInteger(sDate, 2, j));
923 						if ((today.getMonth() < 1) || (today.getMonth() > 12)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> %m'");
924 						if (sDate[j++] != '-') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> '-' expected after %m'");
925 						today.setDay(getInteger(sDate, 2, j));
926 						if ((today.getDay() < 1) || (today.getDay() > 31)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> %d'");
927 						if (sDate[j++] != ' ') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ' ' expected after %d'");
928 						today.setHour(getInteger(sDate, 2, j));
929 						if ((today.getHour() < 0) || (today.getHour() > 23)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> %H'");
930 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ':' expected after %H'");
931 						today.setMin(getInteger(sDate, 2, j));
932 						if ((today.getMin() < 0) || (today.getMin() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> %M'");
933 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ':' expected after %M'");
934 						today.setSec(getInteger(sDate, 2, j));
935 						if ((today.getSec() < 0) || (today.getSec() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> %S'");
936 						if (sDate[j] != '.') break;
937 						j++;
938 						// Be careful!
939 						// Continue in sequence on case '%L'!
940 					case 'L':
941 						// Be careful!
942 						// Don't move this case label and don't insert anything before case '%Q'
943 						{
944 							if (j >= sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%L'");
945 							char a = sDate[j];
946 							if ((a < '0') || (a > '9')) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%L'");
947 							int iMillis = 0;
948 							int iLoop = 0;
949 							do {
950 								iMillis = 10*iMillis + (a - '0');
951 								a = sDate[++j];
952 							} while ((++iLoop < 3) && (a >= '0') && (a <= '9'));
953 							today.setMillis(iMillis);
954 						}
955 						break;
956 					case 'b':
957 						if (j + 3 > sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%b'");
958 						sNumber = sDate.substr(j, 3);
959 						{
960 							int k;
961 							for (k = 0; k < 12; k++) if (strnicmp(UtlInternalDate::_tsMonths[k], sNumber, 3) == 0) break;
962 							if (k >= 12) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%b' -> unknow month = '" + sNumber + "'");
963 							today.setMonth(k + 1);
964 						}
965 						j += 3;
966 						break;
967 					case 'B':
968 						{
969 							int k;
970 							int iLength;
971 							for (k = 0; k < 12; k++) {
972 								iLength = strlen(UtlInternalDate::_tsMonths[k]);
973 								if (j + iLength <= sDate.size()) {
974 									if (strnicmp(UtlInternalDate::_tsMonths[k], sDate.c_str() + j, iLength) == 0) break;
975 								}
976 							}
977 							if (k >= 12) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%B' -> unknow month = '" + sNumber + "'");
978 							today.setMonth(k + 1);
979 							j += iLength;
980 						}
981 						break;
982 					case 't':
983 						today.setWINGZDate(getDouble(sDate, 300, j));
984 						break;
985 					case 'T':
986 						today.setHour(getInteger(sDate, 2, j));
987 						if ((today.getHour() < 0) || (today.getHour() > 23)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> %H'");
988 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> ':' expected after %H'");
989 						today.setMin(getInteger(sDate, 2, j));
990 						if ((today.getMin() < 0) || (today.getMin() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> %M'");
991 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> ':' expected after %M'");
992 						today.setSec(getInteger(sDate, 2, j));
993 						if ((today.getSec() < 0) || (today.getSec() > 59)) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> %S'");
994 						break;
995 					case '|':
996 						// nothing to do
997 						break;
998 					case 'a':
999 					case 'A':
1000 					case 'e':
1001 					case 'j':
1002 					case 'p':
1003 					case 'r':
1004 					case 'U':
1005 					case 'w':
1006 						throw UtlException("date format \"... " + std::string(sFormat.c_str() + (i-1)) + "' not implemented yet");
1007 					default:
1008 						throw UtlException("syntax error on date format \"" + sFormat + "\" for '%" + sFormat[i] + "'");
1009 				}
1010 			} else j++;
1011 			i++;
1012 		}
1013 		if (i < sFormat.size()) {
1014 			if ((sFormat[i] != '%') || (sFormat[i + 1] != '|')) {
1015 				throw UtlException("date format \"" + sFormat + "\" not applied on \"" + sDate + "\" completely");
1016 			}
1017 		}
1018 		return today;
1019 	}
1020 
addDateFromFormat(const std::string & sFormat,const std::string & sDate)1021 	void UtlDate::addDateFromFormat(const std::string& sFormat, const std::string& sDate) {
1022 		std::string::size_type i = 0;
1023 		std::string::size_type j = 0;
1024 		std::string sNumber;
1025 		while ((i < sFormat.size()) && (j < sDate.size())) {
1026 			if (sFormat[i] == '%') {
1027 				i++;
1028 				int iSigned = ((sDate[j] == '-') ? 1 : 0);
1029 				switch(sFormat[i]) {
1030 					case 'Y':
1031 						if (j + 4 + iSigned > sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Y'");
1032 						sNumber = sDate.substr(j, 4 + iSigned);
1033 						addYear(atoi(sNumber.c_str()));
1034 						j += 4 + iSigned;
1035 						break;
1036 					case 'y':
1037 						addYear(getInteger(sDate, 2 + iSigned, j));
1038 						break;
1039 					case 'm':
1040 						addMonth(getInteger(sDate, 2 + iSigned, j));
1041 						break;
1042 					case 'd':
1043 						addDay(getInteger(sDate, 2 + iSigned, j));
1044 						break;
1045 					case 'H':
1046 						addHour(getInteger(sDate, 2 + iSigned, j));
1047 						break;
1048 					case 'I':
1049 						if (j + 2 + iSigned > sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%I'");
1050 						sNumber = sDate.substr(j, 2 + iSigned);
1051 						addHour(atoi(sNumber.c_str()));
1052 						j += 2 + iSigned;
1053 						break;
1054 					case 'M':
1055 						addMin(getInteger(sDate, 2 + iSigned, j));
1056 						break;
1057 					case 'S':
1058 						addSec(getInteger(sDate, 2 + iSigned, j));
1059 						break;
1060 					case '%': break;
1061 					case 'D':
1062 						addMonth(getInteger(sDate, 2 + iSigned, j));
1063 						if (sDate[j++] != '/') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> '/' expected after %m'");
1064 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1065 						addDay(getInteger(sDate, 2 + iSigned, j));
1066 						if (sDate[j++] != '/') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%D -> '/' expected after %d'");
1067 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1068 						addYear(getInteger(sDate, 2 + iSigned, j));
1069 						break;
1070 					case 'Q':
1071 						addYear(getInteger(sDate, 4 + iSigned, j));
1072 						if (sDate[j++] != '-') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> '-' expected after %Y'");
1073 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1074 						addMonth(getInteger(sDate, 2 + iSigned, j));
1075 						if (sDate[j++] != '-') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> '-' expected after %m'");
1076 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1077 						addDay(getInteger(sDate, 2 + iSigned, j));
1078 						if (sDate[j++] != ' ') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ' ' expected after %d'");
1079 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1080 						addHour(getInteger(sDate, 2 + iSigned, j));
1081 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ':' expected after %H'");
1082 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1083 						addMin(getInteger(sDate, 2 + iSigned, j));
1084 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%Q -> ':' expected after %M'");
1085 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1086 						addSec(getInteger(sDate, 2 + iSigned, j));
1087 						if (sDate[j] != '.') break;
1088 						j++;
1089 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1090 						// Be careful!
1091 						// Continue in sequence on case '%L'!
1092 					case 'L':
1093 						// Be careful!
1094 						// Don't move this case label and don't insert anything before case '%Q'
1095 						{
1096 							if (iSigned != 0) j++;
1097 							if (j >= sDate.size()) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%L'");
1098 							char a = sDate[j];
1099 							if ((a < '0') || (a > '9')) throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%L'");
1100 							int iMillis = 0;
1101 							int iLoop = 0;
1102 							do {
1103 								iMillis = 10*iMillis + (a - '0');
1104 								a = sDate[++j];
1105 							} while ((++iLoop < 3) && (a >= '0') && (a <= '9'));
1106 							if (iSigned != 0) iMillis = -iMillis;
1107 							addMillis(iMillis);
1108 						}
1109 						break;
1110 					case 't':
1111 						setWINGZDate(getWINGZDate() + getDouble(sDate, 300, j));
1112 						break;
1113 					case 'T':
1114 						addHour(getInteger(sDate, 2 + iSigned, j));
1115 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> ':' expected after %H'");
1116 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1117 						addMin(getInteger(sDate, 2 + iSigned, j));
1118 						if (sDate[j++] != ':') throw UtlException("syntax error on date format: format \"" + sFormat + "\" doesn't match with date '" + sDate + "' for '%T -> ':' expected after %M'");
1119 						iSigned = ((sDate[j] == '-') ? 1 : 0);
1120 						addSec(getInteger(sDate, 2 + iSigned, j));
1121 						break;
1122 					case '|':
1123 						// nothing to do
1124 						break;
1125 					case 'a':
1126 					case 'A':
1127 					case 'b':
1128 					case 'B':
1129 					case 'e':
1130 					case 'j':
1131 					case 'p':
1132 					case 'r':
1133 					case 'U':
1134 					case 'w':
1135 						throw UtlException("date format \"... " + std::string(sFormat.c_str() + (i-1)) + "' has no sense here");
1136 					default:
1137 						throw UtlException("syntax error on date format \"" + sFormat + "\" for '%" + sFormat[i] + "'");
1138 				}
1139 			} else j++;
1140 			i++;
1141 		}
1142 		if (i < sFormat.size()) {
1143 			if ((sFormat[i] != '%') || (sFormat[i + 1] != '|')) {
1144 				throw UtlException("date format \"" + sFormat + "\" not applied on \"" + sDate + "\" completely");
1145 			}
1146 		}
1147 	}
1148 
getDayWINGZDate() const1149 	int UtlDate::getDayWINGZDate() const {
1150 		return _pInternalDate->getDayWINGZDate();
1151 	}
1152 
getWINGZDate() const1153 	double UtlDate::getWINGZDate() const {
1154 		if (_pInternalDate == NULL) return 0.0;
1155 		return _pInternalDate->getWINGZDate();
1156 	}
1157 
setWINGZDate(double dWINGZDate)1158 	void UtlDate::setWINGZDate(double dWINGZDate) {
1159 		delete _pInternalDate;
1160 		if (dWINGZDate <= 0.0) _pInternalDate = NULL;
1161 		else _pInternalDate = new UtlInternalDate(dWINGZDate);
1162 	}
1163 
1164 
getInteger(const std::string & sValue,int iNbMaxOfDigits,std::string::size_type & iCursor)1165 	int UtlDate::getInteger(const std::string& sValue, int iNbMaxOfDigits, std::string::size_type& iCursor) {
1166 		bool bSigned;
1167 		char a = sValue[iCursor];
1168 		if (a == '-') {
1169 			bSigned = true;
1170 			a = sValue[++iCursor];
1171 			iNbMaxOfDigits--;
1172 		} else {
1173 			bSigned = false;
1174 		}
1175 		if ((a < '0') || (a > '9')) {
1176 			if (bSigned) --iCursor;
1177 			return 0;
1178 		}
1179 		int iNumber = 0;
1180 		do {
1181 			iNumber *= 10;
1182 			iNumber += (int) (a - '0');
1183 			iCursor++;
1184 			iNbMaxOfDigits--;
1185 			if (iCursor >= sValue.size()) break;
1186 			a = sValue[iCursor];
1187 		} while ((a >= '0') && (a <= '9') && (iNbMaxOfDigits > 0));
1188 		if (bSigned) iNumber = -iNumber;
1189 		return iNumber;
1190 	}
1191 
1192 
getDouble(const std::string & sValue,int iNbMaxOfDigits,std::string::size_type & iCursor)1193 	double UtlDate::getDouble(const std::string& sValue, int iNbMaxOfDigits, std::string::size_type& iCursor) {
1194 		bool bSigned;
1195 		char a = sValue[iCursor];
1196 		if (a == '-') {
1197 			bSigned = true;
1198 			a = sValue[++iCursor];
1199 			iNbMaxOfDigits--;
1200 		} else {
1201 			bSigned = false;
1202 		}
1203 		if ((a < '0') || (a > '9')) {
1204 			if (bSigned) --iCursor;
1205 			return 0.0;
1206 		}
1207 		double dNumber = 0.0;
1208 		do {
1209 			dNumber *= 10.0;
1210 			dNumber += (double) ((int) (a - '0'));
1211 			iCursor++;
1212 			iNbMaxOfDigits--;
1213 			if (iCursor >= sValue.size()) return (bSigned) ? -dNumber : dNumber;
1214 			a = sValue[iCursor];
1215 		} while ((a >= '0') && (a <= '9') && (iNbMaxOfDigits > 0));
1216 		if ((a == '.') && (iNbMaxOfDigits > 0)) {
1217 			iCursor++;
1218 			a = sValue[iCursor];
1219 			double dPower = 0.1;
1220 			while ((a >= '0') && (a <= '9') && (iNbMaxOfDigits > 0)) {
1221 				dNumber += dPower * (double) ((int) (a - '0'));
1222 				dPower  *= 0.1;
1223 				iCursor++;
1224 				iNbMaxOfDigits--;
1225 				if (iCursor >= sValue.size()) return dNumber;
1226 				a = sValue[iCursor];
1227 			}
1228 		}
1229 		return (bSigned) ? -dNumber : dNumber;
1230 	}
1231 
1232 
getFrequency()1233 	int UtlDate::getFrequency() {
1234 		if (_pInternalDate==NULL) {
1235 			return 0;
1236 		}
1237 		else {
1238 			if (_pInternalDate->instanceOf("UtlVariableDate")) {
1239 				UtlVariableDate *pDateCast= (UtlVariableDate *) _pInternalDate;
1240 				return pDateCast->getFrequency();
1241 			}
1242 			else {
1243 				return 0;
1244 			}
1245 
1246 		}
1247 	}
1248 
getUnit()1249 	char UtlDate::getUnit() {
1250 		if (_pInternalDate==NULL) {
1251 			return 0;
1252 		}
1253 		else {
1254 			if (_pInternalDate->instanceOf("UtlVariableDate")) {
1255 				UtlVariableDate *pDateCast= (UtlVariableDate *) _pInternalDate;
1256 				return pDateCast->getUnit();
1257 			}
1258 			else {
1259 				return 0;
1260 			}
1261 
1262 		}
1263 	}
1264 
getComment() const1265 	const std::string& UtlDate::getComment() const {
1266 		static std::string sEmpty = "";
1267 		if (_pInternalDate == NULL) return sEmpty;
1268 		return _pInternalDate->getComment();
1269 	}
1270 
setComment(const std::string & sComment)1271 	void UtlDate::setComment(const std::string& sComment) {
1272 		if (_pInternalDate != NULL) {
1273 			_pInternalDate->setComment(sComment);
1274 		}
1275 	}
1276 }
1277