ProviewR Programmer's Reference Manual  V6.1.4
co_time.c
Go to the documentation of this file.
1 
37 /* co_time.c -- Utilities for time management.
38  NOTE! to convert timespecs to tm's, the threadsafe version of localtime,
39  localtime_r must be used, which doesn't exist on DEC. */
40 
41 #include <ctype.h>
42 #ifdef OS_MACOS
43 #include <errno.h>
44 #endif
45 #include <math.h>
46 #include <stdio.h>
47 #include <stdlib.h>
48 
49 #include "co_string.h"
50 #include "co_time.h"
51 #include "co_time_msg.h"
52 
59 
60 #define assertAbs(p) \
61  do { \
62  pwr_Assert(p->tv_nsec >= 0 && p->tv_nsec < 1000000000); \
63  } while (0)
64 #define notATime(p) (p->tv_nsec < 0 || p->tv_nsec >= 1000000000)
65 
66 #define assertDelta(p) \
67  do { \
68  pwr_Assert((p->tv_sec > 0) ? (p->tv_nsec >= 0 && p->tv_nsec < 1000000000) \
69  : TRUE); \
70  pwr_Assert((p->tv_sec < 0) ? (p->tv_nsec <= 0 && p->tv_nsec > -1000000000) \
71  : TRUE); \
72  } while (0)
73 #define notADeltaTime(p) \
74  (((p->tv_sec > 0) && (p->tv_nsec < 0 || p->tv_nsec >= 1000000000)) \
75  || ((p->tv_sec == 0) \
76  && (p->tv_nsec <= -1000000000 || p->tv_nsec >= 1000000000)) \
77  || ((p->tv_sec < 0) && (p->tv_nsec > 0 || p->tv_nsec <= -1000000000)))
78 
79 #define ONEDAY 86400
80 
81 /* String representations of months. */
82 
83 static const char* monStr[] = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL",
84  "AUG", "SEP", "OCT", "NOV", "DEC" };
85 
86 #ifdef OS_MACOS
87 int clock_gettime(clockid_t clockid, struct timespec* pt)
88 {
89  if (clockid == CLOCK_REALTIME) {
90  struct timeval tv;
91 
92  gettimeofday(&tv, 0);
93 
94  pt->tv_sec = tv.tv_sec;
95  pt->tv_nsec = tv.tv_usec * 1000;
96  } else if (clockid == CLOCK_MONOTONIC) {
97  // TODO
98  struct timeval tv;
99 
100  gettimeofday(&tv, 0);
101 
102  pt->tv_sec = tv.tv_sec;
103  pt->tv_nsec = tv.tv_usec * 1000;
104  } else {
105  errno = EINVAL;
106  return -1;
107  }
108 
109  return 0;
110 }
111 #endif
112 
113 /* Validate data in struct tm. */
114 
115 static pwr_tStatus validateTm(struct tm* tms)
116 {
117  int year;
118 
119  /* Check generic ranges. */
120 
121  if (69 > tms->tm_year /*|| tms->tm_year > 137*/) /* EPOCH is 1970 end feb 2038 */
122  return TIME__RANGE;
123  else if (0 > tms->tm_mon || tms->tm_mon > 11)
124  return TIME__RANGE;
125  else if (1 > tms->tm_mday || tms->tm_mday > 31)
126  return TIME__RANGE;
127  else if (0 > tms->tm_hour || tms->tm_hour > 23)
128  return TIME__RANGE;
129  else if (0 > tms->tm_min || tms->tm_min > 59)
130  return TIME__RANGE;
131  else if (0 > tms->tm_sec
132  || tms->tm_sec > 59) /* Should be 61 according to POSIX */
133  return TIME__RANGE;
134 
135  /*
136  * validate date
137  */
138  switch (tms->tm_mon) {
139  case 1:
140  /* check for leap year */
141  year = tms->tm_year + 1900;
142  if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
143  if (tms->tm_mday > 29)
144  return TIME__RANGE;
145  } else {
146  if (tms->tm_mday > 28)
147  return TIME__RANGE;
148  }
149  break;
150 
151  case 3:
152  case 5:
153  case 8:
154  case 10:
155  if (tms->tm_mday > 30)
156  return TIME__RANGE;
157  break;
158 
159  case 0:
160  case 2:
161  case 4:
162  case 6:
163  case 7:
164  case 9:
165  case 11:
166  if (tms->tm_mday > 31)
167  return TIME__RANGE;
168  break;
169 
170  default:
171  return TIME__RANGE;
172  }
173  return TIME__SUCCESS;
174 }
175 
177 int time_IsNull(pwr_tTime* t1)
178 {
179  assertAbs(t1);
180 
181  return (t1->tv_sec == pwr_cNTime.tv_sec)
182  && (t1->tv_nsec == pwr_cNTime.tv_nsec);
183 }
184 
186 
199 pwr_tTime* time_Aadd(pwr_tTime* result, pwr_tTime* t, pwr_tDeltaTime* a)
200 {
201  pwr_tInt64 tv_nsec = t->tv_nsec + a->tv_nsec;
202  pwr_tInt64 tv_sec = t->tv_sec + a->tv_sec;
203  pwr_tTime* r = result;
204 
205  assertAbs(t);
206  assertDelta(a);
207 
208  if (result == NULL)
209  r = t;
210 
211  tv_sec += tv_nsec / 1000000000;
212  tv_nsec %= 1000000000;
213  if (tv_nsec < 0 && tv_sec > 0) {
214  tv_sec--;
215  tv_nsec += 1000000000;
216  } else if (tv_sec < 0 && tv_nsec > 0) {
217  tv_sec++;
218  tv_nsec -= 1000000000;
219  }
220 
221  r->tv_sec = tv_sec;
222  r->tv_nsec = tv_nsec;
223  return r;
224 }
225 
227 
240 pwr_tTime* time_Aadd_NE(pwr_tTime* result, pwr_tTime* t, pwr_tDeltaTime* a)
241 {
242  pwr_tInt64 tv_nsec = t->tv_nsec + a->tv_nsec;
243  pwr_tInt64 tv_sec = t->tv_sec + a->tv_sec;
244  pwr_tTime* r = result;
245 
246  if (result == NULL)
247  r = t;
248 
249  if (notATime(t) || notADeltaTime(a)) {
250  *r = pwr_cNotATime;
251  return r;
252  }
253 
254  tv_sec += tv_nsec / 1000000000;
255  tv_nsec %= 1000000000;
256  if (tv_nsec < 0 && tv_sec > 0) {
257  tv_sec--;
258  tv_nsec += 1000000000;
259  } else if (tv_sec < 0 && tv_nsec > 0) {
260  tv_sec++;
261  tv_nsec -= 1000000000;
262  }
263 
264  r->tv_sec = tv_sec;
265  r->tv_nsec = tv_nsec;
266  return r;
267 }
268 
270 
282 int time_Acomp(pwr_tTime* t1, pwr_tTime* t2)
283 {
284  static pwr_tTime null = { 0, 0 };
285 
286  if (t2 == NULL)
287  t2 = &null;
288 
289  assertAbs(t1);
290  assertAbs(t2);
291 
292  if (t1->tv_sec == t2->tv_sec) {
293  if (t1->tv_nsec == t2->tv_nsec)
294  return 0;
295  return ((t1->tv_nsec > t2->tv_nsec) ? 1 : -1);
296  } else
297  return ((t1->tv_sec > t2->tv_sec) ? 1 : -1);
298 }
299 
301 
312 int time_Acomp_NE(pwr_tTime* t1, pwr_tTime* t2)
313 {
314  static pwr_tTime null = { 0, 0 };
315 
316  if (t2 == NULL)
317  t2 = &null;
318 
319  if (notATime(t1) || notATime(t2))
320  return -2;
321 
322  if (t1->tv_sec == t2->tv_sec) {
323  if (t1->tv_nsec == t2->tv_nsec)
324  return 0;
325  return ((t1->tv_nsec > t2->tv_nsec) ? 1 : -1);
326  } else
327  return ((t1->tv_sec > t2->tv_sec) ? 1 : -1);
328 }
329 
331 
339 pwr_tDeltaTime* time_Adiff(pwr_tDeltaTime* r, pwr_tTime* t, pwr_tTime* s)
340 {
341  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
342  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
343 
344  pwr_Assert(r != NULL);
345  assertAbs(t);
346  assertAbs(s);
347 
348  tv_sec = tv_sec + tv_nsec / 1000000000;
349  tv_nsec = tv_nsec % 1000000000;
350  if (tv_nsec < 0 && tv_sec > 0) {
351  tv_sec--;
352  tv_nsec += 1000000000;
353  } else if (tv_sec < 0 && tv_nsec > 0) {
354  tv_sec++;
355  tv_nsec -= 1000000000;
356  }
357 
358  r->tv_sec = tv_sec;
359  r->tv_nsec = tv_nsec;
360 
361  return r;
362 }
363 
365 
373 pwr_tDeltaTime* time_Adiff_NE(pwr_tDeltaTime* r, pwr_tTime* t, pwr_tTime* s)
374 {
375  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
376  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
377 
378  if (r == NULL || notATime(t) || notATime(s)) {
379  *r = pwr_cNotADeltaTime;
380  return r;
381  }
382 
383  tv_sec = tv_sec + tv_nsec / 1000000000;
384  tv_nsec = tv_nsec % 1000000000;
385  if (tv_nsec < 0 && tv_sec > 0) {
386  tv_sec--;
387  tv_nsec += 1000000000;
388  } else if (tv_sec < 0 && tv_nsec > 0) {
389  tv_sec++;
390  tv_nsec -= 1000000000;
391  }
392 
393  r->tv_sec = tv_sec;
394  r->tv_nsec = tv_nsec;
395 
396  return r;
397 }
398 
400 
408 pwr_tTime* time_Asub(pwr_tTime* result, pwr_tTime* t, pwr_tDeltaTime* s)
409 {
410  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
411  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
412  pwr_tTime* r = result;
413 
414  assertAbs(t);
415  assertDelta(s);
416 
417  if (r == NULL)
418  r = t;
419 
420  tv_sec += tv_nsec / 1000000000;
421  tv_nsec %= 1000000000;
422  if (tv_nsec < 0 && tv_sec > 0) {
423  tv_sec--;
424  tv_nsec += 1000000000;
425  } else if (tv_sec < 0 && tv_nsec > 0) {
426  tv_sec++;
427  tv_nsec -= 1000000000;
428  }
429 
430  r->tv_sec = tv_sec;
431  r->tv_nsec = tv_nsec;
432  return r;
433 }
434 
436 
444 pwr_tTime* time_Asub_NE(pwr_tTime* result, pwr_tTime* t, pwr_tDeltaTime* s)
445 {
446  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
447  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
448  pwr_tTime* r = result;
449 
450  if (r == NULL)
451  r = t;
452 
453  if (notATime(t) || notADeltaTime(s)) {
454  *r = pwr_cNotATime;
455  return r;
456  }
457 
458  tv_sec += tv_nsec / 1000000000;
459  tv_nsec %= 1000000000;
460  if (tv_nsec < 0 && tv_sec > 0) {
461  tv_sec--;
462  tv_nsec += 1000000000;
463  } else if (tv_sec < 0 && tv_nsec > 0) {
464  tv_sec++;
465  tv_nsec -= 1000000000;
466  }
467 
468  r->tv_sec = tv_sec;
469  r->tv_nsec = tv_nsec;
470  return r;
471 }
472 
474 
485 {
486  pwr_tDeltaTime* r = result;
487 
488  assertDelta(t);
489 
490  if (r == NULL)
491  r = t;
492  else {
493  r->tv_sec = t->tv_sec;
494  r->tv_nsec = t->tv_nsec;
495  }
496 
497  if (r->tv_sec < 0)
498  r->tv_sec = -r->tv_sec;
499  if (r->tv_nsec < 0)
500  r->tv_nsec = -r->tv_nsec;
501 
502  return r;
503 }
504 
506 
517 {
518  pwr_tDeltaTime* r = result;
519 
520  if (r == NULL)
521  r = t;
522  else {
523  r->tv_sec = t->tv_sec;
524  r->tv_nsec = t->tv_nsec;
525  }
526 
527  if (notADeltaTime(t)) {
528  *r = pwr_cNotADeltaTime;
529  return r;
530  }
531 
532  if (r->tv_sec < 0)
533  r->tv_sec = -r->tv_sec;
534  if (r->tv_nsec < 0)
535  r->tv_nsec = -r->tv_nsec;
536 
537  return r;
538 }
539 
541 
549 {
550  pwr_tDeltaTime* r = result;
551  pwr_tInt64 tv_nsec, tv_sec;
552 
553  assertDelta(t);
554  assertDelta(a);
555 
556  if (result == NULL)
557  r = t;
558 
559  tv_nsec = t->tv_nsec + a->tv_nsec;
560  tv_sec = t->tv_sec + a->tv_sec + (tv_nsec / 1000000000);
561  tv_nsec = tv_nsec % 1000000000;
562 
563  if (tv_nsec < 0 && tv_sec > 0) {
564  tv_sec--;
565  tv_nsec += 1000000000;
566  } else if (tv_sec < 0 && tv_nsec > 0) {
567  tv_sec++;
568  tv_nsec -= 1000000000;
569  }
570 
571  r->tv_sec = tv_sec;
572  r->tv_nsec = tv_nsec;
573 
574  return r;
575 }
576 
578 
586 {
587  pwr_tDeltaTime* r = result;
588  pwr_tInt64 tv_nsec, tv_sec;
589 
590  if (result == NULL)
591  r = t;
592 
593  if (notADeltaTime(t) || notADeltaTime(a)) {
594  *r = pwr_cNotADeltaTime;
595  return r;
596  }
597 
598  tv_nsec = t->tv_nsec + a->tv_nsec;
599  tv_sec = t->tv_sec + a->tv_sec + (tv_nsec / 1000000000);
600  tv_nsec = tv_nsec % 1000000000;
601 
602  if (tv_nsec < 0 && tv_sec > 0) {
603  tv_sec--;
604  tv_nsec += 1000000000;
605  } else if (tv_sec < 0 && tv_nsec > 0) {
606  tv_sec++;
607  tv_nsec -= 1000000000;
608  }
609 
610  r->tv_sec = tv_sec;
611  r->tv_nsec = tv_nsec;
612 
613  return r;
614 }
615 
617 
630 {
631  static pwr_tDeltaTime null = { 0, 0 };
632 
633  if (t2 == NULL)
634  t2 = &null;
635 
636  assertDelta(t1);
637  assertDelta(t2);
638 
639  if (t1->tv_sec == t2->tv_sec) {
640  if (t1->tv_nsec == t2->tv_nsec)
641  return 0;
642  return ((t1->tv_nsec > t2->tv_nsec) ? 1 : -1);
643  }
644  return ((t1->tv_sec > t2->tv_sec) ? 1 : -1);
645 }
646 
648 
661 {
662  static pwr_tDeltaTime null = { 0, 0 };
663 
664  if (t2 == NULL)
665  t2 = &null;
666 
667  if (notADeltaTime(t1) || notADeltaTime(t2))
668  return -2;
669 
670  if (t1->tv_sec == t2->tv_sec) {
671  if (t1->tv_nsec == t2->tv_nsec)
672  return 0;
673  return ((t1->tv_nsec > t2->tv_nsec) ? 1 : -1);
674  }
675  return ((t1->tv_sec > t2->tv_sec) ? 1 : -1);
676 }
677 
679 
691 {
692  pwr_tDeltaTime* r = result;
693 
694  assertDelta(t);
695 
696  if (r == NULL)
697  r = t;
698  else {
699  r->tv_sec = t->tv_sec;
700  r->tv_nsec = t->tv_nsec;
701  }
702 
703  r->tv_sec = -r->tv_sec;
704  r->tv_nsec = -r->tv_nsec;
705 
706  return r;
707 }
708 
710 
722 {
723  pwr_tDeltaTime* r = result;
724 
725  if (r == NULL)
726  r = t;
727  else {
728  r->tv_sec = t->tv_sec;
729  r->tv_nsec = t->tv_nsec;
730  }
731 
732  if (notADeltaTime(t)) {
733  *r = pwr_cNotADeltaTime;
734  return r;
735  }
736 
737  r->tv_sec = -r->tv_sec;
738  r->tv_nsec = -r->tv_nsec;
739 
740  return r;
741 }
742 
744 
752 {
753  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
754  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
755  pwr_tDeltaTime* r = result;
756 
757  assertDelta(t);
758  assertDelta(s);
759 
760  if (r == NULL)
761  r = t;
762 
763  tv_sec = tv_sec + tv_nsec / 1000000000;
764  tv_nsec = tv_nsec % 1000000000;
765  if (tv_nsec < 0 && tv_sec > 0) {
766  tv_sec--;
767  tv_nsec += 1000000000;
768  } else if (tv_sec < 0 && tv_nsec > 0) {
769  tv_sec++;
770  tv_nsec -= 1000000000;
771  }
772 
773  r->tv_sec = tv_sec;
774  r->tv_nsec = tv_nsec;
775 
776  return r;
777 }
778 
780 
788 {
789  pwr_tInt64 tv_nsec = t->tv_nsec - s->tv_nsec;
790  pwr_tInt64 tv_sec = t->tv_sec - s->tv_sec;
791  pwr_tDeltaTime* r = result;
792 
793  if (r == NULL)
794  r = t;
795 
796  if (notADeltaTime(t) || notADeltaTime(s)) {
797  *r = pwr_cNotADeltaTime;
798  return r;
799  }
800 
801  tv_sec = tv_sec + tv_nsec / 1000000000;
802  tv_nsec = tv_nsec % 1000000000;
803  if (tv_nsec < 0 && tv_sec > 0) {
804  tv_sec--;
805  tv_nsec += 1000000000;
806  } else if (tv_sec < 0 && tv_nsec > 0) {
807  tv_sec++;
808  tv_nsec -= 1000000000;
809  }
810 
811  r->tv_sec = tv_sec;
812  r->tv_nsec = tv_nsec;
813 
814  return r;
815 }
816 
818 
820  pwr_tDeltaTime* dt, int hundreds, char* buf, int bufsize)
821 {
822  char tmpStr[32];
823  div_t day, hour, min;
824  pwr_tDeltaTime t;
825  int neg = 0;
826 
827  if (dt == NULL)
828  return TIME__IVDTIME;
829 
830  if (notADeltaTime(dt)) {
831  strncpy(buf, "NotADeltaTime", bufsize);
832  buf[bufsize - 1] = '\0';
833  return TIME__NADT;
834  }
835 
836  if (dt->tv_sec < 0 || dt->tv_nsec < 0) {
837  neg = 1;
838 #if defined(HW_X86_64) || defined(HW_ARM64)
839  t.tv_sec = labs(dt->tv_sec);
840  t.tv_nsec = labs(dt->tv_nsec);
841 #else
842  t.tv_sec = abs(dt->tv_sec);
843  t.tv_nsec = abs(dt->tv_nsec);
844 #endif
845  dt = &t;
846  }
847 
848  day = div(dt->tv_sec, 24 * 3600);
849  hour = div(day.rem, 3600);
850  min = div(hour.rem, 60);
851 
852  if (day.quot) {
853  if (hundreds) {
854  long int nsec = dt->tv_nsec / 10000000;
855  sprintf(tmpStr, "%s%d %d:%02d:%02d.%02ld", neg?"-":"", day.quot, hour.quot, min.quot,
856  min.rem, nsec);
857  } else
858  sprintf(
859  tmpStr, "%s%d %d:%02d:%02d", neg?"-":"", day.quot, hour.quot, min.quot, min.rem);
860  } else {
861  if (hundreds) {
862  long int nsec = dt->tv_nsec / 10000000;
863  sprintf(tmpStr, "%s%d:%02d:%02d.%02ld", neg?"-":"", hour.quot, min.quot, min.rem, nsec);
864  } else
865  sprintf(tmpStr, "%s%d:%02d:%02d", neg?"-":"", hour.quot, min.quot, min.rem);
866  }
867 
868  strncpy(buf, tmpStr, bufsize);
869  buf[bufsize - 1] = '\0';
870 
871  return TIME__SUCCESS;
872 }
873 
875 
879  pwr_tTime* ts, time_eFormat format, char* buf, int bufsize)
880 {
881  struct tm* tmpTm;
882  int buflen;
883  char tmpStr[16];
884  pwr_tTime time;
885  pwr_tTime* tp;
886 
887  if (ts && notATime(ts)) {
888  strncpy(buf, "NotATime", bufsize);
889  buf[bufsize - 1] = '\0';
890  return TIME__NAT;
891  }
892 
893  if (ts == NULL) {
894  time_GetTime(&time);
895  tp = &time;
896  } else
897  tp = ts;
898 
899  time_t sec = tp->tv_sec;
900  tmpTm = localtime(&sec);
901  if (!tmpTm || EVEN(time_TmToAscii(tmpTm, format, buf, bufsize)))
902  return TIME__RANGE;
903 
904  buflen = strlen(buf);
905  switch (format) {
909  break;
910  default:
911  sprintf(tmpStr, ".%02d", (int)(tp->tv_nsec / 10000000));
912  if (strlen(tmpStr) + buflen < (unsigned int)bufsize)
913  strcpy(&buf[buflen], tmpStr);
914  }
915 
916  return TIME__SUCCESS;
917 }
918 
921 {
922  static char buf[80];
923  time_AtoAscii(0, format, buf, sizeof(buf));
924  return buf;
925 }
926 
929 {
930  char *sp, *dp;
931  char buf[64];
932  int day, hour = 0, min, sec, hun = 0;
933  int useday = 1;
934  int neg = 0;
935 
936  if ( streq( tstr, "NotADeltaTime")) {
937  *ts = pwr_cNotADeltaTime;
938  return TIME__SUCCESS;
939  }
940  if (*tstr == '-') {
941  strncpy(buf, &tstr[1], sizeof(buf) - 1);
942  neg = 1;
943  }
944  else
945  strncpy(buf, tstr, sizeof(buf) - 1);
946  buf[sizeof(buf) - 1] = '\0';
947  sp = buf;
948 
949  day = strtoul(sp, &dp, 10);
950  if (dp == NULL)
951  return TIME__RANGE;
952 
953  if (*dp == ':') {
954  hour = day;
955  day = 0;
956  useday = 0;
957  if (hour > 23)
958  return TIME__RANGE;
959  } else if (*dp != ' ')
960  return TIME__RANGE;
961  sp = dp + 1;
962 
963  if (useday) {
964  if (day > 24855)
965  return TIME__RANGE;
966  hour = strtoul(sp, &dp, 10);
967  if (dp == NULL || *dp != ':' || hour > 23)
968  return TIME__RANGE;
969  sp = dp + 1;
970  }
971 
972  min = strtoul(sp, &dp, 10);
973  if (dp == NULL || *dp != ':' || min > 59)
974  return TIME__RANGE;
975  sp = dp + 1;
976 
977  sec = strtoul(sp, &dp, 10);
978  if ((dp && *dp && *dp != ' ' && *dp != '.') || sec > 59)
979  return TIME__RANGE;
980 
981  if (dp && *dp == '.') {
982  hun = strtoul(dp + 1, &dp, 10);
983  if ((dp && *dp && *dp != ' ') || hun > (10000000 - 1))
984  return TIME__RANGE;
985  }
986 
987  ts->tv_sec = day * 24 * 3600 + hour * 3600 + min * 60 + sec;
988  ts->tv_nsec = hun * 10000000;
989  if (neg) {
990  ts->tv_sec = -ts->tv_sec;
991  ts->tv_nsec = -ts->tv_nsec;
992  }
993 
994  return TIME__SUCCESS;
995 }
996 
998 
999 pwr_tStatus time_AsciiToA(const char* tstr, pwr_tTime* ts)
1000 {
1001  struct tm tmpTm;
1002  int tmphs = 0;
1003  char* dotp;
1004  char buf[64];
1005  pwr_tStatus sts;
1006 
1007  if ( streq( tstr, "NotATime")) {
1008  *ts = pwr_cNotATime;
1009  return TIME__SUCCESS;
1010  }
1011  strncpy(buf, tstr, sizeof(buf) - 1);
1012  buf[sizeof(buf) - 1] = '\0';
1013 
1014  if ((dotp = strchr(buf, '.'))) {
1015  int len;
1016  char* cp;
1017 
1018  *dotp = '\0';
1019  dotp++;
1020  len = strlen(dotp);
1021  if (len > 2) /* only hundreds of seconds */
1022  *(dotp + 2) = 0;
1023 
1024  if (*dotp == '0')
1025  dotp++; /* remove first zero */
1026  tmphs = strtoul(dotp, &cp, 0);
1027  if (*cp)
1028  return TIME__RANGE;
1029  if (len == 1)
1030  tmphs *= 10;
1031  }
1032 
1033  sts = time_AsciiToTm(buf, &tmpTm);
1034  if (EVEN(sts))
1035  return sts;
1036 
1037  ts->tv_sec = mktime(&tmpTm);
1038  if (ts->tv_sec == -1)
1039  return TIME__RANGE;
1040  ts->tv_nsec = tmphs * 10000000;
1041  return TIME__SUCCESS;
1042 }
1043 
1045 
1047  struct tm* tmptr, time_eFormat format, char* buf, int bufsize)
1048 {
1049  pwr_tStatus sts;
1050 
1051  *buf = '\0';
1052  if (EVEN(sts = validateTm(tmptr)))
1053  return sts;
1054 
1055  if (format == time_eFormat_DateAndTime) {
1056  strftime(buf, bufsize, "%d-xxx-%Y %H:%M:%S", tmptr);
1057  strncpy(&buf[3], monStr[tmptr->tm_mon], 3);
1058  } else if (format == time_eFormat_DateAndTimeLoc) {
1059  strftime(buf, bufsize, "%d-%b-%Y %H:%M:%S", tmptr);
1060  } else if (format == time_eFormat_FileDateAndTime) {
1061  strftime(buf, bufsize, "%Y%m%d_%H%M%S", tmptr);
1062  } else if (format == time_eFormat_FileDate) {
1063  strftime(buf, bufsize, "%Y%m%d", tmptr);
1064  } else if (format == time_eFormat_ComprDateAndTime) {
1065  strftime(buf, bufsize, "%y-%m-%d %H:%M:%S", tmptr);
1066  } else if (format == time_eFormat_NumDateAndTime) {
1067  strftime(buf, bufsize, "%Y-%m-%d %H:%M:%S", tmptr);
1068  } else if (format == time_eFormat_TimeAndDate) {
1069  strftime(buf, bufsize, "%H:%M:%S %d/%m/%y", tmptr);
1070  } else {
1071  strftime(buf, bufsize, "%H:%M:%S", tmptr);
1072  }
1073 
1074  return TIME__SUCCESS;
1075 }
1076 
1078 
1079 pwr_tStatus time_AsciiToTm(const char* tstr, struct tm* tmptr)
1080 {
1081  char tmpMonStr[4];
1082  char* cp;
1083  struct tm tt;
1084  int i;
1085  pwr_tStatus sts;
1086  int monstr = 0;
1087 
1088  if (tstr[5] == '-') {
1089  sscanf(tstr, "%02d-%02d-%4d %02d:%02d:%02d", &tt.tm_mday, &tt.tm_mon,
1090  &tt.tm_year, &tt.tm_hour, &tt.tm_min, &tt.tm_sec);
1091  tt.tm_mon--;
1092  }
1093  else if (tstr[4] == '-') {
1094  sscanf(tstr, "%4d-%02d-%02d %02d:%02d:%02d", &tt.tm_year, &tt.tm_mon,
1095  &tt.tm_mday, &tt.tm_hour, &tt.tm_min, &tt.tm_sec);
1096  tt.tm_mon--;
1097  }
1098  else {
1099  sscanf(tstr, "%02d-%3c-%4d %02d:%02d:%02d", &tt.tm_mday, tmpMonStr,
1100  &tt.tm_year, &tt.tm_hour, &tt.tm_min, &tt.tm_sec);
1101  monstr = 1;
1102  }
1103 
1104  tmpMonStr[3] = '\0';
1105  tt.tm_year -= 1900;
1106 
1107  /* We don't handle this in current version */
1108 
1109  tt.tm_wday = -1;
1110  tt.tm_yday = -1;
1111  tt.tm_isdst = -1;
1112 
1113  /* check month */
1114  if (monstr) {
1115  for (cp = tmpMonStr; *cp; cp++)
1116  *cp = toupper(*cp);
1117 
1118  tt.tm_mon = -1;
1119  for (i = 0; i < 12; i++) {
1120  if (streq(tmpMonStr, monStr[i])) {
1121  tt.tm_mon = i;
1122  break;
1123  }
1124  }
1125  }
1126 
1127  if (EVEN(sts = validateTm(&tt)))
1128  return sts;
1129 
1130  *tmptr = tt;
1131 
1132  return TIME__SUCCESS;
1133 }
1134 
1135 /* Compatibility-function that substitutes co_TimeToAsc. */
1136 
1137 pwr_tStatus time_FormAsciiToA(
1138  const char* tstr, short dissolution, short formType, pwr_tTime* ts)
1139 {
1140  struct tm tmpTm;
1141  int i;
1142  int year;
1143  int month;
1144  int day;
1145  int tmphs = 0;
1146  char* dotp;
1147  char buf[64];
1148  pwr_tStatus sts;
1149  char* cp = (char*)tstr;
1150 
1151  /* Format of the date string should be YYYY-MM-DD HH:MM[:SS.CC] */
1152  while (*cp && isspace(*cp))
1153  cp++;
1154 
1155  /* Get year */
1156  for (i = 0; i < 4; i++, cp++) {
1157  if (*cp == '\0' || !isdigit(*cp))
1158  return TIME__RANGE;
1159  buf[i] = *cp;
1160  }
1161  buf[i] = '\0';
1162  year = atoi(buf);
1163  if (*cp == '\0' || *cp != '-')
1164  return TIME__RANGE;
1165  cp++;
1166 
1167  /* Get month */
1168  for (i = 0; i < 2; i++, cp++) {
1169  if (*cp == '\0' || !isdigit(*cp))
1170  return TIME__RANGE;
1171  buf[i] = *cp;
1172  }
1173  buf[i] = '\0';
1174  month = atoi(buf) - 1;
1175  if (month < 0 || month > 11)
1176  return TIME__RANGE;
1177  if (*cp == '\0' || *cp != '-')
1178  return TIME__RANGE;
1179  cp++;
1180 
1181  /* Get Day */
1182  for (i = 0; i < 2; i++, cp++) {
1183  if (*cp == '\0' || !isdigit(*cp))
1184  return TIME__RANGE;
1185  buf[i] = *cp;
1186  }
1187  buf[i] = '\0';
1188  day = atoi(buf);
1189 
1190  /* Build a new date string on VMS format, dd-mmm-yyyy ...*/
1191  sprintf(buf, "%02d-%s-%d%s", day, monStr[month], year, cp);
1192 
1193  if (dissolution == MINUTE) {
1194  strcat(buf, ":00");
1195  } else if (dissolution == HUNDRED) {
1196  if ((dotp = strchr(buf, '.'))) {
1197  int len;
1198  char* cp;
1199 
1200  *dotp = '\0';
1201  dotp++;
1202  len = strlen(dotp);
1203  if (len > 2) /* only hundreds of seconds */
1204  *(dotp + 2) = 0;
1205 
1206  if (*dotp == '0')
1207  dotp++;
1208  tmphs = strtoul(dotp, &cp, 0);
1209  if (*cp)
1210  return TIME__RANGE;
1211  if (len == 1)
1212  tmphs *= 10;
1213  }
1214  }
1215 
1216  sts = time_AsciiToTm(buf, &tmpTm);
1217  if (EVEN(sts))
1218  return sts;
1219 
1220  ts->tv_sec = mktime(&tmpTm);
1221  ts->tv_nsec = tmphs * 10000000;
1222  return TIME__SUCCESS;
1223 }
1224 
1225 /* . */
1226 
1227 void time_AtoFormAscii(
1228  pwr_tTime* ts, short dissolution, short formType, char buf[], int bufsize)
1229 {
1230  int len;
1231  struct tm* tmpTm;
1232  char tmphs[16];
1233  pwr_tTime time, *tp;
1234 
1235  if (ts == NULL) {
1236  time_GetTime(&time);
1237  tp = &time;
1238  } else {
1239  tp = ts;
1240  }
1241 
1242  switch (formType) {
1243  case GB:
1244  case SWE:
1245  default: {
1246  time_t sec = tp->tv_sec;
1247  tmpTm = localtime(&sec);
1248 
1249  switch (dissolution) {
1250  case HUNDRED:
1251  len = strftime(buf, bufsize, "%Y-%m-%d %H:%M:%S", tmpTm);
1252  if (len != 0 && len + 4 <= bufsize) {
1253  sprintf(tmphs, ".%02d", (int)(tp->tv_nsec / 10000000));
1254  strcat(buf, tmphs);
1255  }
1256  break;
1257 
1258  case MINUTE:
1259  strftime(buf, bufsize, "%Y-%m-%d %H:%M", tmpTm);
1260  break;
1261 
1262  case SECOND:
1263  default:
1264  strftime(buf, bufsize, "%Y-%m-%d %H:%M:%S", tmpTm);
1265  break;
1266  }
1267  }
1268  }
1269 }
1270 
1272 
1276 {
1277  static pwr_tDeltaTime time;
1278  pwr_tDeltaTime* t = &time;
1279 
1280  if (dt != NULL)
1281  t = dt;
1282 
1283  t->tv_sec = ms / 1000;
1284  t->tv_nsec = (ms % 1000) * 1000000;
1285 
1286  return t;
1287 }
1288 
1290 
1294 {
1295  static pwr_tDeltaTime time;
1296  pwr_tDeltaTime* t = &time;
1297 
1298  if (dt != NULL)
1299  t = dt;
1300 
1301  if (isnan(f)) {
1302  *t = pwr_cNotADeltaTime;
1303  return t;
1304  }
1305 
1306  t->tv_sec = f;
1307  t->tv_nsec = (f - t->tv_sec) * 1e9;
1308 
1309  return t;
1310 }
1311 
1313 
1317 {
1318  static pwr_tDeltaTime time;
1319  pwr_tDeltaTime* t = &time;
1320 
1321  if (dt != NULL)
1322  t = dt;
1323 
1324  if (isnan(f)) {
1325  *t = pwr_cNotADeltaTime;
1326  return t;
1327  }
1328 
1329  t->tv_sec = f;
1330  t->tv_nsec = (f - t->tv_sec) * 1e9;
1331 
1332  return t;
1333 }
1334 
1336 
1341 {
1342  static pwr_tFloat32 flt;
1343  pwr_tFloat32* fp = &flt;
1344 
1345  if (f != NULL)
1346  fp = f;
1347 
1348  if (notADeltaTime(dt)) {
1349  *fp = NAN;
1350  return *fp;
1351  }
1352 
1353  *fp = 1e-9 * dt->tv_nsec + dt->tv_sec;
1354 
1355  return *fp;
1356 }
1357 
1359 
1361 {
1362  static pwr_tFloat64 flt;
1363  pwr_tFloat64* fp = &flt;
1364 
1365  if (f != NULL)
1366  fp = f;
1367 
1368  if (notADeltaTime(dt)) {
1369  *fp = NAN;
1370  return *fp;
1371  }
1372 
1373  *fp = 1e-9 * dt->tv_nsec + dt->tv_sec;
1374 
1375  return *fp;
1376 }
1377 
1379 time_tClock time_DtoClock(pwr_tStatus* status, pwr_tDeltaTime* tp)
1380 {
1381  pwr_dStatus(sts, status, TIME__SUCCESS);
1382 
1383  return tp->tv_sec * 100 + tp->tv_nsec / 10000000;
1384 }
1385 
1388  pwr_tStatus* status, pwr_tDeltaTime* tp, time_tClock clock)
1389 {
1390  pwr_tDeltaTime time;
1391  pwr_dStatus(sts, status, TIME__SUCCESS);
1392 
1393  if (tp == NULL)
1394  tp = &time;
1395 
1396  tp->tv_sec = clock / 100;
1397  tp->tv_nsec = clock % 100 * 10000000;
1398 
1399  return tp;
1400 }
1401 
1404 {
1405  static pwr_tDeltaTime time;
1406 
1407  if (tp == NULL)
1408  tp = &time;
1409 
1410  memset(tp, 0, sizeof(*tp));
1411 
1412  return tp;
1413 }
1414 
1415 void time_Sleep(float time)
1416 {
1417  pwr_tDeltaTime p_time;
1418  struct timespec ts;
1419 
1420  time_FloatToD(&p_time, time);
1421  ts.tv_sec = p_time.tv_sec;
1422  ts.tv_nsec = p_time.tv_nsec;
1423  nanosleep(&ts, NULL);
1424 }
1425 
1427 int time_GetTime(pwr_tTime* ts)
1428 {
1429  struct timespec t;
1430  int sts;
1431 
1432  sts = clock_gettime(CLOCK_REALTIME, &t);
1433 
1434  ts->tv_sec = t.tv_sec;
1435  ts->tv_nsec = t.tv_nsec;
1436  return sts;
1437 }
1438 
1440 int time_GetTimeMonotonic(pwr_tTime* ts)
1441 {
1442  struct timespec t;
1443  int sts;
1444 
1445  sts = clock_gettime(CLOCK_MONOTONIC, &t);
1446 
1447  ts->tv_sec = t.tv_sec;
1448  ts->tv_nsec = t.tv_nsec;
1449  return sts;
1450 }
1451 
1454  pwr_tTime* time, pwr_tTime* from, pwr_tTime* to, int previous)
1455 {
1456  struct tm* tm;
1457  int days, month, year;
1458  time_t t;
1459  time_t sec = time->tv_sec;
1460 
1461  tm = localtime(&sec);
1462 
1463  sec = time->tv_sec - (tm->tm_mday - 1) * ONEDAY;
1464 
1465  tm = localtime(&sec);
1466 
1467  tm->tm_sec = 0;
1468  tm->tm_min = 0;
1469  tm->tm_hour = 0;
1470  tm->tm_mday = 1;
1471 
1472  t = mktime(tm);
1473 
1474  year = tm->tm_year + 1900;
1475  if (previous) {
1476  if (tm->tm_mon == 0) {
1477  month = 11;
1478  year--;
1479  } else
1480  month = tm->tm_mon - 1;
1481  } else
1482  month = tm->tm_mon;
1483 
1484  switch (month) {
1485  case 1:
1486  if ((year % 4 == 0 && year % 100 != 0) || (year + 1900) % 400 == 0)
1487  days = 29;
1488  else
1489  days = 28;
1490  break;
1491  case 3:
1492  case 5:
1493  case 8:
1494  case 10:
1495  days = 30;
1496  break;
1497  default:
1498  days = 31;
1499  }
1500 
1501  if (previous) {
1502  if (to) {
1503  to->tv_sec = t;
1504  to->tv_nsec = 0;
1505  }
1506  } else {
1507  if (from) {
1508  from->tv_sec = t;
1509  from->tv_nsec = 0;
1510  }
1511  }
1512 
1513  if (previous)
1514  sec = t - (days - 1) * ONEDAY;
1515  else
1516  sec = t + (days + 1) * ONEDAY;
1517 
1518  tm = localtime(&sec);
1519 
1520  tm->tm_sec = 0;
1521  tm->tm_min = 0;
1522  tm->tm_hour = 0;
1523  tm->tm_mday = 1;
1524 
1525  t = mktime(tm);
1526 
1527  if (previous) {
1528  if (from) {
1529  from->tv_sec = t;
1530  from->tv_nsec = 0;
1531  }
1532  } else {
1533  if (to) {
1534  to->tv_sec = t;
1535  to->tv_nsec = 0;
1536  }
1537  }
1538 
1539  return 1;
1540 }
1541 
1543 static int time_PeriodYear(
1544  pwr_tTime* time, pwr_tTime* from, pwr_tTime* to, int previous)
1545 {
1546  struct tm* tm;
1547  int days, year;
1548  time_t t;
1549  time_t sec = time->tv_sec;
1550 
1551  tm = localtime(&sec);
1552 
1553  sec = time->tv_sec - (tm->tm_yday - 1) * ONEDAY;
1554 
1555  tm = localtime(&sec);
1556 
1557  tm->tm_sec = 0;
1558  tm->tm_min = 0;
1559  tm->tm_hour = 0;
1560  tm->tm_mon = 0;
1561  tm->tm_mday = 1;
1562 
1563  t = mktime(tm);
1564 
1565  year = tm->tm_year + 1900;
1566  if (previous)
1567  year--;
1568 
1569  if ((year % 4 == 0 && year % 100 != 0) || (year + 1900) % 400 == 0)
1570  days = 365;
1571  else
1572  days = 366;
1573 
1574  if (previous) {
1575  if (to) {
1576  to->tv_sec = t;
1577  to->tv_nsec = 0;
1578  }
1579  } else {
1580  if (from) {
1581  from->tv_sec = t;
1582  from->tv_nsec = 0;
1583  }
1584  }
1585 
1586  if (previous)
1587  sec = t - (days - 1) * ONEDAY;
1588  else
1589  sec = t + (days + 1) * ONEDAY;
1590 
1591  tm = localtime(&sec);
1592 
1593  tm->tm_sec = 0;
1594  tm->tm_min = 0;
1595  tm->tm_hour = 0;
1596  tm->tm_mon = 0;
1597  tm->tm_mday = 1;
1598 
1599  t = mktime(tm);
1600 
1601  if (previous) {
1602  if (from) {
1603  from->tv_sec = t;
1604  from->tv_nsec = 0;
1605  }
1606  } else {
1607  if (to) {
1608  to->tv_sec = t;
1609  to->tv_nsec = 0;
1610  }
1611  }
1612 
1613  return 1;
1614 }
1615 
1617 
1622 int time_PeriodPreviousWeek(pwr_tTime* time, pwr_tTime* from, pwr_tTime* to)
1623 {
1624  struct tm* tm;
1625  int days;
1626  pwr_tTime t;
1627 
1628  time_t sec = time->tv_sec;
1629  tm = localtime(&sec);
1630  if (tm->tm_wday == 0) /* Sunday */
1631  days = 13;
1632  else
1633  days = tm->tm_wday + 6;
1634 
1635  tm->tm_sec = 0;
1636  tm->tm_min = 0;
1637  tm->tm_hour = 0;
1638  t.tv_sec = mktime(tm);
1639 
1640  if (from) {
1641  from->tv_sec = t.tv_sec - days * ONEDAY;
1642  from->tv_nsec = 0;
1643  }
1644  if (to) {
1645  to->tv_sec = t.tv_sec + (7 - days) * ONEDAY;
1646  to->tv_nsec = 0;
1647  }
1648 
1649  return 1;
1650 }
1651 
1653 void time_PreviousDayBreak(pwr_tTime* time, pwr_tTime* daybreak)
1654 {
1655  struct tm* tm;
1656 
1657  time_t sec = time->tv_sec;
1658  tm = localtime(&sec);
1659 
1660  tm->tm_sec = 0;
1661  tm->tm_min = 0;
1662  tm->tm_hour = 0;
1663 
1664  daybreak->tv_sec = mktime(tm);
1665  daybreak->tv_nsec = 0;
1666 }
1667 
1668 static void time_PeriodSec(
1669  pwr_tTime* from, pwr_tTime* to, pwr_tTime* center, int sec)
1670 {
1671  pwr_tStatus sts;
1672  pwr_tTime current;
1673 
1674  sts = time_GetTime(&current);
1675  to->tv_sec = center->tv_sec + sec / 2;
1676  to->tv_nsec = center->tv_nsec;
1677  if (time_Acomp(to, &current) == 1)
1678  *to = current;
1679  from->tv_sec = to->tv_sec - sec;
1680  from->tv_nsec = to->tv_nsec;
1681 }
1682 
1683 void time_Period(time_ePeriod period, pwr_tTime* from, pwr_tTime* to,
1684  pwr_tTime* center, int daybreak)
1685 {
1686  int sts;
1687  pwr_tTime current;
1688 
1689  switch (period) {
1690  case time_ePeriod_OneSecond:
1691  if (!center) {
1692  time_Period(time_ePeriod_LastSecond, from, to, center, daybreak);
1693  return;
1694  }
1695  time_PeriodSec(from, to, center, 1);
1696  break;
1697  case time_ePeriod_10Seconds:
1698  if (!center) {
1699  time_Period(time_ePeriod_10Seconds, from, to, center, daybreak);
1700  return;
1701  }
1702  time_PeriodSec(from, to, center, 10);
1703  break;
1704  case time_ePeriod_OneMinute:
1705  if (!center) {
1706  time_Period(time_ePeriod_LastMinute, from, to, center, daybreak);
1707  return;
1708  }
1709  time_PeriodSec(from, to, center, 60);
1710  break;
1711  case time_ePeriod_10Minutes:
1712  if (!center) {
1713  time_Period(time_ePeriod_Last10Minutes, from, to, center, daybreak);
1714  return;
1715  }
1716  time_PeriodSec(from, to, center, 600);
1717  break;
1718  case time_ePeriod_OneHour:
1719  if (!center) {
1720  time_Period(time_ePeriod_LastHour, from, to, center, daybreak);
1721  return;
1722  }
1723  time_PeriodSec(from, to, center, 3600);
1724  break;
1725  case time_ePeriod_OneDay:
1726  if (!center) {
1727  sts = time_GetTime(to);
1728  *from = *to;
1729  from->tv_sec -= ONEDAY;
1730  return;
1731  }
1732  time_PeriodSec(from, to, center, ONEDAY);
1733  break;
1734  case time_ePeriod_OneWeek:
1735  if (!center) {
1736  time_Period(time_ePeriod_LastWeek, from, to, center, daybreak);
1737  return;
1738  }
1739  time_PeriodSec(from, to, center, 7 * ONEDAY);
1740  break;
1741  case time_ePeriod_OneMonth:
1742  if (!center) {
1743  time_Period(time_ePeriod_LastMonth, from, to, center, daybreak);
1744  return;
1745  }
1746  time_PeriodMonth(center, from, to, 0);
1747  int middle = from->tv_sec + (to->tv_sec - from->tv_sec) / 2;
1748  int half = middle - from->tv_sec;
1749  if (center->tv_sec >= middle - ONEDAY / 2
1750  && center->tv_sec <= middle + ONEDAY / 2)
1751  return;
1752 
1753  if (center->tv_sec < middle) {
1754  // Take period from previous month
1755  time_PeriodMonth(center, from, to, 1);
1756  middle = from->tv_sec + (to->tv_sec - from->tv_sec) / 2;
1757  half = middle - from->tv_sec;
1758  }
1759  to->tv_sec = center->tv_sec + half;
1760  from->tv_sec = center->tv_sec - half;
1761 
1762  sts = time_GetTime(&current);
1763  if (time_Acomp(to, &current) == 1) {
1764  from->tv_sec = current.tv_sec - (to->tv_sec - from->tv_sec);
1765  from->tv_nsec = current.tv_sec;
1766  *to = current;
1767  }
1768  break;
1769  case time_ePeriod_LastSecond:
1770  sts = time_GetTime(to);
1771  from->tv_sec = to->tv_sec - 1;
1772  from->tv_nsec = to->tv_nsec;
1773  break;
1774  case time_ePeriod_Last10Seconds:
1775  sts = time_GetTime(to);
1776  from->tv_sec = to->tv_sec - 10;
1777  from->tv_nsec = to->tv_nsec;
1778  break;
1779  case time_ePeriod_LastMinute:
1780  sts = time_GetTime(to);
1781  from->tv_sec = to->tv_sec - 60;
1782  from->tv_nsec = to->tv_nsec;
1783  break;
1784  case time_ePeriod_Last10Minutes:
1785  sts = time_GetTime(to);
1786  from->tv_sec = to->tv_sec - 600;
1787  from->tv_nsec = to->tv_nsec;
1788  break;
1789  case time_ePeriod_LastHour:
1790  sts = time_GetTime(to);
1791  from->tv_sec = to->tv_sec - 3600;
1792  from->tv_nsec = to->tv_nsec;
1793  break;
1794  case time_ePeriod_Today:
1795  sts = time_GetTime(from);
1796  *to = *from;
1797 
1798  time_PreviousDayBreak(from, from);
1799 
1800  if (daybreak) {
1801  to->tv_sec += ONEDAY;
1802  time_PreviousDayBreak(to, to);
1803  }
1804  break;
1805  case time_ePeriod_Yesterday:
1806  sts = time_GetTime(to);
1807  time_PreviousDayBreak(to, to);
1808 
1809  from->tv_sec = to->tv_sec - ONEDAY;
1810  from->tv_nsec = 0;
1811  break;
1812  case time_ePeriod_ThisWeek:
1813  sts = time_GetTime(&current);
1814 
1815  sts = time_PeriodPreviousWeek(&current, 0, from);
1816 
1817  *to = current;
1818  if (daybreak) {
1819  to->tv_sec += ONEDAY;
1820  time_PreviousDayBreak(to, to);
1821  }
1822  break;
1823  case time_ePeriod_LastWeek:
1824  sts = time_GetTime(&current);
1825 
1826  sts = time_PeriodPreviousWeek(&current, from, to);
1827  break;
1828  case time_ePeriod_ThisMonth:
1829  sts = time_GetTime(&current);
1830 
1831  sts = time_PeriodMonth(&current, 0, from, 1);
1832 
1833  *to = current;
1834  if (daybreak) {
1835  to->tv_sec += ONEDAY;
1836  time_PreviousDayBreak(to, to);
1837  }
1838  break;
1839  case time_ePeriod_LastMonth:
1840  sts = time_GetTime(&current);
1841 
1842  sts = time_PeriodMonth(&current, from, to, 1);
1843  break;
1844  case time_ePeriod_OneYear:
1845  case time_ePeriod_ThisYear:
1846  sts = time_GetTime(&current);
1847 
1848  sts = time_PeriodYear(&current, 0, from, 1);
1849 
1850  *to = current;
1851  if (daybreak) {
1852  to->tv_sec += ONEDAY;
1853  time_PreviousDayBreak(to, to);
1854  }
1855  break;
1856  default: {
1857  // time_ePeriod_All:
1858  struct tm* tm;
1859 
1860  sts = time_GetTime(to);
1861  if (daybreak) {
1862  to->tv_sec += ONEDAY;
1863  time_PreviousDayBreak(to, to);
1864  }
1865 
1866  time_t sec = to->tv_sec;
1867  tm = localtime(&sec);
1868  tm->tm_sec = 0;
1869  tm->tm_min = 0;
1870  tm->tm_hour = 0;
1871  tm->tm_mday = 1;
1872  tm->tm_mon = 0;
1873  tm->tm_year = 70;
1874  from->tv_sec = mktime(tm);
1875  from->tv_nsec = 0;
1876 
1877  break;
1878  }
1879  }
1880 }
1881 
1882 void time_PreviousPeriod(time_ePeriod period, pwr_tTime* prev_from,
1883  pwr_tTime* prev_to, pwr_tTime* from, pwr_tTime* to)
1884 {
1885  switch (period) {
1886  case time_ePeriod_OneSecond:
1887  case time_ePeriod_LastSecond:
1888  *to = *from = *prev_from;
1889  from->tv_sec -= 1;
1890  if (from->tv_sec < 0) {
1891  from->tv_sec = 0;
1892  to->tv_sec = 1;
1893  }
1894  break;
1895  case time_ePeriod_10Seconds:
1896  case time_ePeriod_Last10Seconds:
1897  *to = *from = *prev_from;
1898  from->tv_sec -= 10;
1899  if (from->tv_sec < 0) {
1900  from->tv_sec = 0;
1901  to->tv_sec = 10;
1902  }
1903  break;
1904  case time_ePeriod_OneMinute:
1905  case time_ePeriod_LastMinute:
1906  *to = *from = *prev_from;
1907  from->tv_sec -= 60;
1908  if (from->tv_sec < 0) {
1909  from->tv_sec = 0;
1910  to->tv_sec = 60;
1911  }
1912  break;
1913  case time_ePeriod_10Minutes:
1914  case time_ePeriod_Last10Minutes:
1915  *to = *from = *prev_from;
1916  from->tv_sec -= 600;
1917  if (from->tv_sec < 0) {
1918  from->tv_sec = 0;
1919  to->tv_sec = 600;
1920  }
1921  break;
1922  case time_ePeriod_OneHour:
1923  case time_ePeriod_LastHour:
1924  *to = *from = *prev_from;
1925  from->tv_sec -= 3600;
1926  if (from->tv_sec < 0) {
1927  from->tv_sec = 0;
1928  to->tv_sec = 3660;
1929  }
1930  break;
1931  case time_ePeriod_OneDay:
1932  case time_ePeriod_Today:
1933  case time_ePeriod_Yesterday:
1934  *to = *from = *prev_from;
1935  from->tv_sec -= ONEDAY;
1936  if (from->tv_sec < 0) {
1937  from->tv_sec = 0;
1938  to->tv_sec = ONEDAY;
1939  }
1940  break;
1941  case time_ePeriod_OneWeek:
1942  case time_ePeriod_ThisWeek:
1943  case time_ePeriod_LastWeek:
1944  *to = *from = *prev_from;
1945  from->tv_sec -= ONEDAY * 7;
1946  if (from->tv_sec < 0) {
1947  from->tv_sec = 0;
1948  to->tv_sec = ONEDAY * 7;
1949  }
1950  break;
1951  case time_ePeriod_OneMonth:
1952  case time_ePeriod_ThisMonth:
1953  case time_ePeriod_LastMonth:
1954  time_PeriodMonth(prev_from, from, to, 1);
1955  from->tv_sec += prev_from->tv_sec - to->tv_sec;
1956  from->tv_nsec = prev_from->tv_nsec;
1957  *to = *prev_from;
1958  if (from->tv_sec < 0) {
1959  from->tv_sec = 0;
1960  to->tv_sec = ONEDAY * 30;
1961  }
1962  break;
1963  case time_ePeriod_OneYear:
1964  case time_ePeriod_ThisYear:
1965  time_PeriodYear(prev_from, from, to, 1);
1966  from->tv_sec += prev_from->tv_sec - to->tv_sec;
1967  from->tv_nsec = prev_from->tv_nsec;
1968  *to = *prev_from;
1969  if (from->tv_sec < 0) {
1970  from->tv_sec = 0;
1971  to->tv_sec = ONEDAY * 365;
1972  }
1973  break;
1974  case time_ePeriod_AllTime:
1975  time_Period(period, from, to, 0, 1);
1976  break;
1977  case time_ePeriod_UserDefined:
1978  // Same lenth of intervall as before
1979  *to = *from = *prev_from;
1980  from->tv_sec -= prev_to->tv_sec - prev_from->tv_sec;
1981  if (from->tv_sec < 0) {
1982  from->tv_sec = 0;
1983  to->tv_sec = prev_to->tv_sec - prev_from->tv_sec;
1984  }
1985  break;
1986  default:;
1987  }
1988 }
1989 
1990 void time_NextPeriod(time_ePeriod period, pwr_tTime* prev_from,
1991  pwr_tTime* prev_to, pwr_tTime* from, pwr_tTime* to)
1992 {
1993  int sts;
1994  pwr_tTime current;
1995 
1996  sts = time_GetTime(&current);
1997 
1998  switch (period) {
1999  case time_ePeriod_OneSecond:
2000  case time_ePeriod_LastSecond:
2001  *to = *from = *prev_to;
2002  to->tv_sec += 1;
2003  if (time_Acomp(&current, to) != 1) {
2004  *to = current;
2005  from->tv_sec = current.tv_sec - 1;
2006  from->tv_nsec = current.tv_nsec;
2007  }
2008  break;
2009  case time_ePeriod_10Seconds:
2010  case time_ePeriod_Last10Seconds:
2011  *to = *from = *prev_to;
2012  to->tv_sec += 10;
2013  if (time_Acomp(&current, to) != 1) {
2014  *to = current;
2015  from->tv_sec = current.tv_sec - 10;
2016  from->tv_nsec = current.tv_nsec;
2017  }
2018  break;
2019  case time_ePeriod_OneMinute:
2020  case time_ePeriod_LastMinute:
2021  *to = *from = *prev_to;
2022  to->tv_sec += 60;
2023  if (time_Acomp(&current, to) != 1) {
2024  *to = current;
2025  from->tv_sec = current.tv_sec - 60;
2026  from->tv_nsec = current.tv_nsec;
2027  }
2028  break;
2029  case time_ePeriod_10Minutes:
2030  case time_ePeriod_Last10Minutes:
2031  *to = *from = *prev_to;
2032  to->tv_sec += 600;
2033  if (time_Acomp(&current, to) != 1) {
2034  *to = current;
2035  from->tv_sec = current.tv_sec - 600;
2036  from->tv_nsec = current.tv_nsec;
2037  }
2038  break;
2039  case time_ePeriod_OneHour:
2040  case time_ePeriod_LastHour:
2041  *to = *from = *prev_to;
2042  to->tv_sec += 3600;
2043  if (time_Acomp(&current, to) != 1) {
2044  *to = current;
2045  from->tv_sec = current.tv_sec - 3600;
2046  from->tv_nsec = current.tv_nsec;
2047  }
2048  break;
2049  case time_ePeriod_OneDay:
2050  case time_ePeriod_Today:
2051  case time_ePeriod_Yesterday:
2052  *to = *from = *prev_to;
2053  to->tv_sec += ONEDAY;
2054  if (time_Acomp(&current, to) != 1) {
2055  *to = current;
2056  from->tv_sec = current.tv_sec - ONEDAY;
2057  from->tv_nsec = current.tv_nsec;
2058  }
2059  break;
2060  case time_ePeriod_OneWeek:
2061  case time_ePeriod_ThisWeek:
2062  case time_ePeriod_LastWeek:
2063  *to = *from = *prev_to;
2064  to->tv_sec += 7 * ONEDAY;
2065  if (time_Acomp(&current, to) != 1) {
2066  *to = current;
2067  from->tv_sec = current.tv_sec - 7 * ONEDAY;
2068  from->tv_nsec = current.tv_nsec;
2069  }
2070  break;
2071  case time_ePeriod_OneMonth:
2072  case time_ePeriod_ThisMonth:
2073  case time_ePeriod_LastMonth:
2074  time_PeriodMonth(prev_to, from, to, 0);
2075  to->tv_sec += prev_to->tv_sec - from->tv_sec;
2076  *from = *prev_to;
2077  if (time_Acomp(&current, to) != 1) {
2078  *to = current;
2079  from->tv_sec = current.tv_sec - 30 * ONEDAY;
2080  from->tv_nsec = current.tv_nsec;
2081  }
2082  break;
2083  case time_ePeriod_OneYear:
2084  case time_ePeriod_ThisYear:
2085  time_PeriodYear(prev_to, from, to, 0);
2086  to->tv_sec += prev_to->tv_sec - from->tv_sec;
2087  *from = *prev_to;
2088  if (time_Acomp(&current, to) != 1) {
2089  *to = current;
2090  from->tv_sec = current.tv_sec - 365 * ONEDAY;
2091  from->tv_nsec = current.tv_nsec;
2092  }
2093  break;
2094  case time_ePeriod_AllTime:
2095  time_Period(period, from, to, 0, 1);
2096  break;
2097  case time_ePeriod_UserDefined:
2098  // Same lenth of intervall as before
2099  *to = *from = *prev_to;
2100  to->tv_sec += prev_to->tv_sec - prev_from->tv_sec;
2101  if (time_Acomp(&current, to) != 1) {
2102  *to = current;
2103  from->tv_sec = current.tv_sec - (prev_to->tv_sec - prev_from->tv_sec);
2104  from->tv_nsec = current.tv_nsec;
2105  }
2106  break;
2107  default:;
2108  }
2109 }
2110 
2111 int time_PeriodZoomIn(time_ePeriod* period)
2112 {
2113  int changed = 1;
2114  switch (*period) {
2115  case time_ePeriod_Last10Seconds:
2116  case time_ePeriod_10Seconds:
2117  *period = time_ePeriod_OneSecond;
2118  break;
2119  case time_ePeriod_LastMinute:
2120  case time_ePeriod_OneMinute:
2121  *period = time_ePeriod_10Seconds;
2122  break;
2123  case time_ePeriod_Last10Minutes:
2124  case time_ePeriod_10Minutes:
2125  *period = time_ePeriod_OneMinute;
2126  break;
2127  case time_ePeriod_OneHour:
2128  case time_ePeriod_LastHour:
2129  *period = time_ePeriod_10Minutes;
2130  break;
2131  case time_ePeriod_Today:
2132  case time_ePeriod_Yesterday:
2133  case time_ePeriod_OneDay:
2134  *period = time_ePeriod_OneHour;
2135  break;
2136  case time_ePeriod_ThisWeek:
2137  case time_ePeriod_LastWeek:
2138  case time_ePeriod_OneWeek:
2139  *period = time_ePeriod_OneDay;
2140  break;
2141  case time_ePeriod_ThisMonth:
2142  case time_ePeriod_LastMonth:
2143  case time_ePeriod_OneMonth:
2144  *period = time_ePeriod_OneWeek;
2145  break;
2146  case time_ePeriod_ThisYear:
2147  case time_ePeriod_OneYear:
2148  *period = time_ePeriod_OneMonth;
2149  break;
2150  case time_ePeriod_AllTime:
2151  *period = time_ePeriod_OneYear;
2152  break;
2153  default:
2154  changed = 0;
2155  }
2156  return changed;
2157 }
2158 
2159 int time_PeriodZoomOut(time_ePeriod* period)
2160 {
2161  int changed = 1;
2162 
2163  switch (*period) {
2164  case time_ePeriod_OneSecond:
2165  case time_ePeriod_LastSecond:
2166  *period = time_ePeriod_10Seconds;
2167  break;
2168  case time_ePeriod_Last10Seconds:
2169  case time_ePeriod_10Seconds:
2170  *period = time_ePeriod_OneMinute;
2171  break;
2172  case time_ePeriod_OneMinute:
2173  case time_ePeriod_LastMinute:
2174  *period = time_ePeriod_10Minutes;
2175  break;
2176  case time_ePeriod_Last10Minutes:
2177  case time_ePeriod_10Minutes:
2178  *period = time_ePeriod_OneHour;
2179  break;
2180  case time_ePeriod_OneHour:
2181  case time_ePeriod_LastHour:
2182  *period = time_ePeriod_OneDay;
2183  break;
2184  case time_ePeriod_Today:
2185  case time_ePeriod_Yesterday:
2186  case time_ePeriod_OneDay:
2187  *period = time_ePeriod_OneWeek;
2188  break;
2189  case time_ePeriod_ThisWeek:
2190  case time_ePeriod_LastWeek:
2191  case time_ePeriod_OneWeek:
2192  *period = time_ePeriod_OneMonth;
2193  break;
2194  case time_ePeriod_ThisMonth:
2195  case time_ePeriod_LastMonth:
2196  case time_ePeriod_OneMonth:
2197  *period = time_ePeriod_OneYear;
2198  break;
2199  case time_ePeriod_ThisYear:
2200  case time_ePeriod_OneYear:
2201  *period = time_ePeriod_AllTime;
2202  break;
2203  default:
2204  changed = 0;
2205  }
2206  return changed;
2207 }
2208 
2210 
2211 int time_PrintA(const char* format, pwr_tTime* ts)
2212 {
2213  char timstr[40];
2214 
2215  time_AtoAscii(ts, time_eFormat_DateAndTime, timstr, sizeof(timstr));
2216  return printf(format, timstr);
2217 }
2218 
2220 
2225 pwr_tFloat32 time_AdiffToFloat(pwr_tTime* t, pwr_tTime* s)
2226 {
2227  pwr_tDeltaTime r;
2228  pwr_tFloat32 f;
2229 
2230  time_Adiff(&r, t, s);
2231  time_DToFloat(&f, &r);
2232  return f;
2233 }
2234 
int time_PeriodMonth(pwr_tTime *time, pwr_tTime *from, pwr_tTime *to, int previous)
Calculate start and end time for month.
Definition: co_time.c:1453
Include file for Time management.
time_eFormat
Time string format.
Definition: co_time.h:72
@ time_eFormat_NumDateAndTime
Date and time format, 2005-01-01 00:00:00.
Definition: co_time.h:78
@ time_eFormat_ComprDateAndTime
Date and time compressed format, 70-01-01 00:00:00.
Definition: co_time.h:76
@ time_eFormat_TimeAndDate
Time and date format, 01:00:00 30/01/87.
Definition: co_time.h:83
@ time_eFormat_FileDateAndTime
Date and time format, 20050101_000000.
Definition: co_time.h:80
@ time_eFormat_DateAndTime
Display date and time, 01-JAN-1970 01:00:00.00.
Definition: co_time.h:73
@ time_eFormat_FileDate
Date format, 20050101.
Definition: co_time.h:81
@ time_eFormat_DateAndTimeLoc
Display date and time with local month.
Definition: co_time.h:82
pwr_tStatus time_AsciiToA(const char *tstr, pwr_tTime *ts)
Convert ascii time to timespec.
Definition: co_time.c:999
pwr_tDeltaTime * time_Float64ToD(pwr_tDeltaTime *dt, pwr_tFloat64 f)
Convert double to time.
Definition: co_time.c:1316
int time_IsNull(pwr_tTime *t1)
Test if time is Null.
Definition: co_time.c:177
pwr_tDeltaTime * time_ClockToD(pwr_tStatus *status, pwr_tDeltaTime *tp, time_tClock clock)
Convert clock time to delta time.
Definition: co_time.c:1387
pwr_tStatus time_AsciiToD(const char *tstr, pwr_tDeltaTime *ts)
Convert ascii to timespec.
Definition: co_time.c:928
pwr_tDeltaTime * time_Dneg(pwr_tDeltaTime *result, pwr_tDeltaTime *t)
Negate a delta time,.
Definition: co_time.c:690
pwr_tDeltaTime * time_FloatToD(pwr_tDeltaTime *dt, pwr_tFloat32 f)
Convert float to time.
Definition: co_time.c:1293
pwr_tStatus time_DtoAscii(pwr_tDeltaTime *dt, int hundreds, char *buf, int bufsize)
Convert a delta time to ascii string.
Definition: co_time.c:819
int time_GetTimeMonotonic(pwr_tTime *ts)
Get current monotonic time.
Definition: co_time.c:1440
pwr_tDeltaTime * time_Dadd(pwr_tDeltaTime *result, pwr_tDeltaTime *t, pwr_tDeltaTime *a)
Add two delta times, the result is also delta.
Definition: co_time.c:547
int time_GetTime(pwr_tTime *ts)
Get current time.
Definition: co_time.c:1427
pwr_tDeltaTime * time_Dsub(pwr_tDeltaTime *result, pwr_tDeltaTime *t, pwr_tDeltaTime *s)
Subtract two delta times.
Definition: co_time.c:750
pwr_tTime * time_Aadd_NE(pwr_tTime *result, pwr_tTime *t, pwr_tDeltaTime *a)
Add an absolute time and a delta time.
Definition: co_time.c:240
pwr_tStatus time_AsciiToTm(const char *tstr, struct tm *tmptr)
Convert timestring to struct.
Definition: co_time.c:1079
pwr_tDeltaTime * time_ZeroD(pwr_tDeltaTime *tp)
Zero a delta time.
Definition: co_time.c:1403
int time_PeriodPreviousWeek(pwr_tTime *time, pwr_tTime *from, pwr_tTime *to)
Calculate start and end time for previous week.
Definition: co_time.c:1622
time_tClock time_DtoClock(pwr_tStatus *status, pwr_tDeltaTime *tp)
Convert delta time to clock time.
Definition: co_time.c:1379
int time_Dcomp(pwr_tDeltaTime *t1, pwr_tDeltaTime *t2)
Compare two delta times.
Definition: co_time.c:629
pwr_tDeltaTime * time_Dabs_NE(pwr_tDeltaTime *result, pwr_tDeltaTime *t)
Take the absolute walue of a delta time.
Definition: co_time.c:516
pwr_tDeltaTime * time_MsToD(pwr_tDeltaTime *dt, pwr_tInt32 ms)
Convert millisec to timespec.
Definition: co_time.c:1275
pwr_tDeltaTime * time_Dadd_NE(pwr_tDeltaTime *result, pwr_tDeltaTime *t, pwr_tDeltaTime *a)
Add two delta times, the result is also delta.
Definition: co_time.c:584
int time_PrintA(const char *format, pwr_tTime *ts)
Print an absolute time. The format should contain s.
Definition: co_time.c:2211
pwr_tTime * time_Asub(pwr_tTime *result, pwr_tTime *t, pwr_tDeltaTime *s)
Subtract a delta time from a time,.
Definition: co_time.c:408
void time_PreviousDayBreak(pwr_tTime *time, pwr_tTime *daybreak)
Calculate previous daybreak.
Definition: co_time.c:1653
int time_Acomp_NE(pwr_tTime *t1, pwr_tTime *t2)
Compare two timespecs.
Definition: co_time.c:312
char * time_GetTimeAscii(time_eFormat format)
Get current time in ascii.
Definition: co_time.c:920
pwr_tDeltaTime * time_Adiff_NE(pwr_tDeltaTime *r, pwr_tTime *t, pwr_tTime *s)
Subtract a time from a time,.
Definition: co_time.c:373
pwr_tStatus time_AtoAscii(pwr_tTime *ts, time_eFormat format, char *buf, int bufsize)
Convert timespec to ascii.
Definition: co_time.c:878
pwr_tFloat64 time_DToFloat64(pwr_tFloat64 *f, pwr_tDeltaTime *dt)
Convert time to Float64.
Definition: co_time.c:1360
pwr_tDeltaTime * time_Dabs(pwr_tDeltaTime *result, pwr_tDeltaTime *t)
Take the absolute walue of a delta time.
Definition: co_time.c:484
int time_Acomp(pwr_tTime *t1, pwr_tTime *t2)
Compare two timespecs.
Definition: co_time.c:282
int time_Dcomp_NE(pwr_tDeltaTime *t1, pwr_tDeltaTime *t2)
Compare two delta times.
Definition: co_time.c:660
pwr_tDeltaTime * time_Adiff(pwr_tDeltaTime *r, pwr_tTime *t, pwr_tTime *s)
Subtract a time from a time,.
Definition: co_time.c:339
pwr_tDeltaTime * time_Dsub_NE(pwr_tDeltaTime *result, pwr_tDeltaTime *t, pwr_tDeltaTime *s)
Subtract two delta times.
Definition: co_time.c:786
pwr_tFloat32 time_DToFloat(pwr_tFloat32 *f, pwr_tDeltaTime *dt)
Convert time to Float32.
Definition: co_time.c:1340
pwr_tStatus time_TmToAscii(struct tm *tmptr, time_eFormat format, char *buf, int bufsize)
Convert time struct to string.
Definition: co_time.c:1046
pwr_tFloat32 time_AdiffToFloat(pwr_tTime *t, pwr_tTime *s)
Subtract a time from a time and return the differens.
Definition: co_time.c:2225
pwr_tTime * time_Asub_NE(pwr_tTime *result, pwr_tTime *t, pwr_tDeltaTime *s)
Subtract a delta time from a time,.
Definition: co_time.c:444
pwr_tTime * time_Aadd(pwr_tTime *result, pwr_tTime *t, pwr_tDeltaTime *a)
Add an absolute time and a delta time.
Definition: co_time.c:199
pwr_tDeltaTime * time_Dneg_NE(pwr_tDeltaTime *result, pwr_tDeltaTime *t)
Negate a delta time,.
Definition: co_time.c:721
#define EVEN(a)
Check if value is even.
Definition: pwr.h:623
double pwr_tFloat64
64-bit float.
Definition: pwr.h:135
int pwr_tInt32
32-bit integer type.
Definition: pwr.h:159
int pwr_tStatus
Status type.
Definition: pwr.h:284
float pwr_tFloat32
32-bit float.
Definition: pwr.h:131
Delta time type.
Definition: pwr.h:369