Projekt

Allgemein

Profil

Herunterladen (16,3 KB) Statistiken
| Zweig: | Markierung: | Revision:
c031313e aquamaniac
/***************************************************************************
$RCSfile$
-------------------
cvs : $Id$
begin : Sun Nov 23 2003
copyright : (C) 2003 by Martin Preuss
email : martin@libchipcard.de

***************************************************************************
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of the GNU Lesser General Public *
* License as published by the Free Software Foundation; either *
* version 2.1 of the License, or (at your option) any later version. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this library; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
* MA 02111-1307 USA *
* *
***************************************************************************/


#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

c7df94e8 aquamaniac
#define DISABLE_DEBUGLOG

c031313e aquamaniac
e309231a aquamaniac
#include "gwentime_p.h"
c031313e aquamaniac
#include <gwenhywfar/gwentime.h>
#include <gwenhywfar/debug.h>

#include <time.h>
#include <ctype.h>
e309231a aquamaniac
#include <errno.h>
#include <string.h>


4574aaa3 aquamaniac
GWEN_LIST_FUNCTIONS(GWEN_TIME_TMPLCHAR, GWEN_TimeTmplChar)


e309231a aquamaniac
fab53b9f martin
GWEN_TIME *GWEN_CurrentTime(void){
e309231a aquamaniac
GWEN_TIME *t;

GWEN_NEW_OBJECT(GWEN_TIME, t);
if (GWEN_Time__GetCurrentTime(t)) {
8b7674e6 aquamaniac
DBG_ERROR(GWEN_LOGDOMAIN, "Could not get current time");
e309231a aquamaniac
GWEN_Time_free(t);
return 0;
}
return t;
}



da13b417 martin
GWEN_TIME *GWEN_Time_fromSeconds(uint32_t secs) {
e309231a aquamaniac
GWEN_TIME *t;

GWEN_NEW_OBJECT(GWEN_TIME, t);
t->secs=secs;
return t;
}



4d783311 aquamaniac
int GWEN_Time_AddSeconds(GWEN_TIME *ti,
da13b417 martin
uint32_t secs) {
uint32_t i;
4d783311 aquamaniac
assert(ti);
i=ti->secs+secs;
if (i<ti->secs) {
DBG_INFO(GWEN_LOGDOMAIN,
da13b417 martin
"Overflow when adding %u seconds", secs);
4d783311 aquamaniac
return GWEN_ERROR_INVALID;
}
ti->secs=i;
return 0;
}



int GWEN_Time_SubSeconds(GWEN_TIME *ti,
da13b417 martin
uint32_t secs) {
4d783311 aquamaniac
assert(ti);

if (ti->secs<secs) {
DBG_INFO(GWEN_LOGDOMAIN,
da13b417 martin
"Underflow when subtracting %u seconds",
4d783311 aquamaniac
secs);
return GWEN_ERROR_INVALID;
}
ti->secs-=secs;
return 0;
}


e309231a aquamaniac
void GWEN_Time__SetSecsAndMSecs(GWEN_TIME *ti,
da13b417 martin
uint32_t secs,
uint32_t msecs){
e309231a aquamaniac
assert(ti);
ti->secs=secs;
ti->msecs=msecs;
}
c031313e aquamaniac


int GWEN_Time_toDb(const GWEN_TIME *t, GWEN_DB_NODE *db) {
GWEN_DB_NODE *dbT;
int i1, i2, i3;

assert(t);
assert(db);
dbT=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, "date");
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS,
"inUtc", 1);

assert(dbT);
if (GWEN_Time_GetBrokenDownUtcDate(t, &i1, &i2, &i3)) {
8b7674e6 aquamaniac
DBG_INFO(GWEN_LOGDOMAIN, "Could not break down date");
c031313e aquamaniac
return -1;
}
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
"day", i1);
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
e309231a aquamaniac
"month", i2+1);
c031313e aquamaniac
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
"year", i3);

dbT=GWEN_DB_GetGroup(db, GWEN_DB_FLAGS_DEFAULT, "time");
assert(dbT);
if (GWEN_Time_GetBrokenDownUtcTime(t, &i1, &i2, &i3)) {
8b7674e6 aquamaniac
DBG_INFO(GWEN_LOGDOMAIN, "Could not break down time");
c031313e aquamaniac
return -1;
}
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
e309231a aquamaniac
"hour", i1);
c031313e aquamaniac
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
e309231a aquamaniac
"min", i2);
c031313e aquamaniac
GWEN_DB_SetIntValue(dbT, GWEN_DB_FLAGS_OVERWRITE_VARS,
e309231a aquamaniac
"sec", i3);
c031313e aquamaniac
return 0;
}



