gwenhywfar 4.0.3
|
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