gwenhywfar
4.3.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 #include "i18n_l.h" 00032 00033 #include <gwenhywfar/debug.h> 00034 #include <gwenhywfar/misc.h> 00035 00036 00037 #include <time.h> 00038 #include <ctype.h> 00039 00040 00041 00042 static const uint8_t daysInMonth[12]={ 00043 31,28,31,30,31,30,31,31,30,31,30,31 00044 }; 00045 00046 00047 00048 00049 GWEN_DATE *GWEN_Date_fromGregorian(int y, int m, int d) { 00050 GWEN_DATE *gd; 00051 00052 if (m<1 || m>12 || d<1 || d>31) { 00053 DBG_ERROR(GWEN_LOGDOMAIN, "Bad date format"); 00054 return NULL; 00055 } 00056 00057 GWEN_NEW_OBJECT(GWEN_DATE, gd); 00058 gd->year=y; 00059 gd->month=m; 00060 gd->day=d; 00061 gd->julian=(1461*(y+4800+(m-14)/12))/4+ 00062 (367*(m-2-12*((m-14)/12)))/12- 00063 (3*((y+4900+(m-14)/12)/100))/4+ 00064 d-32075; 00065 00066 snprintf(gd->asString, sizeof(gd->asString)-1, 00067 "%04d%02d%02d", 00068 gd->year, gd->month, gd->day); 00069 gd->asString[sizeof(gd->asString)-1]=0; 00070 00071 return gd; 00072 } 00073 00074 00075 00076 GWEN_DATE *GWEN_Date_fromJulian(int julian) { 00077 GWEN_DATE *gd; 00078 int l, n, i, j; 00079 00080 GWEN_NEW_OBJECT(GWEN_DATE, gd); 00081 l=julian+68569; 00082 n=(4*l)/146097; 00083 l=l-(146097*n+3)/4; 00084 i=(4000*(l+1))/1461001; 00085 l=l-(1461*i)/4+31; 00086 j=(80*l)/2447; 00087 gd->day=l-(2447*j)/80; 00088 l=j/11; 00089 gd->month=j+2-(12*l); 00090 gd->year=100*(n-49)+i+l; 00091 gd->julian=julian; 00092 00093 snprintf(gd->asString, sizeof(gd->asString)-1, 00094 "%04d%02d%02d", 00095 gd->year, gd->month, gd->day); 00096 gd->asString[sizeof(gd->asString)-1]=0; 00097 00098 return gd; 00099 } 00100 00101 00102 00103 GWEN_DATE *GWEN_Date_fromLocalTime(time_t t) { 00104 struct tm *ltm; 00105 00106 ltm=localtime(&t); 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_fromGmTime(time_t t) { 00120 struct tm *ltm; 00121 00122 ltm=gmtime(&t); 00123 if (ltm) { 00124 GWEN_DATE *gd; 00125 00126 gd=GWEN_Date_fromGregorian(ltm->tm_year+1900, ltm->tm_mon+1, ltm->tm_mday); 00127 return gd; 00128 } 00129 00130 return NULL; 00131 } 00132 00133 00134 00135 00136 GWEN_DATE *GWEN_Date_CurrentDate(void) { 00137 time_t l; 00138 00139 time(&l); 00140 return GWEN_Date_fromLocalTime(l); 00141 } 00142 00143 00144 00145 GWEN_DATE *GWEN_Date_dup(const GWEN_DATE *ogd) { 00146 assert(ogd); 00147 return GWEN_Date_fromGregorian(ogd->year, ogd->month, ogd->day); 00148 } 00149 00150 00151 00152 GWEN_DATE *GWEN_Date_fromString(const char *s) { 00153 int y, m, d; 00154 00155 if (3==sscanf(s, "%04d%02d%02d", &y, &m, &d)) { 00156 return GWEN_Date_fromGregorian(y, m, d); 00157 } 00158 else { 00159 DBG_ERROR(GWEN_LOGDOMAIN, "Bad date [%s]", s); 00160 return NULL; 00161 } 00162 } 00163 00164 00165 00166 void GWEN_Date_free(GWEN_DATE *gd) { 00167 if (gd) { 00168 GWEN_FREE_OBJECT(gd); 00169 } 00170 } 00171 00172 00173 00174 int GWEN_Date_IsLeapYear(int y) { 00175 return ((y%4==0) && (y%100!=0)) || (y%400==0); 00176 } 00177 00178 00179 00180 00181 int GWEN_Date_DaysInMonth(const GWEN_DATE *gd) { 00182 assert(gd); 00183 if (gd->month==2 && 00184 ((((gd->year%4)==0) && ((gd->year)%100!=0)) || ((gd->year)%400==0))) 00185 /* February in a leap year */ 00186 return 29; 00187 else 00188 return daysInMonth[gd->month-1]; 00189 } 00190 00191 00192 00193 int GWEN_Date_DaysInYear(const GWEN_DATE *gd) { 00194 GWEN_DATE *gd11; 00195 int result; 00196 00197 assert(gd); 00198 00199 gd11=GWEN_Date_fromGregorian(gd->year, 1, 1); 00200 result=(gd->julian)-(gd11->julian); 00201 GWEN_Date_free(gd11); 00202 00203 return result; 00204 } 00205 00206 00207 00208 int GWEN_Date_GetYear(const GWEN_DATE *gd) { 00209 assert(gd); 00210 return gd->year; 00211 } 00212 00213 00214 00215 int GWEN_Date_GetMonth(const GWEN_DATE *gd) { 00216 assert(gd); 00217 return gd->month; 00218 } 00219 00220 00221 00222 int GWEN_Date_GetDay(const GWEN_DATE *gd) { 00223 assert(gd); 00224 return gd->day; 00225 } 00226 00227 00228 00229 int GWEN_Date_GetJulian(const GWEN_DATE *gd) { 00230 assert(gd); 00231 return gd->julian; 00232 } 00233 00234 00235 00236 int GWEN_Date_WeekDay(const GWEN_DATE *gd) { 00237 assert(gd); 00238 return (gd->julian+1)%7; /* 0=Sunday */ 00239 } 00240 00241 00242 00243 const char *GWEN_Date_GetString(const GWEN_DATE *gd) { 00244 assert(gd); 00245 return gd->asString; 00246 } 00247 00248 00249 00250 int GWEN_Date_Compare(const GWEN_DATE *gd1, const GWEN_DATE *gd0) { 00251 if (gd0 && gd1) { 00252 if (gd1->julian==gd0->julian) 00253 return 0; 00254 else if (gd1->julian>gd0->julian) 00255 return 1; 00256 else 00257 return -1; 00258 } 00259 else if (gd0) 00260 return 1; 00261 else if (gd1) 00262 return -1; 00263 else 00264 return 0; 00265 } 00266 00267 00268 00269 int GWEN_Date_Diff(const GWEN_DATE *gd1, const GWEN_DATE *gd0) { 00270 assert(gd1); 00271 assert(gd0); 00272 00273 return gd1->julian-gd0->julian; 00274 } 00275 00276 00277 00278 GWEN_DATE *GWEN_Date_fromTime(const GWEN_TIME *ti) { 00279 GWEN_BUFFER *tbuf; 00280 GWEN_DATE *gd; 00281 00282 tbuf=GWEN_Buffer_new(0, 32, 0, 1); 00283 GWEN_Time_toString(ti, "YYYYMMDD", tbuf); 00284 gd=GWEN_Date_fromString(GWEN_Buffer_GetStart(tbuf)); 00285 GWEN_Buffer_free(tbuf); 00286 00287 return gd; 00288 } 00289 00290 00291 00292 00293 GWEN_DATE *GWEN_Date_fromStringWithTemplate(const char *s, const char *tmpl){ 00294 int year, month, day; 00295 const char *p; 00296 const char *t; 00297 GWEN_DATE *gwt; 00298 00299 assert(s); 00300 assert(tmpl); 00301 year=month=day=0; 00302 00303 p=s; 00304 t=tmpl; 00305 while(*t && *p) { 00306 int i; 00307 00308 if (*t=='*') { 00309 t++; 00310 if (!*t) { 00311 DBG_ERROR(GWEN_LOGDOMAIN, "Bad pattern: Must not end with \"*\""); 00312 return 0; 00313 } 00314 i=0; 00315 while(*p) { 00316 if (!isdigit((int)*p)) 00317 break; 00318 if (*p==*t) 00319 break; 00320 i*=10; 00321 i+=(*p)-'0'; 00322 p++; 00323 } /* while */ 00324 } 00325 else { 00326 if (isdigit((int)*p)) 00327 i=(*p)-'0'; 00328 else 00329 i=-1; 00330 p++; 00331 } 00332 00333 if (i==-1 && strchr("YMD", *t)!=NULL) { 00334 DBG_INFO(GWEN_LOGDOMAIN, 00335 "No more digits at [%s], continueing", t); 00336 p--; 00337 } 00338 else { 00339 switch(*t) { 00340 case 'Y': 00341 if (i==-1) { 00342 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00343 return 0; 00344 } 00345 year*=10; 00346 year+=i; 00347 break; 00348 case 'M': 00349 if (i==-1) { 00350 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00351 return 0; 00352 } 00353 month*=10; 00354 month+=i; 00355 break; 00356 case 'D': 00357 if (i==-1) { 00358 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00359 return 0; 00360 } 00361 day*=10; 00362 day+=i; 00363 break; 00364 default: 00365 DBG_VERBOUS(GWEN_LOGDOMAIN, 00366 "Unknown character in template, will skip in both strings"); 00367 break; 00368 } 00369 } 00370 t++; 00371 } /* while */ 00372 00373 if (year<100) 00374 year+=2000; 00375 00376 DBG_DEBUG(GWEN_LOGDOMAIN, 00377 "Got this date/time: %04d/%02d/%02d", 00378 year, month, day); 00379 00380 /* get time in local time */ 00381 gwt=GWEN_Date_fromGregorian(year, month, day); 00382 if (!gwt) { 00383 DBG_INFO(GWEN_LOGDOMAIN, "here"); 00384 return 0; 00385 } 00386 return gwt; 00387 } 00388 00389 00390 00391 00392 00393 GWEN_LIST_FUNCTIONS(GWEN_DATE_TMPLCHAR, GWEN_DateTmplChar) 00394 00395 00396 GWEN_DATE_TMPLCHAR *GWEN_DateTmplChar_new(char c) { 00397 GWEN_DATE_TMPLCHAR *e; 00398 00399 GWEN_NEW_OBJECT(GWEN_DATE_TMPLCHAR, e); 00400 GWEN_LIST_INIT(GWEN_DATE_TMPLCHAR, e); 00401 e->character=c; 00402 switch(c) { 00403 case 'Y': e->maxCount=4; break; 00404 case 'M': e->maxCount=2; break; 00405 case 'D': e->maxCount=2; break; 00406 case 'W': e->maxCount=1; break; 00407 case 'w': 00408 default: e->maxCount=GWEN_DATE_TMPL_MAX_COUNT; break; 00409 } 00410 00411 return e; 00412 } 00413 00414 00415 00416 void GWEN_DateTmplChar_free(GWEN_DATE_TMPLCHAR *e) { 00417 if (e) { 00418 free(e->content); 00419 GWEN_LIST_FINI(GWEN_DATE_TMPLCHAR, e); 00420 GWEN_FREE_OBJECT(e); 00421 } 00422 } 00423 00424 00425 00426 GWEN_DATE_TMPLCHAR *GWEN_Date__findTmplChar(GWEN_DATE_TMPLCHAR_LIST *ll, char c) { 00427 GWEN_DATE_TMPLCHAR *e; 00428 00429 e=GWEN_DateTmplChar_List_First(ll); 00430 while(e) { 00431 if (e->character==c) 00432 break; 00433 e=GWEN_DateTmplChar_List_Next(e); 00434 } 00435 00436 return e; 00437 } 00438 00439 00440 00441 00442 void GWEN_Date__sampleTmplChars(GWEN_UNUSED const GWEN_DATE *t, const char *tmpl, 00443 GWEN_UNUSED GWEN_BUFFER *buf, 00444 GWEN_DATE_TMPLCHAR_LIST *ll) { 00445 const char *s; 00446 00447 s=tmpl; 00448 while(*s) { 00449 if (strchr("YMDWw", *s)) { 00450 GWEN_DATE_TMPLCHAR *e; 00451 00452 e=GWEN_Date__findTmplChar(ll, *s); 00453 if (!e) { 00454 /* new entry, create it */ 00455 e=GWEN_DateTmplChar_new(*s); 00456 GWEN_DateTmplChar_List_Add(e, ll); 00457 } 00458 assert(e); 00459 e->count++; 00460 } 00461 else { 00462 DBG_DEBUG(GWEN_LOGDOMAIN, "Unknown character in template (%02x)", 00463 *s); 00464 } 00465 s++; 00466 } 00467 } 00468 00469 00470 00471 void GWEN_Date__fillTmplChars(const GWEN_DATE *t, GWEN_DATE_TMPLCHAR_LIST *ll) { 00472 GWEN_DATE_TMPLCHAR *e; 00473 00474 00475 e=GWEN_DateTmplChar_List_First(ll); 00476 while(e) { 00477 int v; 00478 00479 if (e->character=='w') { 00480 const char *s=NULL; 00481 00482 switch(GWEN_Date_WeekDay(t)) { 00483 case 0: s=I18N("Sunday"); break; 00484 case 1: s=I18N("Monday"); break; 00485 case 2: s=I18N("Tuesday"); break; 00486 case 3: s=I18N("Wednesday"); break; 00487 case 4: s=I18N("Thursday"); break; 00488 case 5: s=I18N("Friday"); break; 00489 case 6: s=I18N("Saturday"); break; 00490 } 00491 assert(s); 00492 e->content=strdup(s); 00493 e->nextChar=0; 00494 } 00495 else { 00496 char buffer[32]; 00497 int clen; 00498 00499 switch(e->character) { 00500 case 'Y': 00501 v=t->year; 00502 break; 00503 case 'M': 00504 v=t->month; 00505 break; 00506 case 'D': 00507 v=t->day; 00508 break; 00509 case 'W': 00510 v=GWEN_Date_WeekDay(t); 00511 break; 00512 default: 00513 v=-1; 00514 break; 00515 } 00516 if (v==-1) { 00517 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown character, should not happen here"); 00518 abort(); 00519 } 00520 buffer[0]=0; 00521 snprintf(buffer, sizeof(buffer)-1, "%0*d", e->maxCount, v); 00522 buffer[sizeof(buffer)-1]=0; 00523 e->content=strdup(buffer); 00524 /* adjust counter if there are more than maxCount template chars */ 00525 clen=strlen(e->content); 00526 if (e->count>clen) 00527 e->count=clen; 00528 e->nextChar=clen-(e->count); 00529 } 00530 00531 e=GWEN_DateTmplChar_List_Next(e); 00532 } 00533 } 00534 00535 00536 00537 00538 int GWEN_Date_toStringWithTemplate(const GWEN_DATE *t, const char *tmpl, GWEN_BUFFER *buf) { 00539 GWEN_DATE_TMPLCHAR_LIST *ll; 00540 const char *s; 00541 00542 ll=GWEN_DateTmplChar_List_new(); 00543 GWEN_Date__sampleTmplChars(t, tmpl, buf, ll); 00544 GWEN_Date__fillTmplChars(t, ll); 00545 00546 s=tmpl; 00547 while(*s) { 00548 if (strchr("YMDWw", *s)) { 00549 GWEN_DATE_TMPLCHAR *e; 00550 char c; 00551 00552 e=GWEN_Date__findTmplChar(ll, *s); 00553 assert(e); 00554 assert(e->content); 00555 if (s[1]=='*') { 00556 /* append full string */ 00557 GWEN_Buffer_AppendString(buf, e->content); 00558 /* skip asterisk */ 00559 s++; 00560 } 00561 else { 00562 c=e->content[e->nextChar]; 00563 if (c!=0) { 00564 GWEN_Buffer_AppendByte(buf, c); 00565 e->nextChar++; 00566 } 00567 } 00568 } 00569 else 00570 GWEN_Buffer_AppendByte(buf, *s); 00571 s++; 00572 } 00573 GWEN_DateTmplChar_List_free(ll); 00574 return 0; 00575 } 00576 00577 00578 00579 00580 00581 00582 00583 00584