GWEN_TIME *GWEN_Time_fromDb(GWEN_DB_NODE *db) {
GWEN_TIME *t;
GWEN_DB_NODE *dbT;
int day, month, year;
int hour, min, sec;
int inUtc;

day=month=year=0;
hour=min=sec=0;

17f96690 aquamaniac
inUtc=GWEN_DB_GetIntValue(db, "inUtc", 0, 0);
c031313e aquamaniac
dbT=GWEN_DB_GetGroup(db, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "date");
if (dbT) {
day=GWEN_DB_GetIntValue(dbT, "day", 0, 0);
e309231a aquamaniac
month=GWEN_DB_GetIntValue(dbT, "month", 0, 1)-1;
c031313e aquamaniac
year=GWEN_DB_GetIntValue(dbT, "year", 0, 0);
if (!day || !year) {
8b7674e6 aquamaniac
DBG_INFO(GWEN_LOGDOMAIN, "Bad date in DB");
c031313e aquamaniac
return 0;
}
}

dbT=GWEN_DB_GetGroup(db, GWEN_PATH_FLAGS_NAMEMUSTEXIST, "time");
if (dbT) {
hour=GWEN_DB_GetIntValue(dbT, "hour", 0, 0);
min=GWEN_DB_GetIntValue(dbT, "min", 0, 0);
sec=GWEN_DB_GetIntValue(dbT, "sec", 0, 0);
}

c7df94e8 aquamaniac
DBG_VERBOUS(GWEN_LOGDOMAIN,
"Creating time from this: %04d/%02d/%02d - %02d:%02d:%02d (%d)",
year, month, day, hour, min, sec, inUtc);
c031313e aquamaniac
t=GWEN_Time_new(year, month, day, hour, min, sec, inUtc);
if (!t) {
8b7674e6 aquamaniac
DBG_INFO(GWEN_LOGDOMAIN, "Bad date/time");
c031313e aquamaniac
return 0;
}

return t;
}



2b8d4ccd aquamaniac
GWEN_TIME *GWEN_Time__fromString(const char *s, const char *tmpl, int inUtc){
c031313e aquamaniac
int year, month, day;
int hour, min, sec;
const char *p;
const char *t;
GWEN_TIME *gwt;

assert(s);
assert(tmpl);
year=month=day=0;
hour=min=sec=0;

p=s;
t=tmpl;
while(*t && *p) {
int i;

e0647d56 aquamaniac
if (*t=='*') {
t++;
if (!*t) {
DBG_ERROR(GWEN_LOGDOMAIN, "Bad pattern: Must not end with \"*\"");
return 0;
}
i=0;
while(*p) {
if (!isdigit((int)*p))
break;
if (*p==*t)
break;
i*=10;
i+=(*p)-'0';
p++;
} /* while */
}
else {
if (isdigit((int)*p))
i=(*p)-'0';
else
i=-1;
p++;
}
c031313e aquamaniac
da13b417 martin
if (i==-1 && strchr("YMDhms", *t)!=NULL) {
8023746e martin
DBG_INFO(GWEN_LOGDOMAIN,
dc2b863e mlenk
"No more digits at [%s], continuing", t);
da13b417 martin
p--;
}
else {
switch(*t) {
case 'Y':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
year*=10;
year+=i;
break;
case 'M':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
month*=10;
month+=i;
break;
case 'D':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
day*=10;
day+=i;
break;
case 'h':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
hour*=10;
hour+=i;
break;
case 'm':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
min*=10;
min+=i;
break;
case 's':
if (i==-1) {
DBG_INFO(GWEN_LOGDOMAIN, "here");
return 0;
}
sec*=10;
sec+=i;
break;
default:
DBG_VERBOUS(GWEN_LOGDOMAIN,
"Unknown character in template, will skip in both strings");
break;
}
c031313e aquamaniac
}
t++;
} /* while */

8096d169 aquamaniac
if (year<100)
year+=2000;
83a70cb6 martin
if (day==0)
day=1;
8096d169 aquamaniac
da13b417 martin
DBG_DEBUG(GWEN_LOGDOMAIN,
"Got this date/time: %04d/%02d/%02d, %02d:%02d:%02d",
year, month-1, day, hour, min, sec);

c031313e aquamaniac
/* get time in local time */
e309231a aquamaniac
gwt=GWEN_Time_new(year, month-1, day, hour, min, sec, inUtc);
c031313e aquamaniac
if (!gwt) {
8b7674e6 aquamaniac
DBG_INFO(GWEN_LOGDOMAIN, "here");
c031313e aquamaniac
return 0;
}
return gwt;
}



