1 #include "config.h"
2
3 #include <iostream>
4 // #include <sstream>
5 #include <iomanip>
6 #include <string>
7 #include <cstring>
8 #include <cctype>
9
10 #ifdef HAVE_TIME_H
11 #include <time.h>
12 #endif
13 #ifdef HAVE_SYS_TYPES_H
14 #include <sys/types.h>
15 #endif
16
17 #include "asserts.h"
18 #include "error.h"
19 #include "estring.h"
20 #include "tstamp.h"
21
22 /** C'tor */
timestamp()23 timestamp::timestamp()
24 {
25 clear();
26 set();
27 }
28
29 /** C'tor */
timestamp(const timestamp & a_t)30 timestamp::timestamp(const timestamp& a_t)
31 {
32 clear();
33 assign(a_t);
34 }
35
36 /** C'tor */
timestamp(const int a_year,const int a_month,const int a_day,const int a_hour,const int a_minute,const int a_second)37 timestamp::timestamp(
38 const int a_year,
39 const int a_month,
40 const int a_day,
41 const int a_hour,
42 const int a_minute,
43 const int a_second
44 )
45 {
46 clear();
47 assign(a_year,a_month,a_day,a_hour,a_minute,a_second);
48 }
49
50 /** C'tor */
timestamp(const std::string & a_s)51 timestamp::timestamp(const std::string& a_s)
52 {
53 clear();
54 assign(a_s);
55 }
56
57 /** Set the timestamp to the current time and date */
set(void)58 void timestamp::set(void)
59 {
60 time_t t = 0;
61 struct tm* tm_ptr = 0;
62
63 t = time(0);
64 if (t == -1)
65 throw(ERROR(errno,"Could not retrieve current time"));
66 tm_ptr = localtime(&t);
67 if (tm_ptr == 0)
68 throw(ERROR(errno,"Could not convert current time to local time"));
69 m_year = tm_ptr->tm_year + 1900;
70 m_month = tm_ptr->tm_mon + 1;
71 m_day = tm_ptr->tm_mday;
72 m_hour = tm_ptr->tm_hour;
73 m_minute = tm_ptr->tm_min;
74 m_second = tm_ptr->tm_sec;
75 m_resolution = resolution_day;
76 }
77
78 /** Set the timestamp to the value of another timestamp */
assign(const timestamp & a_t)79 void timestamp::assign(const timestamp& a_t)
80 {
81 m_year = a_t.year();
82 m_month = a_t.month();
83 m_day = a_t.day();
84 m_hour = a_t.hour();
85 m_minute = a_t.minute();
86 m_second = a_t.second();
87 m_resolution = a_t.resolution();
88 }
89
90 /** Set the timestamp */
assign(const int a_year,const int a_month,const int a_day,const int a_hour,const int a_minute,const int a_second)91 void timestamp::assign(
92 const int a_year,
93 const int a_month,
94 const int a_day,
95 const int a_hour,
96 const int a_minute,
97 const int a_second
98 )
99 {
100 std::string es;
101
102 if ((a_year < 0) || (a_year > 9999)) {
103 TRY_nomem(es = "Invalid year: \"");
104 TRY_nomem(es += estring(a_year));
105 TRY_nomem(es += "\"");
106
107 throw(ERROR(0,es));
108 }
109 m_year = a_year;
110
111 if ((a_month > 12) || (a_month < 1)) {
112 TRY_nomem(es = "Invalid month: \"");
113 TRY_nomem(es += estring(a_month));
114 TRY_nomem(es += "\"");
115
116 throw(ERROR(0,es));
117 }
118 m_month = a_month;
119
120 if ((a_day > 31) || (a_day < 1)) {
121 TRY_nomem(es = "Invalid day: \"");
122 TRY_nomem(es += estring(a_day));
123 TRY_nomem(es += "\"");
124
125 throw(ERROR(0,es));
126 }
127 m_day = a_day;
128
129 if ((a_hour < 0) || (a_hour > 23)) {
130 TRY_nomem(es = "Invalid hour: \"");
131 TRY_nomem(es += estring(a_hour));
132 TRY_nomem(es += "\"");
133
134 throw(ERROR(0,es));
135 }
136 m_hour = a_hour;
137
138 if ((a_minute < 0) || (a_minute > 59)) {
139 TRY_nomem(es = "Invalid minute: \"");
140 TRY_nomem(es += estring(a_minute));
141 TRY_nomem(es += "\"");
142
143 throw(ERROR(0,es));
144 }
145 m_minute = a_minute;
146
147 if ((a_second < 0) || (a_second > 59)) {
148 TRY_nomem(es = "Invalid second: \"");
149 TRY_nomem(es += estring(a_second));
150 TRY_nomem(es += "\"");
151
152 throw(ERROR(0,es));
153 }
154 m_second = a_second;
155 }
156
157 /** Set the timestamp from a string */
assign(const std::string & a_s)158 void timestamp::assign(const std::string& a_s)
159 {
160 std::string bes;
161 std::string es;
162 std::string ies;
163
164 int l_year = -1;
165 int l_month = -1;
166 int l_day = -1;
167 int l_hour = -1;
168 int l_minute = -1;
169 int l_second = -1;
170 resolution_type r = resolution_day;
171
172 TRY_nomem(es = "Invalid timestamp string: \"");
173 TRY_nomem(es += a_s);
174 TRY_nomem(es += "\"");
175
176 if (!is_timestamp(a_s))
177 throw(ERROR(0,es));
178
179 TRY_nomem(bes = "Parse error converting string to timestamp: \"");
180 TRY_nomem(bes += a_s);
181 TRY_nomem(bes += "\" ");
182
183 TRY_nomem(es = bes + "Invalid year");
184 if (a_s.size() >= 4)
185 {
186 estring str;
187
188 r = resolution_year;
189 TRY_nomem(str = a_s.substr(0,4));
190 TRY(l_year = str,ies);
191 }
192 else
193 throw(ERROR(0,es));
194
195 if (a_s.size() == 4) {
196 assign(l_year,1,1,0,0,0);
197 resolution(r);
198 return;
199 }
200
201 TRY_nomem(es = bes + "Invalid month");
202 if (a_s.size() >= 7)
203 {
204 estring str;
205
206 r = resolution_month;
207 TRY_nomem(str = a_s.substr(5,2));
208 TRY(l_month = str,ies);
209 }
210 else
211 throw(ERROR(0,es));
212
213 if (a_s.size() == 7) {
214 assign(l_year,l_month,1,0,0,0);
215 resolution(r);
216 return;
217 }
218
219 TRY_nomem(es = bes + "Invalid day");
220 if (a_s.size() >= 10)
221 {
222 estring str;
223
224 r = resolution_day;
225 TRY_nomem(str = a_s.substr(8,2));
226 TRY(l_day = str,ies);
227 }
228 else
229 throw(ERROR(0,es));
230
231 if (a_s.size() == 10) {
232 assign(l_year,l_month,l_day,0,0,0);
233 resolution(r);
234 return;
235 }
236
237 TRY_nomem(es = bes + "Invalid hour");
238 if (a_s.size() >= 13)
239 {
240 estring str;
241
242 r = resolution_hour;
243 TRY_nomem(str = a_s.substr(11,2));
244 TRY(l_hour = str,ies);
245 }
246 else
247 throw(ERROR(0,es));
248
249 if (a_s.size() == 13) {
250 assign(l_year,l_month,l_day,l_hour,0,0);
251 resolution(r);
252 return;
253 }
254
255 TRY_nomem(es = bes + "Invalid minute");
256 if (a_s.size() >= 15)
257 {
258 estring str;
259
260 r = resolution_minute;
261 TRY_nomem(str = a_s.substr(13,2));
262 TRY(l_minute = str,ies);
263 }
264 else
265 throw(ERROR(0,es));
266
267 if (a_s.size() == 15) {
268 assign(l_year,l_month,l_day,l_hour,l_minute,0);
269 resolution(r);
270 return;
271 }
272
273 TRY_nomem(es = bes + "Invalid second");
274 if (a_s.size() == 17)
275 {
276 estring str;
277
278 r = resolution_second;
279 TRY_nomem(str = a_s.substr(15,2));
280 TRY(l_second = str,ies);
281 }
282 else
283 throw(ERROR(0,es));
284
285 assign(l_year,l_month,l_day,l_hour,l_minute,l_second);
286 resolution(r);
287 }
288
289 /** Clear the timestamp */
clear(void)290 void timestamp::clear(void)
291 {
292 m_year = 0;
293 m_month = 0;
294 m_day = 0;
295 m_hour = 0;
296 m_minute = 0;
297 m_second = 0;
298 m_resolution = resolution_day;
299 }
300
301 /** Set the timestamp resolution */
resolution(timestamp::resolution_type a_r)302 void timestamp::resolution(timestamp::resolution_type a_r)
303 {
304 m_resolution = a_r;
305 }
306
307 /** Generate a string */
make_str_(const int a_resolution) const308 const std::string timestamp::make_str_(const int a_resolution) const
309 {
310 std::string bes;
311 std::string es;
312 std::string str;
313 estring tmp_str;
314
315 TRY_nomem(es = "Could not create timestamp string");
316
317 if (a_resolution >= resolution_year) {
318 tmp_str.width(4);
319 tmp_str.align(estring::right);
320 tmp_str.left_fillchar('0');
321 TRY_nomem(es = bes + ", error converting year");
322 TRY(tmp_str = year(),es);
323 TRY_nomem(str += tmp_str.fmt_str());
324 tmp_str.reset();
325 }
326
327 if (a_resolution >= resolution_month) {
328 TRY_nomem(es = bes);
329 TRY(str += "-",es);
330 tmp_str.width(2);
331 tmp_str.align(estring::right);
332 tmp_str.left_fillchar('0');
333 TRY_nomem(es = bes + ", error converting month");
334 TRY(tmp_str = month(),es);
335 TRY_nomem(str += tmp_str.fmt_str());
336 tmp_str.reset();
337 }
338
339 if (a_resolution >= resolution_day) {
340 TRY_nomem(es = bes);
341 TRY(str += "-",es);
342 tmp_str.width(2);
343 tmp_str.align(estring::right);
344 tmp_str.left_fillchar('0');
345 TRY_nomem(es = bes + ", error converting day");
346 TRY(tmp_str = day(),es);
347 TRY_nomem(str += tmp_str.fmt_str());
348 tmp_str.reset();
349 }
350
351 if (a_resolution >= resolution_hour) {
352 TRY_nomem(es = bes);
353 TRY(str += ".",es);
354 tmp_str.width(2);
355 tmp_str.align(estring::right);
356 tmp_str.left_fillchar('0');
357 TRY_nomem(es = bes + ", error converting hour");
358 TRY(tmp_str = hour(),es);
359 TRY_nomem(str += tmp_str.fmt_str());
360 tmp_str.reset();
361 }
362
363 if (a_resolution >= resolution_minute) {
364 tmp_str.width(2);
365 tmp_str.align(estring::right);
366 tmp_str.left_fillchar('0');
367 TRY_nomem(es = bes + ", error converting minute");
368 TRY(tmp_str = minute(),es);
369 TRY_nomem(str += tmp_str.fmt_str());
370 tmp_str.reset();
371 }
372
373 if (a_resolution >= resolution_second) {
374 tmp_str.width(2);
375 tmp_str.align(estring::right);
376 tmp_str.left_fillchar('0');
377 TRY_nomem(es = bes + ", error converting second");
378 TRY(tmp_str = second(),es);
379 TRY_nomem(str += tmp_str.fmt_str());
380 tmp_str.reset();
381 }
382
383 return(str);
384 }
385
386 /** Generate a string */
str(void) const387 const std::string timestamp::str(void) const
388 {
389 std::string str;
390
391 TRY_nomem(str = make_str_(m_resolution));
392
393 return(str);
394 }
395
396 /** Generate a string */
str(const timestamp::resolution_type a_resolution) const397 const std::string timestamp::str(
398 const timestamp::resolution_type a_resolution) const
399 {
400 std::string str;
401
402 TRY_nomem(str = make_str_(a_resolution));
403
404 return(str);
405 }
406
407 /** Return the timestamp second */
second(void) const408 int timestamp::second(void) const
409 {
410 return(m_second);
411 }
412
413 /** Return the timestamp minute */
minute(void) const414 int timestamp::minute(void) const
415 {
416 return(m_minute);
417 }
418
419 /** Return the timestamp hour */
hour(void) const420 int timestamp::hour(void) const
421 {
422 return(m_hour);
423 }
424
425 /** Return the timestamp day */
day(void) const426 int timestamp::day(void) const
427 {
428 return(m_day);
429 }
430
431 /** Return the timestamp month */
month(void) const432 int timestamp::month(void) const
433 {
434 return(m_month);
435 }
436
437 /** Return the timestamp year */
year(void) const438 int timestamp::year(void) const
439 {
440 return(m_year);
441 }
442
443 /** Return the timestamp resolution */
resolution(void) const444 timestamp::resolution_type timestamp::resolution(void) const
445 {
446 return(m_resolution);
447 }
448
449 /** Assignment */
operator =(const timestamp & a_t)450 timestamp& timestamp::operator = (const timestamp& a_t)
451 {
452 assign(a_t);
453
454 return(*this);
455 }
456
457 /** Assignment */
operator =(const std::string & a_s)458 timestamp& timestamp::operator = (const std::string& a_s)
459 {
460 assign(a_s);
461
462 return(*this);
463 }
464
465 /** Comparison */
operator <(const timestamp & a_t) const466 bool timestamp::operator < (const timestamp& a_t) const
467 {
468 resolution_type r;
469 bool value;
470
471 r = std::min(m_resolution, a_t.resolution());
472 value = (str(r) < a_t.str(r));
473
474 return(value);
475 }
476
477 /** Comparison */
operator >(const timestamp & a_t) const478 bool timestamp::operator > (const timestamp& a_t) const
479 {
480 resolution_type r;
481 bool value;
482
483 r = std::min(m_resolution, a_t.resolution());
484 value = (str(r) > a_t.str(r));
485
486 return(value);
487 }
488
489 /** Comparison */
operator ==(const timestamp & a_t) const490 bool timestamp::operator == (const timestamp& a_t) const
491 {
492 resolution_type r;
493 bool value;
494
495 r = std::min(m_resolution, a_t.resolution());
496 value = (str(r) == a_t.str(r));
497
498 return(value);
499 }
500
501 /** Return true if the string is a valid timestamp */
is_timestamp(const std::string & a_s)502 bool is_timestamp(const std::string& a_s)
503 {
504 estring str;
505 int i;
506
507 if (a_s.size() < 4) {
508 return(false);
509 }
510 if (!isdigit(a_s[0])) {
511 return(false);
512 }
513 if (!isdigit(a_s[1])) {
514 return(false);
515 }
516 if (!isdigit(a_s[2])) {
517 return(false);
518 }
519 if (!isdigit(a_s[3])) {
520 return(false);
521 }
522 TRY_nomem(str = a_s.substr(0,4));
523 try {
524 i = str;
525 }
526 catch(...) {
527 return(false);
528 }
529 if ((i < 0) || (i > 9999)) {
530 return(false);
531 }
532 if (a_s.size() == 4) {
533 return(true);
534 }
535
536 if (a_s.size() < 7) {
537 return(false);
538 }
539 if (a_s[4] != '-') {
540 return(false);
541 }
542 if (!isdigit(a_s[5])) {
543 return(false);
544 }
545 if (!isdigit(a_s[6])) {
546 return(false);
547 }
548 TRY_nomem(str = a_s.substr(5,2));
549 try {
550 i = str;
551 }
552 catch(...) {
553 return(false);
554 }
555 if ((i < 1) || (i > 12)) {
556 return(false);
557 }
558 if (a_s.size() == 7) {
559 return(true);
560 }
561
562 if (a_s.size() < 10) {
563 return(false);
564 }
565 if (a_s[7] != '-') {
566 return(false);
567 }
568 if (!isdigit(a_s[8])) {
569 return(false);
570 }
571 if (!isdigit(a_s[9])) {
572 return(false);
573 }
574 TRY_nomem(str = a_s.substr(8,2));
575 try {
576 i = str;
577 }
578 catch(...) {
579 return(false);
580 }
581 if ((i < 1) || (i > 31)) {
582 return(false);
583 }
584 if (a_s.size() == 10) {
585 return(true);
586 }
587
588 if (a_s.size() < 13) {
589 return(false);
590 }
591 if (a_s[10] != '.') {
592 return(false);
593 }
594 if (!isdigit(a_s[11])) {
595 return(false);
596 }
597 if (!isdigit(a_s[12])) {
598 return(false);
599 }
600 TRY_nomem(str = a_s.substr(11,2));
601 try {
602 i = str;
603 }
604 catch(...) {
605 return(false);
606 }
607 if ((i < 0) || (i > 23)) {
608 return(false);
609 }
610 if (a_s.size() == 13) {
611 return(true);
612 }
613
614 if (a_s.size() < 15) {
615 return(false);
616 }
617 if (!isdigit(a_s[13])) {
618 return(false);
619 }
620 if (!isdigit(a_s[14])) {
621 return(false);
622 }
623 TRY_nomem(str = a_s.substr(13,2));
624 try {
625 i = str;
626 }
627 catch(...) {
628 return(false);
629 }
630 if ((i < 0) || (i > 59)) {
631 return(false);
632 }
633 if (a_s.size() == 15) {
634 return(true);
635 }
636
637 if (a_s.size() < 17) {
638 return(false);
639 }
640 if (!isdigit(a_s[15])) {
641 return(false);
642 }
643 if (!isdigit(a_s[16])) {
644 return(false);
645 }
646 TRY_nomem(str = a_s.substr(15,2));
647 try {
648 i = str;
649 }
650 catch(...) {
651 return(false);
652 }
653 if ((i < 0) || (i > 59)) {
654 return(false);
655 }
656 if (a_s.size() == 17) {
657 return(true);
658 }
659
660 return(false);
661 }
662
663