rllib  1
rltime_v2.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  rltime_v2.cpp - description
3  -------------------
4  begin : Tue Jan 02 2001
5  copyright : (C) 2001 by R. Lehrig
6  email : lehrig@t-online.de
7  ***************************************************************************/
8 
9 /***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or modify *
12  * it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE as *
13  * published by the Free Software Foundation *
14  * *
15  ***************************************************************************/
16 #include "rltime_v2.h"
17 #include <stdio.h>
18 #include <string.h>
19 #include <time.h>
20 #include <sys/stat.h>
21 #include <math.h>
22 #include <stdlib.h>
23 
24 #ifdef RLUNIX
25 #include <sys/types.h>
26 #include <sys/time.h>
27 #include <unistd.h>
28 #endif
29 
30 #ifdef __VMS
31 #include <ssdef.h>
32 #include <iodef.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <starlet.h>
36 #include <descrip.h>
37 #include <lib$routines.h>
38 #include <libdef.h>
39 #include <jpidef.h>
40 typedef struct
41 {
42  short year;
43  short month;
44  short day;
45  short hour;
46  short min;
47  short sec;
48  short hth;
49 }
50 TDS;
51 typedef struct
52 {
53  long word_1;
54  long word_2;
55 }
57 #endif
58 
59 #ifdef RLWIN32
60 #include <windows.h>
61 #include <mmsystem.h>
62 
63 // gmtime_r can be defined by mingw
64 #ifndef gmtime_r
65 static struct tm* gmtime_r(const time_t* t, struct tm* r)
66 {
67  // gmtime is threadsafe in windows because it uses TLS
68  struct tm *theTm = gmtime(t);
69  if (theTm) {
70  *r = *theTm;
71  return r;
72  } else {
73  return 0;
74  }
75 }
76 #endif // gmtime_r
77 
78 // gmtime_r can be defined by mingw
79 #ifndef localtime_r
80 static struct tm* localtime_r(const time_t* t, struct tm* r)
81 {
82  // localtime is threadsafe in windows because it uses TLS
83  struct tm *theTm = localtime(t);
84  if (theTm) {
85  *r = *theTm;
86  return r;
87  } else {
88  return 0;
89  }
90 }
91 #endif // localtime_r
92 
93 #endif
94 
95 namespace ns_rltime_v2
96 {
97 
99 {
100  if (year)
101  {
102  // read members
103  tm t;
104  memset(&t, 0, sizeof(t));
105  t.tm_year = year - 1900;
106  t.tm_mon = month - 1;
107  t.tm_mday = day;
108  t.tm_hour = hour;
109  t.tm_min = minute;
110  t.tm_sec = second;
111 
112  // normalize milliseconds
113  while (millisecond > 1000)
114  {
115  ++t.tm_sec;
116  millisecond -= 1000;
117  }
118 
119  // normalize time structure
120  time_t ep = timegm(&t);
121  gmtime_r(&ep, &t);
122 
123  // set members
124  year = 1900 + t.tm_year;
125  month = 1 + t.tm_mon;
126  day = t.tm_mday;
127  hour = t.tm_hour;
128  minute = t.tm_min;
129  second = t.tm_sec;
130  }
131 }
132 
133 rlTime::rlTime(int Year, int Month, int Day, int Hour, int Minute, int Second, int Millisecond)
134 {
135  year = Year;
136  month = Month;
137  day = Day;
138  hour = Hour;
139  minute = Minute;
140  second = Second;
141  millisecond = Millisecond;
142 
143  normalizeAsDate();
144 }
145 
147 {
148 }
149 
150 const char *rlTime::version()
151 {
152  return __FILE__;
153 }
154 
155 void rlTime::setTimeFromString(const char *time_string)
156 {
157  year = 0;
158  month = 0;
159  day = 0;
160  hour = 0;
161  minute = 0;
162  second = 0;
163  millisecond = 0;
164  sscanf(time_string,"%d-%d-%d %d:%d:%d %d",&year,&month,&day, &hour,&minute,&second, &millisecond);
165  normalizeAsDate();
166 }
167 
168 void rlTime::setTimeFromIsoString(const char *iso_time_string)
169 {
170  year = 0;
171  month = 0;
172  day = 0;
173  hour = 0;
174  minute = 0;
175  second = 0;
176  millisecond = 0;
177  sscanf(iso_time_string,"%d-%d-%dT%d:%d:%d.%d",&year,&month,&day, &hour,&minute,&second, &millisecond);
178  normalizeAsDate();
179 }
180 
186 void rlTime::setTimeFromSeconds(double seconds)
187 { // we assume that the average month has 30.5 days
188  double mod = fmod(seconds*1000, 1000);
189  millisecond = (int) mod;
190 
191  mod = fmod(seconds, 60);
192  second = (int) mod;
193 
194  seconds /= 60;
195  mod = fmod(seconds, 60);
196  minute = (int) mod;
197 
198  seconds /= 60;
199  mod = fmod(seconds, 24);
200  hour = (int) mod;
201 
202  seconds /= 24;
203  mod = fmod(seconds, 30.5);
204  day = (int) mod;
205 
206  seconds /= 30.5;
207  mod = fmod(seconds, 12);
208  month = (int) mod;
209 
210  seconds /= 12;
211  year = (int) seconds;
212 }
213 
214 
215 const char *rlTime::getTimeString()
216 {
217  sprintf(time_string,"%04d-%02d-%02d %02d:%02d:%02d %03d",year, month, day, hour, minute, second, millisecond);
218  return time_string;
219 }
220 
221 const char *rlTime::getIsoTimeString()
222 {
223  sprintf(iso_time_string,"%04d-%02d-%02dT%02d:%02d:%02d.%03d",year, month, day, hour, minute, second, millisecond);
224  return iso_time_string;
225 }
226 
265 const char *rlTime::toString(const char *format)
266 {
267  // See:
268  // https://doc.qt.io/qt-5/qdatetime.html#toString
269  //
270  char buf[16];
271  char *dest = time_string;
272  while(*format != '\0')
273  {
274  if (strncmp(format,"dd",2) == 0)
275  {
276  sprintf(buf,"%02d",day);
277  strcpy(dest,buf);
278  dest += strlen(buf);
279  format += 2;
280  }
281  else if(strncmp(format,"d",1) == 0)
282  {
283  sprintf(buf,"%d",day);
284  strcpy(dest,buf);
285  dest += strlen(buf);
286  format += 1;
287  }
288  else if(strncmp(format,"MMM",3) == 0)
289  {
290  buf[0] = '\0';
291  if(month == 1) strcpy(buf,"Jan");
292  if(month == 2) strcpy(buf,"Feb");
293  if(month == 3) strcpy(buf,"Mar");
294  if(month == 4) strcpy(buf,"Apr");
295  if(month == 5) strcpy(buf,"May");
296  if(month == 6) strcpy(buf,"Jun");
297  if(month == 7) strcpy(buf,"Jul");
298  if(month == 8) strcpy(buf,"Aug");
299  if(month == 9) strcpy(buf,"Sep");
300  if(month == 10) strcpy(buf,"Oct");
301  if(month == 11) strcpy(buf,"Nov");
302  if(month == 12) strcpy(buf,"Dec");
303  strcpy(dest,buf);
304  dest += strlen(buf);
305  format += 3;
306  }
307  else if(strncmp(format,"MM",2) == 0)
308  {
309  sprintf(buf,"%02d",month);
310  strcpy(dest,buf);
311  dest += strlen(buf);
312  format += 2;
313  }
314  else if(strncmp(format,"M",1) == 0)
315  {
316  sprintf(buf,"%d",month);
317  strcpy(dest,buf);
318  dest += strlen(buf);
319  format += 1;
320  }
321  else if(strncmp(format,"yyyy",4) == 0)
322  {
323  sprintf(buf,"%4d",year);
324  strcpy(dest,buf);
325  dest += strlen(buf);
326  format += 4;
327  }
328  else if(strncmp(format,"yy",2) == 0)
329  {
330  sprintf(buf,"%4d",year);
331  strcpy(dest,&buf[2]);
332  dest += strlen(&buf[2]);
333  format += 2;
334  }
335  else if(strncmp(format,"hh",2) == 0)
336  {
337  if (hour > 12) sprintf(buf,"%02d", hour - 12);
338  else if(hour == 0) sprintf(buf,"%02d", 12);
339  else sprintf(buf,"%02d", hour);
340  strcpy(dest,buf);
341  dest += strlen(buf);
342  format += 2;
343  }
344  else if(strncmp(format,"h",1) == 0)
345  {
346  if (hour > 12) sprintf(buf,"%2d", hour - 12);
347  else if(hour == 0) sprintf(buf,"%2d", 12);
348  else sprintf(buf,"%2d", hour);
349  strcpy(dest,buf);
350  dest += strlen(buf);
351  format += 1;
352  }
353  else if(strncmp(format,"HH",2) == 0)
354  {
355  sprintf(buf,"%02d",hour);
356  strcpy(dest,buf);
357  dest += strlen(buf);
358  format += 2;
359  }
360  else if(strncmp(format,"H",1) == 0)
361  {
362  sprintf(buf,"%d",hour);
363  strcpy(dest,buf);
364  dest += strlen(buf);
365  format += 1;
366  }
367  else if(strncmp(format,"mm",2) == 0)
368  {
369  sprintf(buf,"%02d",minute);
370  strcpy(dest,buf);
371  dest += strlen(buf);
372  format += 2;
373  }
374  else if(strncmp(format,"m",1) == 0)
375  {
376  sprintf(buf,"%d",minute);
377  strcpy(dest,buf);
378  dest += strlen(buf);
379  format += 1;
380  }
381  else if(strncmp(format,"ss",2) == 0)
382  {
383  sprintf(buf,"%02d",second);
384  strcpy(dest,buf);
385  dest += strlen(buf);
386  format += 2;
387  }
388  else if(strncmp(format,"s",1) == 0)
389  {
390  sprintf(buf,"%d",second);
391  strcpy(dest,buf);
392  dest += strlen(buf);
393  format += 1;
394  }
395  else if(strncmp(format,"zzz",3) == 0)
396  {
397  sprintf(buf,"%03d",millisecond);
398  strcpy(dest,buf);
399  dest += strlen(buf);
400  format += 3;
401  }
402  else if(strncmp(format,"z",1) == 0)
403  {
404  sprintf(buf,"%d",millisecond);
405  strcpy(dest,buf);
406  dest += strlen(buf);
407  format += 1;
408  }
409  else if(strncmp(format,"AP",2) == 0)
410  {
411  if (hour == 0) strcpy(dest,"PM");
412  else if(hour < 13) strcpy(dest,"AM");
413  else strcpy(dest,"PM");
414  dest += strlen("AM");
415  format += 2;
416  }
417  else if(strncmp(format,"ap",2) == 0)
418  {
419  if (hour == 0) strcpy(dest,"pm");
420  else if(hour < 13) strcpy(dest,"am");
421  else strcpy(dest,"pm");
422  dest += strlen("am");
423  format += 2;
424  }
425  else if(strncmp(format,"A",1) == 0)
426  {
427  if (hour == 0) strcpy(dest,"PM");
428  else if(hour < 13) strcpy(dest,"AM");
429  else strcpy(dest,"PM");
430  dest += strlen("AM");
431  format += 1;
432  }
433  else if(strncmp(format,"a",1) == 0)
434  {
435  if (hour == 0) strcpy(dest,"pm");
436  else if(hour < 13) strcpy(dest,"am");
437  else strcpy(dest,"pm");
438  dest += strlen("am");
439  format += 1;
440  }
441  else
442  {
443  *dest++ = *format++;
444  }
445  if(dest - time_string + 6 > (int) sizeof(time_string)) break;
446  }
447  *dest = '\0';
448  return time_string;
449 }
450 
452 {
453 #ifdef RLUNIX
454  time_t t;
455  struct tm *tms;
456  struct tm tmsbuf;
457  struct timeval tv;
458  struct timezone tz;
459 
460  time(&t);
461  tms = localtime_r(&t, &tmsbuf);
462  gettimeofday(&tv, &tz);
463 
464  /* adjust year and month */
465  tms->tm_year += 1900;
466  tms->tm_mon += 1;
467 
468  millisecond = (int)tv.tv_usec / 1000;
469  second = (int)tms->tm_sec;
470  minute = (int)tms->tm_min;
471  hour = (int)tms->tm_hour;
472  day = (int)tms->tm_mday;
473  month = (int)tms->tm_mon;
474  year = (int)tms->tm_year;
475 #endif
476 
477 #ifdef __VMS
478  TDS tds;
479  sys$numtim(&tds, 0);
480  millisecond = (int)tds.hth * 10;
481  second = (int)tds.sec;
482  minute = (int)tds.min;
483  hour = (int)tds.hour;
484  day = (int)tds.day;
485  month = (int)tds.month;
486  year = (int)tds.year;
487 #endif
488 
489 #ifdef RLWIN32
490  SYSTEMTIME st;
491  GetLocalTime(&st);
492  millisecond = st.wMilliseconds;
493  second = st.wSecond;
494  minute = st.wMinute;
495  hour = st.wHour;
496  day = st.wDay;
497  month = st.wMonth;
498  year = st.wYear;
499 #endif
500 }
501 
502 int rlTime::getFileModificationTime(const char *filename)
503 {
504  struct stat statbuf;
505  struct tm *tms;
506  struct tm tmsbuf;
507 
508 #ifdef RLUNIX
509  if(lstat(filename,&statbuf)) return -1;
510 #else
511  if(stat(filename,&statbuf)) return -1;
512 #endif
513  tms = localtime_r(&statbuf.st_mtime, &tmsbuf);
514 
515  /* adjust year and month */
516  tms->tm_year += 1900;
517  tms->tm_mon += 1;
518 
519  millisecond = 0;
520  second = (int)tms->tm_sec;
521  minute = (int)tms->tm_min;
522  hour = (int)tms->tm_hour;
523  day = (int)tms->tm_mday;
524  month = (int)tms->tm_mon;
525  year = (int)tms->tm_year;
526 
527  return 0;
528 }
529 
531 {
532 #ifdef RLUNIX
533  struct timeval tv;
534  struct tm t;
535 
536  t.tm_mday = day;
537  t.tm_mon = month - 1;
538  t.tm_year = year - 1900;
539  t.tm_hour = hour;
540  t.tm_min = minute;
541  t.tm_sec = second;
542  tv.tv_sec = mktime(&t);
543  tv.tv_usec = 1000 * millisecond;
544  settimeofday(&tv,NULL);
545 #endif
546 
547 #ifdef __VMS
548  VAX_BIN_TIME vbt;
549  struct dsc$descriptor_s d_time;
550  char smonth[12][4],buf[64];
551 
552  // Initialize month array
553  memset (smonth , 0, sizeof(smonth));
554  memcpy (smonth [0], "JAN", 3);
555  memcpy (smonth [1], "FEB", 3);
556  memcpy (smonth [2], "MAR", 3);
557  memcpy (smonth [3], "APR", 3);
558  memcpy (smonth [4], "MAY", 3);
559  memcpy (smonth [5], "JUN", 3);
560  memcpy (smonth [6], "JUL", 3);
561  memcpy (smonth [7], "AUG", 3);
562  memcpy (smonth [8], "SEP", 3);
563  memcpy (smonth [9], "OCT", 3);
564  memcpy (smonth [10], "NOV", 3);
565  memcpy (smonth [11], "DEC", 3);
566  // Create time buffer
567  sprintf(buf, "%02d-%3.3s-%04d %02d:%02d:%02d.%02d",
568  day,
569  smonth[month-1],
570  year,
571  hour,
572  minute,
573  second,
574  millisecond / 10);
575 
576  // Fill string descriptor
577  d_time.dsc$w_length = strlen(buf);
578  d_time.dsc$b_dtype = DSC$K_DTYPE_T;
579  d_time.dsc$b_class = DSC$K_CLASS_S;
580  d_time.dsc$a_pointer = buf;
581  // Convert time buf to VAX bin time
582  sys$bintim(&d_time, &vbt);
583  // Set the system time
584  sys$setime(&vbt);
585 #endif
586 
587 #ifdef RLWIN32
588  SYSTEMTIME st;
589  st.wDay = day;
590  st.wMonth = month;
591  st.wYear = year;
592  st.wHour = hour;
593  st.wMinute = minute;
594  st.wSecond = second;
595  st.wMilliseconds = millisecond;
596  SetSystemTime(&st);
597 #endif
598 }
599 
601 {
602  rlTime t;
603  t = *this + time;
604  *this = t;
605  return *this;
606 }
607 
609 {
610  rlTime t;
611  t = *this - time;
612  *this = t;
613  return *this;
614 }
615 
616 rlTime rlTime::operator+(const rlTime &time) const
617 {
618  int maxmonth,y,m;
619  rlTime t;
620 
621  t.year = year + time.year;
622  t.month = month + time.month;
623  t.day = day + time.day;
624  t.hour = hour + time.hour;
625  t.minute = minute + time.minute;
626  t.second = second + time.second;
628 
629  y = t.year;
630  if(t.month > 12 || (t.month==12 && t.day==31 && t.hour>=24)) y++;
631  m = t.month;
632  if(t.month > 12 || (t.month==12 && t.day==31 && t.hour>=24)) m = 1;
633 
634  switch(m % 12)
635  {
636  case 1: // january
637  maxmonth = 31;
638  break;
639  case 2: // february
640  maxmonth = 28;
641  // Annus bisextilis (calendario Gregoriano)
642  if(y%4==0)
643  {
644  maxmonth = 29;
645  int hth = y % 100;
646  int special = y % 400; // 1900-+-2100-2200-2300-+-2500-2600-2700
647  if(hth == 0 && special != 0) maxmonth = 28;
648  }
649  break;
650  case 3: // march
651  maxmonth = 31;
652  break;
653  case 4: // april
654  maxmonth = 30;
655  break;
656  case 5: // may
657  maxmonth = 31;
658  break;
659  case 6: // june
660  maxmonth = 30;
661  break;
662  case 7: // july
663  maxmonth = 31;
664  break;
665  case 8: // august
666  maxmonth = 31;
667  break;
668  case 9: // september
669  maxmonth = 30;
670  break;
671  case 10: // october
672  maxmonth = 31;
673  break;
674  case 11: // november
675  maxmonth = 30;
676  break;
677  case 12: // december
678  maxmonth = 31;
679  break;
680  default:
681  maxmonth = 31;
682  break;
683  }
684 
685  if(t.millisecond >= 1000) { t.second++; t.millisecond -= 1000; }
686  if(t.second >= 60) { t.minute++; t.second -= 60; }
687  if(t.minute >= 60) { t.hour++, t.minute -= 60; }
688  if(t.hour >= 24) { t.day++; t.hour -= 24; }
689  if(t.day > maxmonth) { t.month++; t.day -= maxmonth; }
690  if(t.month > 12) { t.year++; t.month -= 12; }
691  return t;
692 }
693 
694 rlTime rlTime::operator-(const rlTime &time) const
695 {
696  int maxmonth,y,m;
697  rlTime t;
698 
699  y = 0;
700  t.year = year - time.year;
701  t.month = month - time.month;
702  t.day = day - time.day;
703  t.hour = hour - time.hour;
704  t.minute = minute - time.minute;
705  t.second = second - time.second;
707 
708  if(t.millisecond < 0) { t.second--; t.millisecond += 1000; }
709  if(t.second < 0) { t.minute--; t.second += 60; }
710  if(t.minute < 0) { t.hour--, t.minute += 60; }
711  if(t.hour < 0) { t.day--; t.hour += 24; }
712 
713  if(t.day < 0)
714  {
715  t.month--;
716  y = t.year;
717  m = t.month;
718  if(m <= 0) { m += 12; y--; }
719  switch(m % 12)
720  {
721  case 1: // january
722  maxmonth = 31;
723  break;
724  case 2: // february
725  maxmonth = 28;
726  // Annus bisextilis (calendario Gregoriano)
727  if(y%4==0)
728  {
729  maxmonth = 29;
730  int hth = y % 100;
731  int special = y % 400; // 1900-+-2100-2200-2300-+-2500-2600-2700
732  if(hth == 0 && special != 0) maxmonth = 28;
733  }
734  break;
735  case 3: // march
736  maxmonth = 31;
737  break;
738  case 4: // april
739  maxmonth = 30;
740  break;
741  case 5: // may
742  maxmonth = 31;
743  break;
744  case 6: // june
745  maxmonth = 30;
746  break;
747  case 7: // july
748  maxmonth = 31;
749  break;
750  case 8: // august
751  maxmonth = 31;
752  break;
753  case 9: // september
754  maxmonth = 30;
755  break;
756  case 10: // october
757  maxmonth = 31;
758  break;
759  case 11: // november
760  maxmonth = 30;
761  break;
762  case 12: // december
763  maxmonth = 31;
764  break;
765  default:
766  maxmonth = 31;
767  break;
768  }
769  t.day += maxmonth;
770  }
771 
772  if(y >= 0)
773  {
774  //printf("after christ was born. thus everything is ok.\n");
775  }
776  else
777  {
778  //printf("before christ was born. now also ok\n");
779  { t.month++; t.day -= 30; }
780  if(t.day < 30) { t.day++; t.hour -= 24; }
781  if(t.hour < 0 ) { t.hour++; t.minute -= 60; }
782  if(t.minute < 0 ) { t.minute++; t.second -= 60; }
783  if(t.second < 0 ) { t.second++; t.millisecond -= 1000; }
784  }
785 
786  return t;
787 }
788 
789 int rlTime::operator==(const rlTime &time) const
790 {
791  if(year != time.year) return 0;
792  if(month != time.month) return 0;
793  if(day != time.day) return 0;
794  if(hour != time.hour) return 0;
795  if(minute != time.minute) return 0;
796  if(second != time.second) return 0;
797  if(millisecond != time.millisecond) return 0;
798 
799  return 1;
800 }
801 
802 int rlTime::operator<(const rlTime &time) const
803 {
804  if(this->year < time.year) return 1;
805  else if(this->year == time.year)
806  {
807  if(this->month < time.month) return 1;
808  else if(this->month == time.month)
809  {
810  if(this->day < time.day) return 1;
811  else if(this->day == time.day)
812  {
813  if(this->hour < time.hour) return 1;
814  else if(this->hour == time.hour)
815  {
816  if(this->minute < time.minute) return 1;
817  else if(this->minute == time.minute)
818  {
819  if(this->second < time.second) return 1;
820  else if(this->second == time.second)
821  {
822  if(this->millisecond < time.millisecond) return 1;
823  }
824  }
825  }
826  }
827  }
828  }
829  return 0;
830 }
831 
832 int rlTime::operator<=(const rlTime &time) const
833 {
834  if((*this) == time) return 1;
835  if((*this) < time) return 1;
836  return 0;
837 }
838 
839 int rlTime::operator>(const rlTime &time) const
840 {
841  if(this->year > time.year) return 1;
842  else if(this->year == time.year)
843  {
844  if(this->month > time.month) return 1;
845  else if(this->month == time.month)
846  {
847  if(this->day > time.day) return 1;
848  else if(this->day == time.day)
849  {
850  if(this->hour > time.hour) return 1;
851  else if(this->hour == time.hour)
852  {
853  if(this->minute > time.minute) return 1;
854  else if(this->minute == time.minute)
855  {
856  if(this->second > time.second) return 1;
857  else if (this->second == time.second)
858  {
859  if(this->millisecond > time.millisecond) return 1;
860  }
861  }
862  }
863  }
864  }
865  }
866  return 0;
867 }
868 
869 int rlTime::operator>=(const rlTime &time) const
870 {
871  if((*this) == time) return 1;
872  if((*this) > time) return 1;
873  return 0;
874 }
875 
876 rlTime& rlTime::operator+=(time_t seconds)
877 {
878  if(0 > seconds) return this->operator -=(-seconds);
879  lldiv_t d = lldiv(seconds, time_t(60));
880  second += d.rem;
881  if(d.quot)
882  {
883  d = lldiv(d.quot, time_t(60));
884  minute += d.rem;
885  if(d.quot)
886  {
887  d = lldiv(d.quot, time_t(24));
888  hour += d.rem;
889  if (d.quot)
890  {
891  d = lldiv(d.quot, time_t(31));
892  day += d.rem;
893  if(d.quot)
894  {
895  d = lldiv(d.quot, time_t(12));
896  month += d.rem;
897  year += d.quot;
898  }
899  }
900  }
901  }
902  this->normalizeAsDate();
903  return *this;
904 }
905 
906 rlTime& rlTime::operator-=(time_t seconds)
907 {
908  if(0 > seconds) return this->operator +=(-seconds);
909  lldiv_t d = lldiv(seconds, time_t(60));
910  second -= d.rem;
911  if(second < 0)
912  {
913  ++d.quot;
914  second += 60;
915  }
916  if(d.quot)
917  {
918  d = lldiv(d.quot, time_t(60));
919  minute -= d.rem;
920  if(minute < 0)
921  {
922  ++d.quot;
923  minute += 60;
924  }
925  if(d.quot)
926  {
927  d = lldiv(d.quot, time_t(24));
928  hour -= d.rem;
929  if(hour < 0)
930  {
931  ++d.quot;
932  hour += 24;
933  }
934  if(d.quot)
935  {
936  d = lldiv(d.quot, time_t(31));
937  day -= d.rem;
938  if(day < 0)
939  {
940  ++d.quot;
941  day += 31;
942  }
943  if(d.quot)
944  {
945  d = lldiv(d.quot, time_t(12));
946  month -= d.rem;
947  if(month < 0)
948  {
949  ++d.quot;
950  month += 12;
951  }
952  year -= d.quot;
953  }
954  }
955  }
956  }
957  this->normalizeAsDate();
958  return *this;
959 }
960 
961 rlTime rlTime::operator+(time_t seconds) const
962 {
963  rlTime t(*this);
964 
965  t += seconds;
966  return t;
967 }
968 
969 rlTime rlTime::operator-(time_t seconds) const
970 {
971  rlTime t(*this);
972 
973  t -= seconds;
974  return t;
975 }
976 
977 // ???
978 //double rlTime::operator-(const rlTime &time) const
979 //{
980 // return this->secondsSinceEpoche() - time.secondsSinceEpoche();
981 //}
982 
983 rlTime& rlTime::operator+=(double seconds)
984 {
985  rlTime t, sec;
987  t = *this + sec;
988  *this = t;
989  return *this;
990 }
991 
992 rlTime& rlTime::operator-=(double seconds)
993 {
994  rlTime t, sec;
996  t = *this - sec;
997  *this = t;
998  return *this;
999 }
1000 
1001 rlTime rlTime::operator+(double seconds) const
1002 {
1003  rlTime t, sec;
1005  t = *this + sec;
1006  return t;
1007 }
1008 
1009 rlTime rlTime::operator-(double seconds) const
1010 {
1011  rlTime t, sec;
1013  t = *this - sec;
1014  return t;
1015 }
1016 
1017 time_t rlTime::timegm(struct tm* tm_)
1018 {
1019  time_t t = mktime(tm_);
1020  struct tm ltm;
1021  struct tm gtm;
1022  struct tm *lt = localtime_r(&t, &ltm);
1023  struct tm *gt = gmtime_r(&t, &gtm);
1024  time_t diff = mktime(lt) - mktime(gt);
1025  return t + diff;
1026 }
1027 
1029 {
1030  struct tm begin;
1031  struct tm test;
1032 
1033  memset(&begin,0,sizeof(tm));
1034  memset(&test,0,sizeof(tm));
1035 
1036  begin.tm_year = 70;
1037  begin.tm_mon = 0;
1038  begin.tm_mday = 2; // see below
1039  begin.tm_hour = 0;
1040  begin.tm_min = 0;
1041  begin.tm_sec = 0;
1042  begin.tm_isdst = 0;
1043 
1044  test.tm_year = year - 1900;
1045  test.tm_mon = month - 1;
1046  test.tm_mday = day;
1047  test.tm_hour = hour;
1048  test.tm_min = minute;
1049  test.tm_sec = second;
1050  test.tm_isdst = -1;
1051 
1052  time_t t0 = timegm(&begin) - 86400; // a weak workaround: on several platform (especially Windows 7 in Europe Timezones) mktime() is not capable of converting 1970-01-01T00:00:00 into seconds, because they try to convert it into UTC instead of localtime
1053  time_t t1 = mktime(&test); // this might be error prone, see above
1054 
1055  return difftime(t1,t0) + (((double) millisecond) / 1000);
1056 }
1057 
1062 double rlTime::seconds() const
1063 {
1064  double ret = (((double) millisecond) / 1000) + second + minute*60 + hour*60*60 + month*60*60*30.5 + year*60*60*30.5*12;
1065  return ret;
1066 }
1067 
1068 const char* rlTime::formatTimeDiff(double tdiff, enum FormatLargestUnit fmt, unsigned bufferLength, char* buffer)
1069 {
1070  if(0 < bufferLength)
1071  {
1072  if(not buffer) buffer = new char[bufferLength];
1073 
1074  bool isNegative = (tdiff < 0);
1075  tdiff = fabs(tdiff);
1076  int milliseconds = ((int) (tdiff * 1000)) % 1000;
1077  time_t seconds = (time_t) tdiff;
1078  lldiv_t minutes, hours, days, weeks;
1079 
1080  minutes = lldiv(seconds, 60);
1081 
1082  const char* fmtString = "%s%d:%02d.%03d";
1083  switch (fmt)
1084  {
1086  fmtString = "%s%d:%02d.%03d";
1087  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), minutes.quot, minutes.rem, milliseconds);
1088  break;
1090  fmtString = "%s%d:%02d:%02d.%03d";
1091  hours = lldiv(minutes.quot, 60);
1092  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), hours.quot, hours.rem, minutes.rem, milliseconds);
1093  break;
1095  fmtString = "%s%d:%02d:%02d:%02d.%03d";
1096  hours = lldiv(minutes.quot, 60);
1097  days = lldiv(hours.quot, 24);
1098  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), days.quot, days.rem, hours.rem, minutes.rem, milliseconds);
1099  break;
1101  fmtString = "%s%d:%d:%02d:%02d:%02d.%03d";
1102  hours = lldiv(minutes.quot, 60);
1103  days = lldiv(hours.quot, 24);
1104  weeks = lldiv(days.quot, 7);
1105  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), weeks.quot, weeks.rem, days.rem, hours.rem, minutes.rem, milliseconds);
1106  break;
1107  case MinutesSeconds:
1108  fmtString = "%s%d:%02d";
1109  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), minutes.quot, minutes.rem);
1110  break;
1111  case HoursMinutesSeconds:
1112  fmtString = "%s%d:%02d:%02d";
1113  hours = lldiv(minutes.quot, 60);
1114  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), hours.quot, hours.rem, minutes.rem);
1115  break;
1117  fmtString = "%s%d:%02d:%02d:%02d";
1118  hours = lldiv(minutes.quot, 60);
1119  days = lldiv(hours.quot, 24);
1120  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), days.quot, days.rem, hours.rem, minutes.rem);
1121  break;
1123  fmtString = "%s%d:%d:%02d:%02d:%02d";
1124  hours = lldiv(minutes.quot, 60);
1125  days = lldiv(hours.quot, 24);
1126  weeks = lldiv(days.quot, 7);
1127  snprintf(buffer, bufferLength, fmtString, (isNegative ? "-" : ""), weeks.quot, weeks.rem, days.rem, hours.rem, minutes.rem);
1128  break;
1129  }
1130  }
1131 
1132  return buffer;
1133 }
1134 
1135 const char* rlTime::formatTimeDiff(const rlTime& t1, const rlTime& t2, enum FormatLargestUnit fmt, unsigned bufferLength, char* buffer)
1136 {
1137  rlTime tdiff;
1138  tdiff = t2 - t1;
1139  return formatTimeDiff(tdiff.seconds(), fmt, bufferLength, buffer);
1140 }
1141 
1142 const char *rlTime::formatTimeDiffString(double tdiff, enum FormatLargestUnit fmt)
1143 {
1144  char strBuffer[32];
1145 
1146  const char* result = formatTimeDiff(tdiff, fmt, sizeof(strBuffer), strBuffer);
1147  int len = strlen(result);
1148  time_string[0] = '\0';
1149  if(len+1 < (int) sizeof(time_string)) strcpy(time_string, result);
1150  return time_string;
1151 }
1152 
1153 const char *rlTime::formatTimeDiffString(const rlTime& t1, const rlTime& t2, enum FormatLargestUnit fmt)
1154 {
1155  return formatTimeDiffString(t2 - t1, fmt);
1156 }
1157 
1158 } // end of namespace ns_rltime_v2
static time_t timegm(struct tm *tm_)
Definition: rltime_v2.cpp:1017
rlTime operator+(const rlTime &time) const
Definition: rltime_v2.cpp:616
"0:00:00:00.000", needs at least 15 bytes buffer
Definition: rltime_v2.h:96
int operator>=(const rlTime &time) const
Definition: rltime_v2.cpp:869
int getFileModificationTime(const char *filename)
Definition: rltime.cpp:164
"0:0:00:00:00.000", needs at least 17 bytes buffer
Definition: rltime_v2.h:97
double secondsSinceEpoche() const
Definition: rltime_v2.cpp:1028
int operator<(const rlTime &time) const
Definition: rltime_v2.cpp:802
#define RLWIN32
Definition: rldefine.h:42
const char * formatTimeDiffString(double, enum FormatLargestUnit=HoursMinutesSecondsFraction)
Caller chooses formatting template, default is Hours:Minutes:Seconds.Milliseconds, returned object manages string memory.
Definition: rltime_v2.cpp:1142
rlTime & operator-=(const rlTime &time)
Definition: rltime_v2.cpp:608
"0:00", needs at least 5 bytes buffer
Definition: rltime_v2.h:98
void setTimeFromString(const char *time_string)
Definition: rltime.cpp:78
const char * getIsoTimeString()
Definition: rltime.cpp:108
int operator==(const rlTime &time) const
Definition: rltime_v2.cpp:789
"0:00.000", needs at least 9 bytes buffer
Definition: rltime_v2.h:94
Definition: rltime.cpp:39
char iso_time_string[32]
Definition: rltime_v2.h:124
rlTime & operator+=(const rlTime &time)
Definition: rltime_v2.cpp:600
const char * toString(const char *format)
Definition: rltime_v2.cpp:265
"0:00:00", needs at least 8 bytes buffer
Definition: rltime_v2.h:99
static struct tm * gmtime_r(const time_t *t, struct tm *r)
Definition: rltime_v2.cpp:65
int operator>(const rlTime &time) const
Definition: rltime_v2.cpp:839
const char * getTimeString()
Definition: rltime.cpp:102
virtual ~rlTime()
Definition: rltime.cpp:74
rlTime(int Year=0, int Month=0, int Day=0, int Hour=0, int Minute=0, int Second=0, int Millisecond=0)
Definition: rltime.cpp:63
void setTimeFromIsoString(const char *iso_time_string)
Definition: rltime.cpp:90
char time_string[32 *2]
Definition: rltime_v2.h:123
"0:0:00:00:00", needs at least 13 bytes buffer
Definition: rltime_v2.h:101
void setTimeFromSeconds(double const seconds)
Definition: rltime_v2.cpp:186
int operator<=(const rlTime &time) const
Definition: rltime_v2.cpp:832
"0:00:00.000", needs at least 12 bytes buffer
Definition: rltime_v2.h:95
static const char * formatTimeDiff(double, enum FormatLargestUnit=HoursMinutesSecondsFraction, unsigned bufferLength=32, char *buffer=0)
Caller chooses formatting template, default is Hours:Minutes:Seconds.Milliseconds, caller provides buffer, or buffer must be deleted (delete[])
Definition: rltime_v2.cpp:1068
double seconds() const
Definition: rltime_v2.cpp:1062
"0:00:00:00", needs at least 11 bytes buffer
Definition: rltime_v2.h:100
rlTime operator-(const rlTime &time) const
Definition: rltime_v2.cpp:694
const char * version()
Definition: rltime_v2.cpp:150
static struct tm * localtime_r(const time_t *t, struct tm *r)
Definition: rltime_v2.cpp:80