2b8d4ccd aquamaniac
GWEN_TIME *GWEN_Time_fromString(const char *s, const char *tmpl){
return GWEN_Time__fromString(s, tmpl, 0);
}



GWEN_TIME *GWEN_Time_fromUtcString(const char *s, const char *tmpl){
return GWEN_Time__fromString(s, tmpl, 1);
}



e309231a aquamaniac
GWEN_TIME *GWEN_Time_new(int year,
int month,
int day,
int hour,
int min,
int sec,
int inUtc){
da13b417 martin
uint32_t s;
e309231a aquamaniac
if (inUtc)
s=GWEN_Time__mktimeUtc(year, month, day, hour, min, sec);
else {
struct tm ti;
struct tm *tp;
time_t tt;

tt=time(0);
tp=localtime(&tt);
assert(tp);
memmove(&ti, tp, sizeof(ti));
ti.tm_sec=sec;
ti.tm_min=min;
ti.tm_hour=hour;
if (year<100) {
if (year<72)
year+=2000;
year+=1900;
}
ti.tm_year=year-1900;
17f96690 aquamaniac
ti.tm_mon=month;
e309231a aquamaniac
ti.tm_mday=day;
ti.tm_yday=0;
ti.tm_wday=0;
tt=mktime(&ti);
assert(tt!=(time_t)-1);
da13b417 martin
s=(uint32_t)tt;
e309231a aquamaniac
}
return GWEN_Time_fromSeconds(s);
}



da13b417 martin
uint32_t GWEN_Time__mktimeUtc(int year,
e309231a aquamaniac
int month,
int day,
int hour,
int min,
int sec) {
da13b417 martin
uint32_t result;
e309231a aquamaniac
int i;
int isLeap;
da13b417 martin
const uint32_t hoursecs=60*60;
const uint32_t daysecs=24*hoursecs;
const uint32_t yearsecs=365*daysecs;
const uint32_t monthDays[12]=
e309231a aquamaniac
{
31, 28, 31, 30,
31, 30, 31, 31,
30, 31, 30, 31
};

result=(year-1970)*yearsecs;

for (i=1970; i<year; i++)
if ((((i % 4)==0) &&
((i % 100)!=0)) ||
((i % 400)==0))
result+=daysecs;

isLeap=((((year % 4)==0) &&
((year % 100)!=0)) ||
((year % 400)==0));

for (i=0; i<month; i++)
if (isLeap && i==1)
result+=29*daysecs;
else
result+=monthDays[i]*daysecs;

result+=(day-1)*daysecs;
result+=(hour*hoursecs);
result+=min*60;
result+=sec;

return result;
}



GWEN_TIME *GWEN_Time_dup(const GWEN_TIME *t){
GWEN_TIME *newT;
2b8d4ccd aquamaniac
e309231a aquamaniac
assert(t);
GWEN_NEW_OBJECT(GWEN_TIME, newT);
newT->secs=t->secs;
newT->msecs=t->msecs;
return newT;
}
2b8d4ccd aquamaniac
c031313e aquamaniac

e309231a aquamaniac
void GWEN_Time_free(GWEN_TIME *t){
if (t) {
GWEN_FREE_OBJECT(t);
}
}



double GWEN_Time_Diff(const GWEN_TIME *t1, const GWEN_TIME *t0){
double d;

assert(t1);
assert(t0);

bd4e684a aquamaniac
d=1000.0*((double)(t1->secs)-(double)(t0->secs));
d+=(double)((double)(t1->msecs)-(double)(t0->msecs));
e309231a aquamaniac
return d;
}



31cdd19a aquamaniac
double GWEN_Time_DiffSeconds(const GWEN_TIME *t1, const GWEN_TIME *t0){
double d;

assert(t1);
assert(t0);

d=(double)(t1->secs)-(double)(t0->secs);
d+=((double)((double)(t1->msecs)-(double)(t0->msecs)))/1000.0;

return d;
}



