gwenhywfar  4.6.0beta
gwentime_all.c
Go to the documentation of this file.
1 /***************************************************************************
2  $RCSfile$
3  -------------------
4  cvs : $Id$
5  begin : Sun Nov 23 2003
6  copyright : (C) 2003 by Martin Preuss
7  email : martin@libchipcard.de
8 
9  ***************************************************************************
10  * *
11  * This library is free software; you can redistribute it and/or *
12  * modify it under the terms of the GNU Lesser General Public *
13  * License as published by the Free Software Foundation; either *
14  * version 2.1 of the License, or (at your option) any later version. *
15  * *
16  * This library is distributed in the hope that it will be useful, *
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
19  * Lesser General Public License for more details. *
20  * *
21  * You should have received a copy of the GNU Lesser General Public *
22  * License along with this library; if not, write to the Free Software *
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
24  * MA 02111-1307 USA *
25  * *
26  ***************************************************************************/
27 
28 
29 #ifdef HAVE_CONFIG_H
30 # include <config.h>
31 #endif
32 
33 #define DISABLE_DEBUGLOG
34 
35 
36 #include "gwentime_p.h"
37 #include <gwenhywfar/gwentime.h>
38 #include <gwenhywfar/debug.h>
39 
40 #include <time.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <string.h>
44 
45 
46 GWEN_LIST_FUNCTIONS(GWEN_TIME_TMPLCHAR, GWEN_TimeTmplChar)
47 
48 
49 
51  GWEN_TIME *t;
52 
55  DBG_ERROR(GWEN_LOGDOMAIN, "Could not get current time");
56  GWEN_Time_free(t);
57  return 0;
58  }
59  return t;
60 }
61 
62 
63 
65  GWEN_TIME *t;
66 
68  t->secs=secs;
69  return t;
70 }
71 
72 
73 
75  uint32_t secs) {
76  uint32_t i;
77 
78  assert(ti);
79  i=ti->secs+secs;
80  if (i<ti->secs) {
82  "Overflow when adding %u seconds", secs);
83  return GWEN_ERROR_INVALID;
84  }
85  ti->secs=i;
86  return 0;
87 }
88 
89 
90 
92  uint32_t secs) {
93  assert(ti);
94 
95  if (ti->secs<secs) {
97  "Underflow when subtracting %u seconds",
98  secs);
99  return GWEN_ERROR_INVALID;
100  }
101  ti->secs-=secs;
102  return 0;
103 }
104 
105 
107  uint32_t secs,
108  uint32_t msecs){
109  assert(ti);
110  ti->secs=secs;
111  ti->msecs=msecs;
112 }
113 
114 
115 
117  GWEN_DB_NODE *dbT;
118  int i1, i2, i3;
119 
120  assert(t);
121  assert(db);
122  dbT=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, "date");
124  "inUtc", 1);
125 
126  assert(dbT);
127  if (GWEN_Time_GetBrokenDownUtcDate(t, &i1, &i2, &i3)) {
128  DBG_INFO(GWEN_LOGDOMAIN, "Could not break down date");
129  return -1;
130  }
132  "day", i1);
134  "month", i2+1);
136  "year", i3);
137 
138  dbT=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, "time");
139  assert(dbT);
140  if (GWEN_Time_GetBrokenDownUtcTime(t, &i1, &i2, &i3)) {
141  DBG_INFO(GWEN_LOGDOMAIN, "Could not break down time");
142  return -1;
143  }
145  "hour", i1);
147  "min", i2);
149  "sec", i3);
150 
151  return 0;
152 }
153 
154 
155 
157  GWEN_TIME *t;
158  GWEN_DB_NODE *dbT;
159  int day, month, year;
160  int hour, min, sec;
161  int inUtc;
162 
163  day=month=year=0;
164  hour=min=sec=0;
165 
166  inUtc=GWEN_DB_GetIntValue(db, "inUtc", 0, 0);
168  if (dbT) {
169  day=GWEN_DB_GetIntValue(dbT, "day", 0, 0);
170  month=GWEN_DB_GetIntValue(dbT, "month", 0, 1)-1;
171  year=GWEN_DB_GetIntValue(dbT, "year", 0, 0);
172  if (!day || !year) {
173  DBG_INFO(GWEN_LOGDOMAIN, "Bad date in DB");
174  return 0;
175  }
176  }
177 
179  if (dbT) {
180  hour=GWEN_DB_GetIntValue(dbT, "hour", 0, 0);
181  min=GWEN_DB_GetIntValue(dbT, "min", 0, 0);
182  sec=GWEN_DB_GetIntValue(dbT, "sec", 0, 0);
183  }
184 
186  "Creating time from this: %04d/%02d/%02d - %02d:%02d:%02d (%d)",
187  year, month, day, hour, min, sec, inUtc);
188  t=GWEN_Time_new(year, month, day, hour, min, sec, inUtc);
189  if (!t) {
190  DBG_INFO(GWEN_LOGDOMAIN, "Bad date/time");
191  return 0;
192  }
193 
194  return t;
195 }
196 
197 
198 
199 GWEN_TIME *GWEN_Time__fromString(const char *s, const char *tmpl, int inUtc){
200  int year, month, day;
201  int hour, min, sec;
202  const char *p;
203  const char *t;
204  GWEN_TIME *gwt;
205 
206  assert(s);
207  assert(tmpl);
208  year=month=day=0;
209  hour=min=sec=0;
210 
211  p=s;
212  t=tmpl;
213  while(*t && *p) {
214  int i;
215 
216  if (*t=='*') {
217  t++;
218  if (!*t) {
219  DBG_ERROR(GWEN_LOGDOMAIN, "Bad pattern: Must not end with \"*\"");
220  return 0;
221  }
222  i=0;
223  while(*p) {
224  if (!isdigit((int)*p))
225  break;
226  if (*p==*t)
227  break;
228  i*=10;
229  i+=(*p)-'0';
230  p++;
231  } /* while */
232  }
233  else {
234  if (isdigit((int)*p))
235  i=(*p)-'0';
236  else
237  i=-1;
238  p++;
239  }
240 
241  if (i==-1 && strchr("YMDhms", *t)!=NULL) {
243  "No more digits at [%s], continuing", t);
244  p--;
245  }
246  else {
247  switch(*t) {
248  case 'Y':
249  if (i==-1) {
250  DBG_INFO(GWEN_LOGDOMAIN, "here");
251  return 0;
252  }
253  year*=10;
254  year+=i;
255  break;
256  case 'M':
257  if (i==-1) {
258  DBG_INFO(GWEN_LOGDOMAIN, "here");
259  return 0;
260  }
261  month*=10;
262  month+=i;
263  break;
264  case 'D':
265  if (i==-1) {
266  DBG_INFO(GWEN_LOGDOMAIN, "here");
267  return 0;
268  }
269  day*=10;
270  day+=i;
271  break;
272  case 'h':
273  if (i==-1) {
274  DBG_INFO(GWEN_LOGDOMAIN, "here");
275  return 0;
276  }
277  hour*=10;
278  hour+=i;
279  break;
280  case 'm':
281  if (i==-1) {
282  DBG_INFO(GWEN_LOGDOMAIN, "here");
283  return 0;
284  }
285  min*=10;
286  min+=i;
287  break;
288  case 's':
289  if (i==-1) {
290  DBG_INFO(GWEN_LOGDOMAIN, "here");
291  return 0;
292  }
293  sec*=10;
294  sec+=i;
295  break;
296  default:
298  "Unknown character in template, will skip in both strings");
299  break;
300  }
301  }
302  t++;
303  } /* while */
304 
305  if (year<100)
306  year+=2000;
307  if (day==0)
308  day=1;
309 
311  "Got this date/time: %04d/%02d/%02d, %02d:%02d:%02d",
312  year, month-1, day, hour, min, sec);
313 
314  /* get time in local time */
315  gwt=GWEN_Time_new(year, month-1, day, hour, min, sec, inUtc);
316  if (!gwt) {
317  DBG_INFO(GWEN_LOGDOMAIN, "here");
318  return 0;
319  }
320  return gwt;
321 }
322 
323 
324 
325 GWEN_TIME *GWEN_Time_fromString(const char *s, const char *tmpl){
326  return GWEN_Time__fromString(s, tmpl, 0);
327 }
328 
329 
330 
331 GWEN_TIME *GWEN_Time_fromUtcString(const char *s, const char *tmpl){
332  return GWEN_Time__fromString(s, tmpl, 1);
333 }
334 
335 
336 
338  int month,
339  int day,
340  int hour,
341  int min,
342  int sec,
343  int inUtc){
344  uint32_t s;
345 
346  if (inUtc)
347  s=GWEN_Time__mktimeUtc(year, month, day, hour, min, sec);
348  else {
349  struct tm ti;
350  struct tm *tp;
351  time_t tt;
352 
353  tt=time(0);
354  tp=localtime(&tt);
355  assert(tp);
356  memmove(&ti, tp, sizeof(ti));
357  ti.tm_sec=sec;
358  ti.tm_min=min;
359  ti.tm_hour=hour;
360  if (year<100) {
361  if (year<72)
362  year+=2000;
363  year+=1900;
364  }
365  ti.tm_year=year-1900;
366  ti.tm_mon=month;
367  ti.tm_mday=day;
368  ti.tm_yday=0;
369  ti.tm_wday=0;
370  tt=mktime(&ti);
371  assert(tt!=(time_t)-1);
372  s=(uint32_t)tt;
373  }
374  return GWEN_Time_fromSeconds(s);
375 }
376 
377 
378 
379 uint32_t GWEN_Time__mktimeUtc(int year,
380  int month,
381  int day,
382  int hour,
383  int min,
384  int sec) {
385  uint32_t result;
386  int i;
387  int isLeap;
388  const uint32_t hoursecs=60*60;
389  const uint32_t daysecs=24*hoursecs;
390  const uint32_t yearsecs=365*daysecs;
391  const uint32_t monthDays[12]=
392  {
393  31, 28, 31, 30,
394  31, 30, 31, 31,
395  30, 31, 30, 31
396  };
397 
398  result=(year-1970)*yearsecs;
399 
400  for (i=1970; i<year; i++)
401  if ((((i % 4)==0) &&
402  ((i % 100)!=0)) ||
403  ((i % 400)==0))
404  result+=daysecs;
405 
406  isLeap=((((year % 4)==0) &&
407  ((year % 100)!=0)) ||
408  ((year % 400)==0));
409 
410  for (i=0; i<month; i++)
411  if (isLeap && i==1)
412  result+=29*daysecs;
413  else
414  result+=monthDays[i]*daysecs;
415 
416  result+=(day-1)*daysecs;
417  result+=(hour*hoursecs);
418  result+=min*60;
419  result+=sec;
420 
421  return result;
422 }
423 
424 
425 
427  GWEN_TIME *newT;
428 
429  assert(t);
430  GWEN_NEW_OBJECT(GWEN_TIME, newT);
431  newT->secs=t->secs;
432  newT->msecs=t->msecs;
433  return newT;
434 }
435 
436 
437 
439  if (t) {
440  GWEN_FREE_OBJECT(t);
441  }
442 }
443 
444 
445 
446 double GWEN_Time_Diff(const GWEN_TIME *t1, const GWEN_TIME *t0){
447  double d;
448 
449  assert(t1);
450  assert(t0);
451 
452  d=1000.0*((double)(t1->secs)-(double)(t0->secs));
453  d+=(double)((double)(t1->msecs)-(double)(t0->msecs));
454 
455  return d;
456 }
457 
458 
459 
460 double GWEN_Time_DiffSeconds(const GWEN_TIME *t1, const GWEN_TIME *t0){
461  double d;
462 
463  assert(t1);
464  assert(t0);
465 
466  d=(double)(t1->secs)-(double)(t0->secs);
467  d+=((double)((double)(t1->msecs)-(double)(t0->msecs)))/1000.0;
468 
469  return d;
470 }
471 
472 
473 
474 int GWEN_Time_Compare(const GWEN_TIME *t1, const GWEN_TIME *t0){
475  if (t1 && t0) {
476  if (t1->secs<t0->secs)
477  return -1;
478  else if (t1->secs>t0->secs)
479  return 1;
480  else {
481  if (t1->msecs<t0->msecs)
482  return -1;
483  else if (t1->msecs>t0->msecs)
484  return 1;
485  else
486  return 0;
487  }
488  }
489  else if (t1)
490  return 1;
491  else if (t0)
492  return -1;
493 
494  return 0;
495 }
496 
497 
498 
500  assert(t);
501  return (double)((t->secs*1000)+(t->msecs));
502 }
503 
504 
505 
506 uint32_t GWEN_Time_Seconds(const GWEN_TIME *t){
507  assert(t);
508  return t->secs;
509 }
510 
511 
512 
514  int *hours,
515  int *mins,
516  int *secs){
517  struct tm *tb;
518  time_t tt;
519 
520  assert(t);
521  tt=t->secs;
522  tb=localtime(&tt);
523  if (!tb) {
524  DBG_ERROR(GWEN_LOGDOMAIN, "localtime(): %s", strerror(errno));
525  return -1;
526  }
527  *hours=tb->tm_hour;
528  *mins=tb->tm_min;
529  *secs=tb->tm_sec;
530  return 0;
531 }
532 
533 
534 
536  int *hours,
537  int *mins,
538  int *secs){
539  struct tm *tb;
540  time_t tt;
541 
542  assert(t);
543  tt=t->secs;
544  tb=gmtime(&tt);
545  if (!tb) {
546  DBG_ERROR(GWEN_LOGDOMAIN, "gmtime(): %s", strerror(errno));
547  return -1;
548  }
549  *hours=tb->tm_hour;
550  *mins=tb->tm_min;
551  *secs=tb->tm_sec;
552  return 0;
553 }
554 
555 
556 
558  int *days,
559  int *month,
560  int *year){
561  struct tm *tb;
562  time_t tt;
563 
564  assert(t);
565  tt=t->secs;
566  tb=localtime(&tt);
567  if (!tb) {
568  DBG_ERROR(GWEN_LOGDOMAIN, "localtime(): %s", strerror(errno));
569  return -1;
570  }
571  *days=tb->tm_mday;
572  *month=tb->tm_mon;
573  *year=tb->tm_year+1900;
574  return 0;
575 }
576 
577 
578 
580  int *days,
581  int *month,
582  int *year){
583  struct tm *tb;
584  time_t tt;
585 
586  assert(t);
587  tt=t->secs;
588  tb=gmtime(&tt);
589  if (!tb) {
590  DBG_ERROR(GWEN_LOGDOMAIN, "gmtime(): %s", strerror(errno));
591  return -1;
592  }
593  *days=tb->tm_mday;
594  *month=tb->tm_mon;
595  *year=tb->tm_year+1900;
596  return 0;
597 }
598 
599 
600 
601 /* TODO: compiler says "function returns an aggregate" */
602 struct tm GWEN_Time_toTm(const GWEN_TIME *t) {
603  struct tm *tb;
604  time_t tt;
605 
606  assert(t);
607  tt=t->secs;
608  tb=localtime(&tt);
609  return *tb;
610 }
611 
612 time_t GWEN_Time_toTime_t(const GWEN_TIME *t) {
613  assert(t);
614  return t->secs;
615 }
616 
617 
618 
619 
620 GWEN_TIME_TMPLCHAR *GWEN_TimeTmplChar_new(char c) {
621  GWEN_TIME_TMPLCHAR *e;
622 
623  GWEN_NEW_OBJECT(GWEN_TIME_TMPLCHAR, e);
624  GWEN_LIST_INIT(GWEN_TIME_TMPLCHAR, e);
625  e->character=c;
626  return e;
627 }
628 
629 
630 
631 void GWEN_TimeTmplChar_free(GWEN_TIME_TMPLCHAR *e) {
632  if (e) {
633  free(e->content);
634  GWEN_LIST_FINI(GWEN_TIME_TMPLCHAR, e);
635  GWEN_FREE_OBJECT(e);
636  }
637 }
638 
639 
640 GWEN_TIME_TMPLCHAR *GWEN_Time__findTmplChar(GWEN_TIME_TMPLCHAR_LIST *ll,
641  char c) {
642  GWEN_TIME_TMPLCHAR *e;
643 
644  e=GWEN_TimeTmplChar_List_First(ll);
645  while(e) {
646  if (e->character==c)
647  break;
648  e=GWEN_TimeTmplChar_List_Next(e);
649  }
650 
651  return e;
652 }
653 
654 
655 
656 
657 void GWEN_Time__sampleTmplChars(GWEN_UNUSED const GWEN_TIME *t, const char *tmpl,
659  GWEN_TIME_TMPLCHAR_LIST *ll) {
660  const char *s;
661 
662  s=tmpl;
663  while(*s) {
664  if (strchr("YMDhms", *s)) {
665  GWEN_TIME_TMPLCHAR *e;
666 
667  e=GWEN_Time__findTmplChar(ll, *s);
668  if (!e) {
669  /* new entry, create it */
670  e=GWEN_TimeTmplChar_new(*s);
671  GWEN_TimeTmplChar_List_Add(e, ll);
672  }
673  assert(e);
674  e->count++;
675  }
676  else {
677  DBG_DEBUG(GWEN_LOGDOMAIN, "Unknown character in template (%02x)",
678  *s);
679  }
680  s++;
681  }
682 }
683 
684 
685 
687  GWEN_TIME_TMPLCHAR_LIST *ll,
688  int useUtc) {
689  GWEN_TIME_TMPLCHAR *e;
690  int year, month, day, hour, minute, second;
691 
692  if (useUtc) {
693  GWEN_Time_GetBrokenDownUtcDate(t, &day, &month, &year);
694  GWEN_Time_GetBrokenDownUtcTime(t, &hour, &minute, &second);
695  }
696  else {
697  GWEN_Time_GetBrokenDownDate(t, &day, &month, &year);
698  GWEN_Time_GetBrokenDownTime(t, &hour, &minute, &second);
699  }
700 
701  e=GWEN_TimeTmplChar_List_First(ll);
702  while(e) {
703  int v;
704  char buffer[32];
705 
706  switch(e->character) {
707  case 'Y': v=year; break;
708  case 'M': v=month+1; break;
709  case 'D': v=day; break;
710  case 'h': v=hour; break;
711  case 'm': v=minute; break;
712  case 's': v=second; break;
713  default: v=-1; break;
714  }
715  if (v==-1) {
716  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown character, should not happen here");
717  abort();
718  }
719  buffer[0]=0;
720  snprintf(buffer, sizeof(buffer)-1, "%0*d", GWEN_TIME_TMPL_MAX_COUNT, v);
721  buffer[sizeof(buffer)-1]=0;
722  e->content=strdup(buffer);
723  e->nextChar=strlen(e->content)-(e->count);
724  e=GWEN_TimeTmplChar_List_Next(e);
725  }
726 }
727 
728 
729 
730 
731 int GWEN_Time__toString(const GWEN_TIME *t, const char *tmpl,
732  GWEN_BUFFER *buf, int useUtc) {
733  GWEN_TIME_TMPLCHAR_LIST *ll;
734  const char *s;
735 
736  ll=GWEN_TimeTmplChar_List_new();
737  GWEN_Time__sampleTmplChars(t, tmpl, buf, ll);
738  GWEN_Time__fillTmplChars(t, ll, useUtc);
739 
740  s=tmpl;
741  while(*s) {
742  if (strchr("YMDhms", *s)) {
743  GWEN_TIME_TMPLCHAR *e;
744  char c;
745 
746  e=GWEN_Time__findTmplChar(ll, *s);
747  assert(e);
748  assert(e->content);
749  if (s[1]=='*') {
750  /* append full string */
751  GWEN_Buffer_AppendString(buf, e->content);
752  /* skip asterisk */
753  s++;
754  }
755  else {
756  c=e->content[e->nextChar++];
757  assert(c);
758  GWEN_Buffer_AppendByte(buf, c);
759  }
760  }
761  else
762  GWEN_Buffer_AppendByte(buf, *s);
763  s++;
764  }
765  GWEN_TimeTmplChar_List_free(ll);
766  return 0;
767 }
768 
769 
770 
771 int GWEN_Time_toString(const GWEN_TIME *t, const char *tmpl,
772  GWEN_BUFFER *buf) {
773  return GWEN_Time__toString(t, tmpl, buf, 0);
774 }
775 
776 
777 
778 int GWEN_Time_toUtcString(const GWEN_TIME *t, const char *tmpl,
779  GWEN_BUFFER *buf) {
780  return GWEN_Time__toString(t, tmpl, buf, 1);
781 }
782 
783 
784 
785 
786 
787 
788 
789 
790 
791