gwenhywfar 4.0.3

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+1, 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   if (gd0 && gd1) {
00226     if (gd1->julian==gd0->julian)
00227       return 0;
00228     else if (gd1->julian>gd0->julian)
00229       return 1;
00230     else
00231       return -1;
00232   }
00233   else if (gd0)
00234     return 1;
00235   else if (gd1)
00236     return -1;
00237   else
00238     return 0;
00239 }
00240 
00241 
00242 
00243 int GWEN_Date_Diff(const GWEN_DATE *gd1, const GWEN_DATE *gd0) {
00244   assert(gd1);
00245   assert(gd0);
00246 
00247   return gd1->julian-gd0->julian;
00248 }
00249 
00250 
00251 
00252 GWEN_DATE *GWEN_Date_fromTime(const GWEN_TIME *ti) {
00253   GWEN_BUFFER *tbuf;
00254   GWEN_DATE *gd;
00255 
00256   tbuf=GWEN_Buffer_new(0, 32, 0, 1);
00257   GWEN_Time_toString(ti, "YYYYMMDD", tbuf);
00258   gd=GWEN_Date_fromString(GWEN_Buffer_GetStart(tbuf));
00259   GWEN_Buffer_free(tbuf);
00260 
00261   return gd;
00262 }
00263 
00264 
00265 
00266 
00267 GWEN_DATE *GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl){
00268   int year, month, day;
00269   const char *p;
00270   const char *t;
00271   GWEN_DATE *gwt;
00272 
00273   assert(s);
00274   assert(tmpl);
00275   year=month=day=0;
00276 
00277   p=s;
00278   t=tmpl;
00279   while(*t && *p) {
00280     int i;
00281 
00282     if (*t=='*') {
00283       t++;
00284       if (!*t) {
00285         DBG_ERROR(GWEN_LOGDOMAIN, "Bad pattern: Must not end with \"*\"");
00286         return 0;
00287       }
00288       i=0;
00289       while(*p) {
00290         if (!isdigit((int)*p))
00291           break;
00292         if (*p==*t)
00293           break;
00294         i*=10;
00295         i+=(*p)-'0';
00296         p++;
00297       } /* while */
00298     }
00299     else {
00300       if (isdigit((int)*p))
00301         i=(*p)-'0';
00302       else
00303         i=-1;
00304       p++;
00305     }
00306 
00307     if (i==-1 && strchr("YMD", *t)!=NULL) {
00308       DBG_INFO(GWEN_LOGDOMAIN,
00309                "No more digits at [%s], continueing", t);
00310       p--;
00311     }
00312     else {
00313       switch(*t) {
00314       case 'Y':
00315         if (i==-1) {
00316           DBG_INFO(GWEN_LOGDOMAIN, "here");
00317           return 0;
00318         }
00319         year*=10;
00320         year+=i;
00321         break;
00322       case 'M':
00323         if (i==-1) {
00324           DBG_INFO(GWEN_LOGDOMAIN, "here");
00325           return 0;
00326         }
00327         month*=10;
00328         month+=i;
00329         break;
00330       case 'D':
00331         if (i==-1) {
00332           DBG_INFO(GWEN_LOGDOMAIN, "here");
00333           return 0;
00334         }
00335         day*=10;
00336         day+=i;
00337         break;
00338       default:
00339         DBG_VERBOUS(GWEN_LOGDOMAIN,
00340                     "Unknown character in template, will skip in both strings");
00341         break;
00342       }
00343     }
00344     t++;
00345   } /* while */
00346 
00347   if (year<100)
00348     year+=2000;
00349 
00350   DBG_DEBUG(GWEN_LOGDOMAIN,
00351             "Got this date/time: %04d/%02d/%02d",
00352             year, month, day);
00353 
00354   /* get time in local time */
00355   gwt=GWEN_Date_fromGregorian(year, month, day);
00356   if (!gwt) {
00357     DBG_INFO(GWEN_LOGDOMAIN, "here");
00358     return 0;
00359   }
00360   return gwt;
00361 }
00362 
00363 
00364 
00365 
00366 
00367 GWEN_LIST_FUNCTIONS(GWEN_DATE_TMPLCHAR, GWEN_DateTmplChar)
00368 
00369 
00370 GWEN_DATE_TMPLCHAR *GWEN_DateTmplChar_new(char c) {
00371   GWEN_DATE_TMPLCHAR *e;
00372 
00373   GWEN_NEW_OBJECT(GWEN_DATE_TMPLCHAR, e);
00374   GWEN_LIST_INIT(GWEN_DATE_TMPLCHAR, e);
00375   e->character=c;
00376   return e;
00377 }
00378 
00379 
00380 
00381 void GWEN_DateTmplChar_free(GWEN_DATE_TMPLCHAR *e) {
00382   if (e) {
00383     free(e->content);
00384     GWEN_LIST_FINI(GWEN_DATE_TMPLCHAR, e);
00385     GWEN_FREE_OBJECT(e);
00386   }
00387 }
00388 
00389 
00390 
00391 GWEN_DATE_TMPLCHAR *GWEN_Date__findTmplChar(GWEN_DATE_TMPLCHAR_LIST *ll, char c) {
00392   GWEN_DATE_TMPLCHAR *e;
00393 
00394   e=GWEN_DateTmplChar_List_First(ll);
00395   while(e) {
00396     if (e->character==c)
00397       break;
00398     e=GWEN_DateTmplChar_List_Next(e);
00399   }
00400 
00401   return e;
00402 }
00403 
00404 
00405 
00406 
00407 void GWEN_Date__sampleTmplChars(GWEN_UNUSED const GWEN_DATE *t, const char *tmpl,
00408                                 GWEN_UNUSED GWEN_BUFFER *buf,
00409                                 GWEN_DATE_TMPLCHAR_LIST *ll) {
00410   const char *s;
00411 
00412   s=tmpl;
00413   while(*s) {
00414     if (strchr("YMD", *s)) {
00415       GWEN_DATE_TMPLCHAR *e;
00416 
00417       e=GWEN_Date__findTmplChar(ll, *s);
00418       if (!e) {
00419         /* new entry, create it */
00420         e=GWEN_DateTmplChar_new(*s);
00421         GWEN_DateTmplChar_List_Add(e, ll);
00422       }
00423       assert(e);
00424       e->count++;
00425     }
00426     else {
00427       DBG_DEBUG(GWEN_LOGDOMAIN, "Unknown character in template (%02x)",
00428                 *s);
00429     }
00430     s++;
00431   }
00432 }
00433 
00434 
00435 
00436 void GWEN_Date__fillTmplChars(const GWEN_DATE *t, GWEN_DATE_TMPLCHAR_LIST *ll) {
00437   GWEN_DATE_TMPLCHAR *e;
00438 
00439 
00440   e=GWEN_DateTmplChar_List_First(ll);
00441   while(e) {
00442     int v;
00443     char buffer[32];
00444 
00445     switch(e->character) {
00446     case 'Y': v=t->year; break;
00447     case 'M': v=t->month; break;
00448     case 'D': v=t->day; break;
00449     default:  v=-1; break;
00450     }
00451     if (v==-1) {
00452       DBG_ERROR(GWEN_LOGDOMAIN, "Unknown character, should not happen here");
00453       abort();
00454     }
00455     buffer[0]=0;
00456     snprintf(buffer, sizeof(buffer)-1, "%0*d", GWEN_DATE_TMPL_MAX_COUNT, v);
00457     buffer[sizeof(buffer)-1]=0;
00458     e->content=strdup(buffer);
00459     e->nextChar=strlen(e->content)-(e->count);
00460     e=GWEN_DateTmplChar_List_Next(e);
00461   }
00462 }
00463 
00464 
00465 
00466 
00467 int GWEN_Date_toStringWithTemplate(const GWEN_DATE *t, const char *tmpl, GWEN_BUFFER *buf) {
00468   GWEN_DATE_TMPLCHAR_LIST *ll;
00469   const char *s;
00470 
00471   ll=GWEN_DateTmplChar_List_new();
00472   GWEN_Date__sampleTmplChars(t, tmpl, buf, ll);
00473   GWEN_Date__fillTmplChars(t, ll);
00474 
00475   s=tmpl;
00476   while(*s) {
00477     if (strchr("YMD", *s)) {
00478       GWEN_DATE_TMPLCHAR *e;
00479       char c;
00480 
00481       e=GWEN_Date__findTmplChar(ll, *s);
00482       assert(e);
00483       assert(e->content);
00484       c=e->content[e->nextChar++];
00485       assert(c);
00486       GWEN_Buffer_AppendByte(buf, c);
00487     }
00488     else
00489       GWEN_Buffer_AppendByte(buf, *s);
00490     s++;
00491   }
00492   GWEN_DateTmplChar_List_free(ll);
00493   return 0;
00494 }
00495 
00496 
00497 
00498 
00499 
00500 
00501 
00502 
00503