eb2c12a4 martin
int GWEN_Time_Compare(const GWEN_TIME *t1, const GWEN_TIME *t0){
if (t1 && t0) {
if (t1->secs<t0->secs)
return -1;
else if (t1->secs>t0->secs)
return 1;
else {
if (t1->msecs<t0->msecs)
return -1;
else if (t1->msecs>t0->msecs)
return 1;
else
return 0;
}
}
else if (t1)
return 1;
else if (t0)
return -1;

return 0;
}



e309231a aquamaniac
double GWEN_Time_Milliseconds(const GWEN_TIME *t){
assert(t);
return (double)((t->secs*1000)+(t->msecs));
}



da13b417 martin
uint32_t GWEN_Time_Seconds(const GWEN_TIME *t){
e309231a aquamaniac
assert(t);
return t->secs;
}



int GWEN_Time_GetBrokenDownTime(const GWEN_TIME *t,
int *hours,
int *mins,
int *secs){
struct tm *tb;
time_t tt;

assert(t);
tt=t->secs;
tb=localtime(&tt);
if (!tb) {
8b7674e6 aquamaniac
DBG_ERROR(GWEN_LOGDOMAIN, "localtime(): %s", strerror(errno));
e309231a aquamaniac
return -1;
}
*hours=tb->tm_hour;
*mins=tb->tm_min;
*secs=tb->tm_sec;
return 0;
}



int GWEN_Time_GetBrokenDownUtcTime(const GWEN_TIME *t,
int *hours,
int *mins,
int *secs){
struct tm *tb;
time_t tt;

assert(t);
tt=t->secs;
tb=gmtime(&tt);
if (!tb) {
8b7674e6 aquamaniac
DBG_ERROR(GWEN_LOGDOMAIN, "gmtime(): %s", strerror(errno));
e309231a aquamaniac
return -1;
}
*hours=tb->tm_hour;
*mins=tb->tm_min;
*secs=tb->tm_sec;
return 0;
}



int GWEN_Time_GetBrokenDownDate(const GWEN_TIME *t,
int *days,
int *month,
int *year){
struct tm *tb;
time_t tt;

assert(t);
tt=t->secs;
tb=localtime(&tt);
if (!tb) {
8b7674e6 aquamaniac
DBG_ERROR(GWEN_LOGDOMAIN, "localtime(): %s", strerror(errno));
e309231a aquamaniac
return -1;
}
*days=tb->tm_mday;
*month=tb->tm_mon;
*year=tb->tm_year+1900;
return 0;
}



int GWEN_Time_GetBrokenDownUtcDate(const GWEN_TIME *t,
int *days,
int *month,
int *year){
struct tm *tb;
time_t tt;

assert(t);
tt=t->secs;
tb=gmtime(&tt);
if (!tb) {
8b7674e6 aquamaniac
DBG_ERROR(GWEN_LOGDOMAIN, "gmtime(): %s", strerror(errno));
e309231a aquamaniac
return -1;
}
*days=tb->tm_mday;
*month=tb->tm_mon;
*year=tb->tm_year+1900;
return 0;
}

c031313e aquamaniac

85718285 martin
/* TODO: compiler says "function returns an aggregate" */
cda26b7b aquamaniac
struct tm GWEN_Time_toTm(const GWEN_TIME *t) {
fc89fb27 cstim
struct tm *tb;
time_t tt;
c031313e aquamaniac
fc89fb27 cstim
assert(t);
tt=t->secs;
tb=localtime(&tt);
return *tb;
}
c031313e aquamaniac
cda26b7b aquamaniac
time_t GWEN_Time_toTime_t(const GWEN_TIME *t) {
fc89fb27 cstim
assert(t);
return t->secs;
}
c031313e aquamaniac
4574aaa3 aquamaniac


GWEN_TIME_TMPLCHAR *GWEN_TimeTmplChar_new(char c) {
GWEN_TIME_TMPLCHAR *e;

GWEN_NEW_OBJECT(GWEN_TIME_TMPLCHAR, e);
GWEN_LIST_INIT(GWEN_TIME_TMPLCHAR, e);
e->character=c;
return e;
}



void GWEN_TimeTmplChar_free(GWEN_TIME_TMPLCHAR *e) {
if (e) {
free(e->content);
GWEN_LIST_FINI(GWEN_TIME_TMPLCHAR, e);
GWEN_FREE_OBJECT(e);
}
}


