blob: 777063b2c151798dfabf267842e44abb7742e5aa [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
3//
4// This program is free software; you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation; either version 2 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program; if not, write to the Free Software
16// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
39#include <cc++/config.h>
40#include <cc++/exception.h>
41#include <cc++/thread.h>
42#include <cc++/export.h>
43#include <cc++/numbers.h>
44#include <cstdlib>
45#include <cstdio>
46#include <iostream>
47#include <ctime>
48#include <cmath>
49
50#ifdef WIN32
51#include "time.h"
52#endif
53
54#ifdef CCXX_NAMESPACES
55namespace ost {
56using namespace std;
57#ifdef __BORLANDC__
58using std::time_t;
59using std::tm;
60using std::localtime;
61#endif
62#endif
63
64Date::Date()
65{
66 time_t now = SysTime::getTime();
67 struct tm dt;
68 SysTime::getLocalTime(&now, &dt);
69
70 toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
71}
72
73Date::Date(struct tm *dt)
74{
75 toJulian(dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday);
76}
77
78Date::Date(time_t tm)
79{
80 struct tm dt;
81 SysTime::getLocalTime(&tm, &dt);
82 toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
83}
84
85Date::Date(char *str, size_t size)
86{
87 setDate(str, size);
88}
89
90Date::~Date()
91{
92}
93
94void Date::setDate(const char *str, size_t size)
95{
96 time_t now = SysTime::getTime();
97 struct tm dt;
98 SysTime::getLocalTime(&now, &dt);
99 int year = 0;
100 const char *mstr = str;
101 const char *dstr = str;
102
103 if(!size)
104 size = strlen(str);
105//0000
106 if(size == 4) {
107#ifdef DEBUG
108 cout << "Date::SetDate(): 0000" << endl;
109#endif
110 year = dt.tm_year + 1900;
111 mstr = str;
112 dstr = str + 2;
113 }
114//00/00
115 else if(size == 5) {
116#ifdef DEBUG
117 cout << "Date::SetDate(): 00/00" << endl;
118#endif
119 year = dt.tm_year + 1900;
120 mstr = str;
121 dstr = str + 3;
122 }
123//000000
124 else if(size == 6) {
125#ifdef DEBUG
126 cout << "Date::SetDate(): 000000" << endl;
127#endif
128 ZNumber nyear((char*)str, 2);
129 year = ((dt.tm_year + 1900) / 100) * 100 + nyear();
130 mstr = str + 2;
131 dstr = str + 4;
132 }
133//00000000
134 else if(size == 8 && str[2] >= '0' && str[2] <= '9' && str[5] >= '0' && str[5] <= '9') {
135#ifdef DEBUG
136 cout << "Date::SetDate(): 00000000" << endl;
137#endif
138 ZNumber nyear((char*)str, 4);
139 year = nyear();
140 mstr = str + 4;
141 dstr = str + 6;
142 }
143//00/00/00
144 else if(size == 8) {
145#ifdef DEBUG
146 cout << "Date::SetDate(): 00/00/00" << endl;
147#endif
148 ZNumber nyear((char*)str, 2);
149 year = ((dt.tm_year + 1900) / 100) * 100 + nyear();
150 mstr = str + 3;
151 dstr = str + 6;
152 }
153
154//0000/00/00
155 else if(size == 10) {
156#ifdef DEBUG
157 cout << "Date::SetDate(): 0000-00-00" << endl;
158#endif
159 ZNumber nyear((char*)str, 4);
160 year = nyear();
161 mstr = str + 5;
162 dstr = str + 8;
163 }
164#ifdef CCXX_EXCEPTIONS
165 else if(Thread::getException() == Thread::throwObject) {
166 throw this;
167 }
168#ifdef COMMON_STD_EXCEPTION
169 else if(Thread::getException() == Thread::throwException) {
170 throw Exception("Date::setDate(): Invalid date.");
171 }
172#endif
173#endif
174 else {
175 julian = 0x7fffffffl;
176 return;
177 }
178
179 ZNumber nmonth((char*)mstr, 2);
180 ZNumber nday((char*)dstr, 2);
181 toJulian(year, nmonth(), nday());
182}
183
184Date::Date(int year, unsigned month, unsigned day)
185{
186 toJulian(year, month, day);
187}
188
189void Date::update(void)
190{
191}
192
193bool Date::isValid(void) const
194{
195 if(julian == 0x7fffffffl)
196 return false;
197 return true;
198}
199
200char *Date::getDate(char *buf) const
201{
202 fromJulian(buf);
203 return buf;
204}
205
206time_t Date::getDate(tm* dt) const
207{
208 char buf[11];
209 memset(dt, 0, sizeof(tm));
210 fromJulian(buf);
211 Number nyear(buf, 4);
212 Number nmonth(buf + 5, 2);
213 Number nday(buf + 8, 2);
214
215 dt->tm_year = nyear() - 1900;
216 dt->tm_mon = nmonth() - 1;
217 dt->tm_mday = nday();
218
219 return mktime(dt); // to fill in day of week etc.
220}
221
222time_t Date::getDate(void) const
223{
224 struct tm dt;
225 return getDate(&dt);
226}
227
228int Date::getYear(void) const
229{
230 char buf[11];
231 fromJulian(buf);
232 Number num(buf, 4);
233 return num();
234}
235
236unsigned Date::getMonth(void) const
237{
238 char buf[11];
239 fromJulian(buf);
240 Number num(buf + 5, 2);
241 return num();
242}
243
244unsigned Date::getDay(void) const
245{
246 char buf[11];
247 fromJulian(buf);
248 Number num(buf + 8, 2);
249 return num();
250}
251
252unsigned Date::getDayOfWeek(void) const
253{
254 return (unsigned)((julian + 1l) % 7l);
255}
256
257String Date::operator()() const
258{
259 char buf[11];
260
261 fromJulian(buf);
262 String date(buf);
263
264 return date;
265}
266
267long Date::getValue(void) const
268{
269 char buf[11];
270 fromJulian(buf);
271 return atol(buf) * 10000 + atol(buf + 5) * 100 + atol(buf + 8);
272}
273
274Date& Date::operator++()
275{
276 ++julian;
277 update();
278 return *this;
279}
280
281Date& Date::operator--()
282{
283 --julian;
284 update();
285 return *this;
286}
287
288Date& Date::operator+=(const long val)
289{
290 julian += val;
291 update();
292 return *this;
293}
294
295Date& Date::operator-=(long val)
296{
297 julian -= val;
298 update();
299 return *this;
300}
301
302int Date::operator==(const Date &d)
303{
304 return julian == d.julian;
305}
306
307int Date::operator!=(const Date &d)
308{
309 return julian != d.julian;
310}
311
312int Date::operator<(const Date &d)
313{
314 return julian < d.julian;
315}
316
317int Date::operator<=(const Date &d)
318{
319 return julian <= d.julian;
320}
321
322int Date::operator>(const Date &d)
323{
324 return julian > d.julian;
325}
326
327int Date::operator>=(const Date &d)
328{
329 return julian >= d.julian;
330}
331
332void Date::toJulian(long year, long month, long day)
333{
334 julian = 0x7fffffffl;
335
336 if(month < 1 || month > 12 || day < 1 || day > 31 || year == 0) {
337#ifdef CCXX_EXCEPTIONS
338 if(Thread::getException() == Thread::throwObject) {
339 throw this;
340 }
341#ifdef COMMON_STD_EXCEPTION
342 else if(Thread::getException() == Thread::throwException) {
343 throw Exception("Date::toJulian(): Invalid date.");
344 }
345#endif
346#endif
347 return;
348 }
349
350 if(year < 0)
351 year--;
352
353 julian = day - 32075l +
354 1461l * (year + 4800l + ( month - 14l) / 12l) / 4l +
355 367l * (month - 2l - (month - 14l) / 12l * 12l) / 12l -
356 3l * ((year + 4900l + (month - 14l) / 12l) / 100l) / 4l;
357}
358
359void Date::fromJulian(char *buffer) const
360{
361// The following conversion algorithm is due to
362// Henry F. Fliegel and Thomas C. Van Flandern:
363
364 ZNumber nyear(buffer, 4);
365 buffer[4] = '-';
366 ZNumber nmonth(buffer + 5, 2);
367 buffer[7] = '-';
368 ZNumber nday(buffer + 8, 2);
369
370 double i, j, k, l, n;
371
372 l = julian + 68569.0;
373 n = int( 4 * l / 146097.0);
374 l = l - int( (146097.0 * n + 3)/ 4 );
375 i = int( 4000.0 * (l+1)/1461001.0);
376 l = l - int(1461.0*i/4.0) + 31.0;
377 j = int( 80 * l/2447.0);
378 k = l - int( 2447.0 * j / 80.0);
379 l = int(j/11);
380 j = j+2-12*l;
381 i = 100*(n - 49) + i + l;
382 nyear = int(i);
383 nmonth = int(j);
384 nday = int(k);
385
386 buffer[10] = '\0';
387}
388
389Date operator+(const Date &date, const long val)
390{
391 Date d = date;
392 d.julian += val;
393 d.update();
394 return d;
395}
396
397Date operator+(const long val, const Date &date)
398{
399 Date d = date;
400 d.julian += val;
401 d.update();
402 return d;
403}
404
405Date operator-(const Date &date, const long val)
406{
407 Date d = date;
408 d.julian -= val;
409 d.update();
410 return d;
411}
412
413Date operator-(const long val, const Date &date)
414{
415 Date d = date;
416 d.julian -= val;
417 d.update();
418 return d;
419}
420
421Time::Time()
422{
423 time_t now = SysTime::getTime();
424 struct tm dt;
425 SysTime::getLocalTime(&now, &dt);
426
427 toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
428}
429
430Time::Time(struct tm *dt)
431{
432 toSeconds(dt->tm_hour, dt->tm_min, dt->tm_sec);
433}
434
435Time::Time(time_t tm)
436{
437 struct tm dt;
438 SysTime::getLocalTime(&tm, &dt);
439 toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
440}
441
442Time::Time(char *str, size_t size)
443{
444 setTime(str, size);
445}
446
447Time::Time(int hour, int minute, int second)
448{
449 toSeconds(hour, minute, second);
450}
451
452Time::~Time()
453{
454}
455
456bool Time::isValid(void) const
457{
458 if(seconds == -1)
459 return false;
460 return true;
461}
462
463char *Time::getTime(char *buf) const
464{
465 fromSeconds(buf);
466 return buf;
467}
468
469time_t Time::getTime(void) const
470{
471 return static_cast<time_t>(seconds);
472}
473
474int Time::getHour(void) const
475{
476 char buf[7];
477 fromSeconds(buf);
478 ZNumber num(buf, 2);
479 return num();
480}
481
482int Time::getMinute(void) const
483{
484 char buf[7];
485 fromSeconds(buf);
486 ZNumber num(buf + 2, 2);
487 return num();
488}
489
490int Time::getSecond(void) const
491{
492 char buf[7];
493 fromSeconds(buf);
494 ZNumber num(buf + 4, 2);
495 return num();
496}
497
498void Time::update(void)
499{
500}
501
502void Time::setTime(char *str, size_t size)
503{
504 int sec = 00;
505
506 if(!size)
507 size = strlen(str);
508
509//00:00
510 if (size == 5) {
511 sec = 00;
512 }
513//00:00:00
514 else if (size == 8) {
515 ZNumber nsecond(str + 6, 2);
516 sec = nsecond();
517 }
518#ifdef CCXX_EXCEPTIONS
519 else if(Thread::getException() == Thread::throwObject) {
520 throw this;
521 }
522#ifdef COMMON_STD_EXCEPTION
523 else if(Thread::getException() == Thread::throwException) {
524 throw Exception("Time::setTime(): Invalid time.");
525 }
526#endif
527#endif
528 else {
529 return;
530 }
531
532 ZNumber nhour(str, 2);
533 ZNumber nminute(str+3, 2);
534 toSeconds(nhour(), nminute(), sec);
535}
536
537String Time::operator()() const
538{
539 char buf[7];
540
541 fromSeconds(buf);
542 String strTime(buf);
543
544 return strTime;
545}
546
547long Time::getValue(void) const
548{
549 return seconds;
550}
551
552Time& Time::operator++()
553{
554 ++seconds;
555 update();
556 return *this;
557}
558
559Time& Time::operator--()
560{
561 --seconds;
562 update();
563 return *this;
564}
565
566Time& Time::operator+=(const int val)
567{
568 seconds += val;
569 update();
570 return *this;
571}
572
573Time& Time::operator-=(const int val)
574{
575 seconds -= val;
576 update();
577 return *this;
578}
579
580int Time::operator==(const Time &t)
581{
582 return seconds == t.seconds;
583}
584
585int Time::operator!=(const Time &t)
586{
587 return seconds != t.seconds;
588}
589
590int Time::operator<(const Time &t)
591{
592 return seconds < t.seconds;
593}
594
595int Time::operator<=(const Time &t)
596{
597 return seconds <= t.seconds;
598}
599
600int Time::operator>(const Time &t)
601{
602 return seconds > t.seconds;
603}
604
605int Time::operator>=(const Time &t)
606{
607 return seconds >= t.seconds;
608}
609
610void Time::toSeconds(int hour, int minute, int second)
611{
612 seconds = -1;
613
614 if (hour > 23 ||minute > 59 ||second > 59) {
615#ifdef CCXX_EXCEPTIONS
616 if(Thread::getException() == Thread::throwObject) {
617 throw this;
618 }
619#ifdef COMMON_STD_EXCEPTION
620 else if(Thread::getException() == Thread::throwException) {
621 throw Exception("Time::toSeconds(): Invalid time.");
622 }
623#endif
624#endif
625 return;
626 }
627
628 seconds = 3600 * hour + 60 * minute + second;
629}
630
631void Time::fromSeconds(char *buffer) const
632{
633 ZNumber hour(buffer, 2);
634 ZNumber minute(buffer + 2, 2);
635 ZNumber second(buffer + 4, 2);
636
637 hour = seconds / 3600;
638 minute = (seconds - (3600 * hour())) / 60;
639 second = seconds - (3600 * hour()) - (60 * minute());
640 buffer[6] = '\0';
641}
642
643Time operator+(const Time &time1, const Time &time2)
644{
645 Time t;
646 t.seconds = time1.seconds + time2.seconds;
647 t.update();
648 return t;
649}
650
651Time operator-(const Time &time1, const Time &time2)
652{
653 Time t;
654 t.seconds = time1.seconds - time2.seconds;
655 t.update();
656 return t;
657}
658
659Time operator+(const Time &time, const int val)
660{
661 Time t = time;
662 t.seconds += val;
663 t.update();
664 return t;
665}
666
667Time operator+(const int val, const Time &time)
668{
669 Time t = time;
670 t.seconds += val;
671 t.update();
672 return t;
673}
674
675Time operator-(const Time &time, const int val)
676{
677 Time t = time;
678 t.seconds -= val;
679 t.update();
680 return t;
681}
682
683Time operator-(const int val, const Time &time)
684{
685 Time t = time;
686 t.seconds -= val;
687 t.update();
688 return t;
689}
690
691Datetime::Datetime(time_t tm)
692{
693 struct tm dt;
694 SysTime::getLocalTime(&tm, &dt);
695 toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
696 toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
697}
698
699Datetime::Datetime(tm *dt) :
700Date(dt), Time(dt)
701{}
702
703Datetime::Datetime(const char *a_str, size_t size)
704{
705 char *timestr;
706
707 if (!size)
708 size = strlen(a_str);
709
710 char *str = new char[size+1];
711 strncpy(str, a_str, size);
712 str[size]=0;
713
714// 00/00 00:00
715 if (size == 11) {
716 timestr = str + 6;
717 setDate(str, 5);
718 setTime(timestr, 5);
719 }
720// 00/00/00 00:00
721 else if (size == 14) {
722 timestr = str + 9;
723 setDate(str, 8);
724 setTime(timestr,5);
725 }
726// 00/00/00 00:00:00
727 else if (size == 17) {
728 timestr = str + 9;
729 setDate(str, 8);
730 setTime(timestr,8);
731 }
732// 0000/00/00 00:00:00
733 else if (size == 19) {
734 timestr = str + 11;
735 setDate(str, 10);
736 setTime(timestr,8);
737 }
738#ifdef CCXX_EXCEPTIONS
739 else if(Thread::getException() == Thread::throwObject) {
740 delete str;
741 throw this;
742 }
743#ifdef COMMON_STD_EXCEPTION
744 else if(Thread::getException() == Thread::throwException) {
745 delete str;
746 throw Exception("Datetime::Datetime(): Invalid time.");
747 }
748#endif
749#endif
750 delete str;
751}
752
753Datetime::Datetime(int year, unsigned month, unsigned day,
754 int hour, int minute, int second) :
755 Date(year, month, day), Time(hour, minute, second)
756{}
757
758Datetime::Datetime() : Date(), Time()
759{
760 time_t now = SysTime::getTime();
761 struct tm dt;
762 SysTime::getLocalTime(&now, &dt);
763
764 toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
765 toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
766}
767
768Datetime::~Datetime()
769{
770}
771
772bool Datetime::isValid(void) const
773{
774 return Date::isValid() && Time::isValid();
775}
776
777char *Datetime::getDatetime(char *buf) const
778{
779 fromJulian(buf);
780 buf[10] = ' ';
781 fromSeconds(buf+11);
782 return buf;
783}
784
785time_t Datetime::getDatetime(void) const
786{
787 char buf[11];
788 struct tm dt;
789 memset(&dt, 0, sizeof(dt));
790
791 fromJulian(buf);
792 ZNumber nyear(buf, 4);
793 ZNumber nmonth(buf + 5, 2);
794 ZNumber nday(buf + 8, 2);
795 dt.tm_year = nyear() - 1900;
796 dt.tm_mon = nmonth() - 1;
797 dt.tm_mday = nday();
798
799 fromSeconds(buf);
800 ZNumber nhour(buf, 2);
801 ZNumber nminute(buf + 2, 2);
802 ZNumber nsecond(buf + 4, 2);
803 dt.tm_hour = nhour();
804 dt.tm_min = nminute();
805 dt.tm_sec = nsecond();
806 dt.tm_isdst = -1;
807
808 return mktime(&dt);
809}
810
811Datetime& Datetime::operator=(const Datetime datetime)
812{
813 julian = datetime.julian;
814 seconds = datetime.seconds;
815
816 return *this;
817}
818
819Datetime& Datetime::operator+=(const Datetime &datetime)
820{
821 seconds += datetime.seconds;
822 julian += datetime.julian;
823 Date::update();
824 Time::update();
825 return *this;
826}
827
828Datetime& Datetime::operator-=(const Datetime &datetime)
829{
830 seconds -= datetime.seconds;
831 julian -= datetime.julian;
832 Date::update();
833 Time::update();
834 return *this;
835}
836
837Datetime& Datetime::operator+=(const Time &time)
838{
839 seconds += time.getValue();
840 Date::update();
841 Time::update();
842 return *this;
843}
844
845Datetime& Datetime::operator-=(const Time &time)
846{
847 seconds -= time.getValue();
848 Date::update();
849 Time::update();
850 return *this;
851}
852
853
854int Datetime::operator==(const Datetime &d)
855{
856 return (julian == d.julian) && (seconds == d.seconds);
857}
858
859int Datetime::operator!=(const Datetime &d)
860{
861 return (julian != d.julian) || (seconds != d.seconds);
862}
863
864int Datetime::operator<(const Datetime &d)
865{
866 if (julian != d.julian) {
867 return (julian < d.julian);
868 }
869 else {
870 return (seconds < d.seconds);
871 }
872}
873
874int Datetime::operator<=(const Datetime &d)
875{
876 if (julian != d.julian) {
877 return (julian < d.julian);
878 }
879 else {
880 return (seconds <= d.seconds);
881 }
882}
883
884int Datetime::operator>(const Datetime &d)
885{
886 if (julian != d.julian) {
887 return (julian > d.julian);
888 }
889 else {
890 return (seconds > d.seconds);
891 }
892}
893
894int Datetime::operator>=(const Datetime &d)
895{
896 if (julian != d.julian) {
897 return (julian > d.julian);
898 }
899 else {
900 return (seconds >= d.seconds);
901 }
902}
903
904bool Datetime::operator!() const
905{
906 return !(Date::isValid() && Time::isValid());
907}
908
909
910String Datetime::strftime(const char *format) const
911{
912 char buffer[64];
913 size_t last;
914 time_t t;
915 tm tbp;
916 String retval;
917
918 t = getDatetime();
919 SysTime::getLocalTime(&t, &tbp);
920#ifdef WIN32
921 last = ::strftime(buffer, 64, format, &tbp);
922#else
923 last = std::strftime(buffer, 64, format, &tbp);
924#endif
925
926 buffer[last] = '\0';
927 retval = buffer;
928 return retval;
929}
930
931DateNumber::DateNumber(char *str) :
932Number(str, 10), Date(str, 10)
933{}
934
935DateNumber::~DateNumber()
936{}
937
938#ifdef CCXX_NAMESPACES
939}
940#endif