gwendate.c

Go to the documentation of this file.
00001 /***************************************************************************
00002     begin       : Tue Jul 07 2009
00003     copyright   : (C) 2009 by Martin Preuss
00004     email       : martin@libchipcard.de
00005 
00006  ***************************************************************************
00007  *                                                                         *
00008  *   This library is free software; you can redistribute it and/or         *
00009  *   modify it under the terms of the GNU Lesser General Public            *
00010  *   License as published by the Free Software Foundation; either          *
00011  *   version 2.1 of the License, or (at your option) any later version.    *
00012  *                                                                         *
00013  *   This library is distributed in the hope that it will be useful,       *
00014  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00015  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
00016  *   Lesser General Public License for more details.                       *
00017  *                                                                         *
00018  *   You should have received a copy of the GNU Lesser General Public      *
00019  *   License along with this library; if not, write to the Free Software   *
00020  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
00021  *   MA  02111-1307  USA                                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #ifdef HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 
00030 #include "gwendate_p.h"
00031 
00032 #include <gwenhywfar/debug.h>
00033 #include <gwenhywfar/misc.h>
00034 
00035 
00036 #include <time.h>
00037 #include <ctype.h>
00038 
00039 
00040 
00041 static const uint8_t daysInMonth[12]={
00042   31,28,31,30,31,30,31,31,30,31,30,31
00043 };
00044 
00045 
00046 
00047 
00048 GWEN_DATE *GWEN_Date_fromGregorian(int y, int m, int d) {
00049   GWEN_DATE *gd;
00050 
00051   if (m<1 || m>12 || d<1 || d>31) {
00052     DBG_ERROR(GWEN_LOGDOMAIN, "Bad date format");
00053     return NULL;
00054   }
00055 
00056   GWEN_NEW_OBJECT(GWEN_DATE, gd);
00057   gd->year=y;
00058   gd->month=m;
00059   gd->day=d;
00060   gd->julian=(1461*(y+4800+(m-14)/12))/4+
00061     (367*(m-2-12*((m-14)/12)))/12-
00062     (3*((y+4900+(m-14)/12)/100))/4+
00063     d-32075;
00064 
00065   snprintf(gd->asString, sizeof(gd->asString)-1,
00066            "%04d%02d%02d",
00067            gd->year, gd->month, gd->day);
00068   gd->asString[sizeof(gd->asString)-1]=0;
00069 
00070   return gd;
00071 }
00072 
00073 
00074 
00075 GWEN_DATE *GWEN_Date_fromJulian(int julian) {
00076   GWEN_DATE *gd;
00077   int l, n, i, j;
00078 
00079   GWEN_NEW_OBJECT(GWEN_DATE, gd);
00080   l=julian+68569;
00081   n=(4*l)/146097;
00082   l=l-(146097*n+3)/4;
00083   i=(4000*(l+1))/1461001;
00084   l=l-(1461*i)/4+31;
00085   j=(80*l)/2447;
00086   gd->day=l-(2447*j)/80;
00087   l=j/11;
00088   gd->month=j+2-(12*l);
00089   gd->year=100*(n-49)+i+l;
00090 
00091   snprintf(gd->asString, sizeof(gd->asString)-1,
00092            "%04d%02d%02d",
00093            gd->year, gd->month, gd->day);
00094   gd->asString[sizeof(gd->asString)-1]=0;
00095 
00096   return gd;
00097 }
00098 
00099 
00100 
00101 GWEN_DATE *GWEN_Date_CurrentDate() {
00102   time_t l;
00103   struct tm *ltm;
00104 
00105   time(&l);
00106   ltm=localtime(&l);
00107   if (ltm) {
00108     GWEN_DATE *gd;
00109 
00110     gd=GWEN_Date_fromGregorian(ltm->tm_year+1900, ltm->tm_mon, ltm->tm_mday);
00111     return gd;
00112   }
00113 
00114   return NULL;
00115 }
00116 
00117 
00118 
00119 GWEN_DATE *GWEN_Date_dup(const GWEN_DATE *ogd) {
00120   assert(ogd);
00121   return GWEN_Date_fromGregorian(ogd->year, ogd->month, ogd->day);
00122 }
00123 
00124 
00125 
00126 GWEN_DATE *GWEN_Date_fromString(const char *s) {
00127   int y, m, d;
00128 
00129   if (3==sscanf(s, "%04d%02d%02d", &y, &m, &d)) {
00130     return GWEN_Date_fromGregorian(y, m, d);
00131   }
00132   else {
00133     DBG_ERROR(GWEN_LOGDOMAIN, "Bad date [%s]", s);
00134     return NULL;
00135   }
00136 }
00137 
00138 
00139 
00140 void GWEN_Date_free(GWEN_DATE *gd) {
00141   if (gd) {
00142     GWEN_FREE_OBJECT(gd);
00143   }
00144 }
00145 
00146 
00147 
00148 int GWEN_Date_IsLeapYear(int y) {
00149   return ((y%4==0) && (y%100!=0)) || (y%400==0);
00150 }
00151 
00152 
00153 
00154 
00155 int GWEN_Date_DaysInMonth(const GWEN_DATE *gd) {
00156   assert(gd);
00157   if (gd->month==2 &&
00158       ((((gd->year%4)==0) && ((gd->year)%100!=0)) || ((gd->year)%400==0)))
00159     /* February in a leap year */
00160     return 29;
00161   else
00162     return daysInMonth[gd->month-1];
00163 }
00164 
00165 
00166 
00167 int GWEN_Date_DaysInYear(const GWEN_DATE *gd) {
00168   GWEN_DATE *gd11;
00169   int result;
00170 
00171   assert(gd);
00172 
00173   gd11=GWEN_Date_fromGregorian(gd->year, 1, 1);
00174   result=(gd->julian)-(gd11->julian);
00175   GWEN_Date_free(gd11);
00176 
00177   return result;
00178 }
00179 
00180 
00181 
00182 int GWEN_Date_GetYear(const GWEN_DATE *gd) {
00183   assert(gd);
00184   return gd->year;
00185 }
00186 
00187 
00188 
00189 int GWEN_Date_GetMonth(const GWEN_DATE *gd) {
00190   assert(gd);
00191   return gd->month;
00192 }
00193 
00194 
00195 
00196 int GWEN_Date_GetDay(const GWEN_DATE *gd) {
00197   assert(gd);
00198   return gd->day;
00199 }
00200 
00201 
00202 
00203 int GWEN_Date_GetJulian(const GWEN_DATE *gd) {
00204   assert(gd);
00205   return gd->julian;
00206 }
00207 
00208 
00209 
00210 int GWEN_Date_WeekDay(const GWEN_DATE *gd) {
00211   assert(gd);
00212   return (gd->julian+1)%7; /* 0=Sunday */
00213 }
00214 
00215 
00216 
00217 const char *GWEN_Date_GetString(const GWEN_DATE *gd) {
00218   assert(gd);
00219   return gd->asString;
00220 }
00221 
00222 
00223 
00224 int GWEN_Date_Compare(const GWEN_DATE *gd1, const GWEN_DATE *gd0) {
00225   assert(gd0);
00226   assert(gd1);
00227   if (gd1->julian==gd0->julian)
00228     return 0;
00229   else if (gd1->julian>gd0->julian)
00230     return 1;
00231   else
00232     return -1;
00233 }
00234 
00235 
00236 
00237 int GWEN_Date_Diff(const GWEN_DATE *gd1, const GWEN_DATE *gd0) {
00238   assert(gd1);
00239   assert(gd0);
00240 
00241   return gd1->julian-gd0->julian;
00242 }
00243 
00244 
00245 
00246 
00247 
00248 GWEN_DATE *GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl){
00249   int year, month, day;
00250   const char *p;
00251   const char *t;
00252   GWEN_DATE *gwt;
00253 
00254   assert(s);
00255   assert(tmpl);
00256   year=month=day=0;
00257 
00258   p=s;
00259   t=tmpl;
00260   while(*t && *p) {
00261     int i;
00262 
00263     if (*t=='*') {
00264       t++;
00265       if (!*t) {
00266         DBG_ERROR(GWEN_LOGDOMAIN, "Bad pattern: Must not end with \"*\"");
00267         return 0;
00268       }
00269       i=0;
00270       while(*p) {
00271         if (!isdigit((int)*p))
00272           break;
00273         if (*p==*t)
00274           break;
00275         i*=10;
00276         i+=(*p)-'0';
00277         p++;
00278       } /* while */
00279     }
00280     else {
00281       if (isdigit((int)*p))
00282         i=(*p)-'0';
00283       else
00284         i=-1;
00285       p++;
00286     }
00287 
00288     if (i==-1 && strchr("YMD", *t)!=NULL) {
00289       DBG_INFO(GWEN_LOGDOMAIN,
00290                "No more digits at [%s], continueing", t);
00291       p--;
00292     }
00293     else {
00294       switch(*t) {
00295       case 'Y':
00296         if (i==-1) {
00297           DBG_INFO(GWEN_LOGDOMAIN, "here");
00298           return 0;
00299         }
00300         year*=10;
00301         year+=i;
00302         break;
00303       case 'M':
00304         if (i==-1) {
00305           DBG_INFO(GWEN_LOGDOMAIN, "here");
00306           return 0;
00307         }
00308         month*=10;
00309         month+=i;
00310         break;
00311       case 'D':
00312         if (i==-1) {
00313           DBG_INFO(GWEN_LOGDOMAIN, "here");
00314           return 0;
00315         }
00316         day*=10;
00317         day+=i;
00318         break;
00319       default:
00320         DBG_VERBOUS(GWEN_LOGDOMAIN,
00321                     "Unknown character in template, will skip in both strings");
00322         break;
00323       }
00324     }
00325     t++;
00326   } /* while */
00327 
00328   if (year<100)
00329     year+=2000;
00330 
00331   DBG_DEBUG(GWEN_LOGDOMAIN,
00332             "Got this date/time: %04d/%02d/%02d",
00333             year, month, day);
00334 
00335   /* get time in local time */
00336   gwt=GWEN_Date_fromGregorian(year, month, day);
00337   if (!gwt) {
00338     DBG_INFO(GWEN_LOGDOMAIN, "here");
00339     return 0;
00340   }
00341   return gwt;
00342 }
00343 
00344 
00345 
00346 
00347 
00348 GWEN_LIST_FUNCTIONS(GWEN_DATE_TMPLCHAR, GWEN_DateTmplChar)
00349 
00350 
00351 GWEN_DATE_TMPLCHAR *GWEN_DateTmplChar_new(char c) {
00352   GWEN_DATE_TMPLCHAR *e;
00353 
00354   GWEN_NEW_OBJECT(GWEN_DATE_TMPLCHAR, e);
00355   GWEN_LIST_INIT(GWEN_DATE_TMPLCHAR, e);
00356   e->character=c;
00357   return e;
00358 }
00359 
00360 
00361 
00362 void GWEN_DateTmplChar_free(GWEN_DATE_TMPLCHAR *e) {
00363   if (e) {
00364     free(e->content);
00365     GWEN_LIST_FINI(GWEN_DATE_TMPLCHAR, e);
00366     GWEN_FREE_OBJECT(e);
00367   }
00368 }
00369 
00370 
00371 
00372 GWEN_DATE_TMPLCHAR *GWEN_Date__findTmplChar(GWEN_DATE_TMPLCHAR_LIST *ll, char c) {
00373   GWEN_DATE_TMPLCHAR *e;
00374 
00375   e=GWEN_DateTmplChar_List_First(ll);
00376   while(e) {
00377     if (e->character==c)
00378       break;
00379     e=GWEN_DateTmplChar_List_Next(e);
00380   }
00381 
00382   return e;
00383 }
00384 
00385 
00386 
00387 
00388 void GWEN_Date__sampleTmplChars(GWEN_UNUSED const GWEN_DATE *t, const char *tmpl,
00389                                 GWEN_UNUSED GWEN_BUFFER *buf,
00390                                 GWEN_DATE_TMPLCHAR_LIST *ll) {
00391   const char *s;
00392 
00393   s=tmpl;
00394   while(*s) {
00395     if (strchr("YMD", *s)) {
00396       GWEN_DATE_TMPLCHAR *e;
00397 
00398       e=GWEN_Date__findTmplChar(ll, *s);
00399       if (!e) {
00400         /* new entry, create it */
00401         e=GWEN_DateTmplChar_new(*s);
00402         GWEN_DateTmplChar_List_Add(e, ll);
00403       }
00404       assert(e);
00405       e->count++;
00406     }
00407     else {
00408       DBG_DEBUG(GWEN_LOGDOMAIN, "Unknown character in template (%02x)",
00409                 *s);
00410     }
00411     s++;
00412   }
00413 }
00414 
00415 
00416 
00417 void GWEN_Date__fillTmplChars(const GWEN_DATE *t, GWEN_DATE_TMPLCHAR_LIST *ll) {
00418   GWEN_DATE_TMPLCHAR *e;
00419 
00420 
00421   e=GWEN_DateTmplChar_List_First(ll);
00422   while(e) {
00423     int v;
00424     char buffer[32];
00425 
00426     switch(e->character) {
00427     case 'Y': v=t->year; break;
00428     case 'M': v=t->month; break;
00429     case 'D': v=t->day; break;
00430     default:  v=-1; break;
00431     }
00432     if (v==-1) {
00433       DBG_ERROR(GWEN_LOGDOMAIN, "Unknown character, should not happen here");
00434       abort();
00435     }
00436     buffer[0]=0;
00437     snprintf(buffer, sizeof(buffer)-1, "%0*d", GWEN_DATE_TMPL_MAX_COUNT, v);
00438     buffer[sizeof(buffer)-1]=0;
00439     e->content=strdup(buffer);
00440     e->nextChar=strlen(e->content)-(e->count);
00441     e=GWEN_DateTmplChar_List_Next(e);
00442   }
00443 }
00444 
00445 
00446 
00447 
00448 int GWEN_Date_toStringWithTemplate(const GWEN_DATE *t, const char *tmpl, GWEN_BUFFER *buf) {
00449   GWEN_DATE_TMPLCHAR_LIST *ll;
00450   const char *s;
00451 
00452   ll=GWEN_DateTmplChar_List_new();
00453   GWEN_Date__sampleTmplChars(t, tmpl, buf, ll);
00454   GWEN_Date__fillTmplChars(t, ll);
00455 
00456   s=tmpl;
00457   while(*s) {
00458     if (strchr("YMD", *s)) {
00459       GWEN_DATE_TMPLCHAR *e;
00460       char c;
00461 
00462       e=GWEN_Date__findTmplChar(ll, *s);
00463       assert(e);
00464       assert(e->content);
00465       c=e->content[e->nextChar++];
00466       assert(c);
00467       GWEN_Buffer_AppendByte(buf, c);
00468     }
00469     else
00470       GWEN_Buffer_AppendByte(buf, *s);
00471     s++;
00472   }
00473   GWEN_DateTmplChar_List_free(ll);
00474   return 0;
00475 }
00476 
00477 
00478 
00479 
00480 
00481 
00482 
00483 
00484 
Generated on Mon Jul 5 22:51:13 2010 for gwenhywfar by  doxygen 1.6.3