GWEN_TIME_TMPLCHAR *GWEN_Time__findTmplChar(GWEN_TIME_TMPLCHAR_LIST *ll,
char c) {
GWEN_TIME_TMPLCHAR *e;

e=GWEN_TimeTmplChar_List_First(ll);
while(e) {
if (e->character==c)
break;
e=GWEN_TimeTmplChar_List_Next(e);
}

return e;
}




85718285 martin
void GWEN_Time__sampleTmplChars(GWEN_UNUSED const GWEN_TIME *t, const char *tmpl,
GWEN_UNUSED GWEN_BUFFER *buf,
4574aaa3 aquamaniac
GWEN_TIME_TMPLCHAR_LIST *ll) {
const char *s;

s=tmpl;
while(*s) {
if (strchr("YMDhms", *s)) {
GWEN_TIME_TMPLCHAR *e;

e=GWEN_Time__findTmplChar(ll, *s);
if (!e) {
/* new entry, create it */
e=GWEN_TimeTmplChar_new(*s);
GWEN_TimeTmplChar_List_Add(e, ll);
}
assert(e);
e->count++;
}
else {
DBG_DEBUG(GWEN_LOGDOMAIN, "Unknown character in template (%02x)",
*s);
}
s++;
}
}



void GWEN_Time__fillTmplChars(const GWEN_TIME *t,
GWEN_TIME_TMPLCHAR_LIST *ll,
int useUtc) {
GWEN_TIME_TMPLCHAR *e;
int year, month, day, hour, minute, second;

if (useUtc) {
GWEN_Time_GetBrokenDownUtcDate(t, &day, &month, &year);
GWEN_Time_GetBrokenDownUtcTime(t, &hour, &minute, &second);
}
else {
GWEN_Time_GetBrokenDownDate(t, &day, &month, &year);
GWEN_Time_GetBrokenDownTime(t, &hour, &minute, &second);
}

e=GWEN_TimeTmplChar_List_First(ll);
while(e) {
int v;
char buffer[32];

switch(e->character) {
case 'Y': v=year; break;
case 'M': v=month+1; break;
case 'D': v=day; break;
case 'h': v=hour; break;
case 'm': v=minute; break;
case 's': v=second; break;
default: v=-1; break;
}
if (v==-1) {
DBG_ERROR(GWEN_LOGDOMAIN, "Unknown character, should not happen here");
abort();
}
buffer[0]=0;
snprintf(buffer, sizeof(buffer)-1, "%0*d", GWEN_TIME_TMPL_MAX_COUNT, v);
buffer[sizeof(buffer)-1]=0;
e->content=strdup(buffer);
e->nextChar=strlen(e->content)-(e->count);
e=GWEN_TimeTmplChar_List_Next(e);
}
}




int GWEN_Time__toString(const GWEN_TIME *t, const char *tmpl,
GWEN_BUFFER *buf, int useUtc) {
GWEN_TIME_TMPLCHAR_LIST *ll;
const char *s;

ll=GWEN_TimeTmplChar_List_new();
GWEN_Time__sampleTmplChars(t, tmpl, buf, ll);
GWEN_Time__fillTmplChars(t, ll, useUtc);

s=tmpl;
while(*s) {
if (strchr("YMDhms", *s)) {
GWEN_TIME_TMPLCHAR *e;
char c;

e=GWEN_Time__findTmplChar(ll, *s);
assert(e);
assert(e->content);
e251316f martin
if (s[1]=='*') {
/* append full string */
GWEN_Buffer_AppendString(buf, e->content);
/* skip asterisk */
s++;
}
else {
c=e->content[e->nextChar++];
assert(c);
GWEN_Buffer_AppendByte(buf, c);
}
4574aaa3 aquamaniac
}
else
GWEN_Buffer_AppendByte(buf, *s);
s++;
}
GWEN_TimeTmplChar_List_free(ll);
return 0;
}



int GWEN_Time_toString(const GWEN_TIME *t, const char *tmpl,
GWEN_BUFFER *buf) {
return GWEN_Time__toString(t, tmpl, buf, 0);
}



int GWEN_Time_toUtcString(const GWEN_TIME *t, const char *tmpl,
GWEN_BUFFER *buf) {
return GWEN_Time__toString(t, tmpl, buf, 1);
}