TPCCLIB
Loading...
Searching...
No Matches
datetime.c
Go to the documentation of this file.
1
6/*****************************************************************************/
7#include "libtpcmisc.h"
8/*****************************************************************************/
9#include <locale.h>
10#include <unistd.h>
11#include <time.h>
12/*****************************************************************************/
13
14/*****************************************************************************/
15#ifndef HAVE_GMTIME_R
22struct tm* gmtime_r(
25 const time_t *t,
27 struct tm *tm
28) {
29 struct tm *ltm=gmtime(t);
30 if(ltm==NULL || tm==NULL) return(NULL);
31 *tm=*ltm; tm->tm_isdst=-1;
32 return tm;
33}
34#endif // HAVE_GMTIME_R
35/*****************************************************************************/
36
37/*****************************************************************************/
38#ifndef HAVE_LOCALTIME_R
46struct tm* localtime_r(
49 const time_t *t,
51 struct tm *tm
52) {
53 struct tm *ltm=localtime(t);
54 if(ltm==NULL || tm==NULL) return(NULL);
55 *tm=*ltm; tm->tm_isdst=-1;
56 return tm;
57}
58#endif // HAVE_LOCALTIME_R
59/*****************************************************************************/
60
61/*****************************************************************************/
62#ifndef HAVE_TIMEGM
69time_t timegm(
71 struct tm *tm
72) {
73#ifdef HAVE_GMTIME_R
74 {
75 time_t temp_lt;
76 struct tm temp_gm;
77 if(!tm) temp_lt=0; else temp_lt=mktime(tm);
78 if(gmtime_r(&temp_lt, &temp_gm)==NULL) return((time_t)-1);
79 return(time_t)(temp_lt + (temp_lt - mktime(&temp_gm)));
80 }
81#endif
82
83#ifdef HAVE_GMTIME_S
84 {
85 time_t temp_lt;
86 struct tm temp_gm;
87 if(!tm) temp_lt=0; else temp_lt=mktime(tm);
88 if(gmtime_s(&temp_gm, &temp_lt)!=0) return(time_t)-1);
89 return(time_t)(temp_lt + (temp_lt - mktime(&temp_gm)));
90 }
91#endif
92
93 time_t temp_lt;
94 struct tm *temp_gm;
95 if(!tm) temp_lt=0; else {tm->tm_isdst=-1; temp_lt=mktime(tm);}
96 temp_gm=gmtime(&temp_lt); if(temp_gm) temp_gm->tm_isdst=-1;
97 return(time_t)(temp_lt + (temp_lt - mktime(temp_gm)));
98}
99#endif // HAVE_TIMEGM
100/*****************************************************************************/
101
102/*****************************************************************************/
113 const time_t *t,
116 char *buf
117) {
118 if(buf==NULL) return(NULL);
119 buf[0]=(char)0;
120 struct tm tm;
121 if(!gmtime_r(t, &tm)) return(NULL);
122 if(!strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &tm)) return(NULL);
123 return(buf);
124}
125/*****************************************************************************/
126
127/*****************************************************************************/
129/* How many days come before each month (0-12). */
130static const unsigned short __mon_yday[2][13] = {
131 /* Normal years. */
132 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
133 /* Leap years. */
134 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
135};
137/*****************************************************************************/
138
139/*****************************************************************************/
148 char *str
149) {
150 int Y, M, D, n;
151 if(strlen(str)<10) return 1;
152 if(str[4]!='-' || str[7]!='-') return 2;
153 if(strncasecmp(str, "YYYY-MM-DD", 10)==0) return -1;
154 n=sscanf(str, "%4d-%2d-%2d", &Y, &M, &D); if(n!=3) return 3;
155 if(M>12 || D>31) return -1;
156 if(Y<0 || M<1 || D<1) return -1;
157 return 0;
158}
159/*****************************************************************************/
160
161/*****************************************************************************/
170 char *str,
173 char *intdate
174) {
175 int Y, M, D, n;
176 if(strlen(str)<10) return 1;
177 if(str[2]!='.' && str[2]!='/') return 2;
178 if(str[5]!='.' && str[5]!='/') return 2;
179 if(isspace(str[8])) return 2;
180 if(strncasecmp(str, "DD.MM.YYYY", 10)==0 ||
181 strncasecmp(str, "DD/MM/YYYY", 10)==0) return -1;
182 n=sscanf(str, "%2d/%2d/%4d", &D, &M, &Y);
183 if(n<3) n=sscanf(str, "%2d.%2d.%4d", &D, &M, &Y);
184 if(n!=3) return 3;
185 if(M>12 || D>31) return -1;
186 if(Y<0 || M<1 || D<1) return -1;
187 if(intdate!=NULL) sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
188 return 0;
189}
190/*****************************************************************************/
191
192/*****************************************************************************/
201 char *str,
204 char *intdate
205) {
206 int Y, M, D, n;
207 if(strlen(str)<8) return 1;
208 if(str[2]!='.' && str[2]!='/') return 2;
209 if(str[5]!='.' && str[5]!='/') return 2;
210 if(strncasecmp(str, "DD.MM.YY", 8)==0 ||
211 strncasecmp(str, "DD/MM/YY", 8)==0) return -1;
212 n=sscanf(str, "%2d/%2d/%2d", &D, &M, &Y);
213 if(n<3) n=sscanf(str, "%2d.%2d.%2d", &D, &M, &Y);
214 if(n!=3) return 3;
215 if(Y>99 || M>12 || D>31) return -1;
216 if(Y<0 || M<1 || D<1) return -1;
217 if(intdate!=NULL) {
218 if(Y>=70) Y+=1900; else Y+=2000;
219 sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
220 }
221 return 0;
222}
223/*****************************************************************************/
224
225/*****************************************************************************/
232 int dateint,
234 int *year,
236 int *month,
238 int *day
239) {
240 int Y, M, D, n;
241 if(dateint<1201 || dateint>99991231) return 1;
242 n=dateint/100; D=dateint-100*n; Y=n/100; M=n-100*Y;
243 if(M>12 || D>31) return -1;
244 if(Y<1 || M<1 || D<1) return -1;
245 if(year!=NULL) *year=Y;
246 if(month!=NULL) *month=M;
247 if(day!=NULL) *day=D;
248 return 0;
249}
250/*****************************************************************************/
251
252/*****************************************************************************/
261 char *str
262) {
263 int h, m, s, n;
264 if(strlen(str)<8) return 1;
265 if(str[2]!=':' || str[5]!=':') return 2;
266 if(strncasecmp(str, "hh:mm:ss", 8)==0) return -1;
267 n=sscanf(str, "%d:%d:%d", &h, &m, &s); if(n!=3) return 3;
268 if(h<0 || h>23 || m<0 || m>59 || s<0 || s>59) return -1;
269 return 0;
270}
271/*****************************************************************************/
272
273/*****************************************************************************/
282 char *str,
286 char *intdate
287) {
288 int ret1, ret2, len, type=0;
289 char correct_date[20], *time_ptr=NULL;
290
291 len=strlen(str); if(len<17) return 1;
292 if((ret1=isdate(str))<=0) {
293 type=1; strncpy(correct_date, str, 10); correct_date[10]=(char)0;
294 } else if((ret1=isdate2(str, correct_date))<=0) type=2;
295 else if((ret1=isdate3(str, correct_date))<=0) type=3;
296 else {return 2;}
297 if(type==1 || type==2) {
298 if(str[10]!=' ' && str[10]!='\t') return 3;
299 time_ptr=str+11;
300 } else if(type==3) {
301 if(str[8]!=' ' && str[8]!='\t') return 3;
302 time_ptr=str+9;
303 }
304 ret2=istime(time_ptr);
305 if(ret1>0) {
306 if(ret2>=0) return(100*ret1+ret2); else return(100*ret2);
307 }
308 if(ret2>0) return(10*ret2);
309 if(ret1<0) {if(ret2<0) return(-3); else return(-1);}
310 if(ret2<0) return(-2);
311 if(intdate!=NULL) {
312 sprintf(intdate, "%10.10s %8.8s", correct_date, time_ptr);
313 }
314 return 0;
315}
316/*****************************************************************************/
317
318/*****************************************************************************/
326 char *str,
328 struct tm *date,
330 int verbose
331) {
332 char buf[32];
333 int ret, n, YYYY=0, MM=0, DD=0, hh=0, mm=0, ss=0;
334
335 if(verbose>0) printf("get_datetime(%s)\n", str);
336 if(date==NULL) return(1);
337 ret=isdatetime(str, buf); if(ret!=0) return(ret);
338 n=sscanf(buf, "%d-%d-%d %d:%d:%d", &YYYY, &MM, &DD, &hh, &mm, &ss);
339 if(n!=6) return(40);
340 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
341 date->tm_hour=hh; date->tm_min=mm; date->tm_sec=ss;
342 date->tm_isdst=-1;
343#ifdef HAVE_TM_GMTOFF
344 date->tm_gmtoff=0L;
345#endif
346 if(verbose>2) {
347 printf("tm_mday=%d\n", date->tm_mday);
348 printf("tm_mon=%d\n", date->tm_mon);
349 printf("tm_year=%d\n", date->tm_year);
350 printf("tm_hour=%d\n", date->tm_hour);
351 time_t t=timegm(date);
352 printf(" tm_hour=%d\n", date->tm_hour);
353 printf("time_t=%ld\n", (long)t);
354 printf("time_t_int=%d\n", (int)t);
355 }
356// if(mktime(date)==-1 && date->tm_year<70) {
357 if(timegm(date)==-1 && date->tm_year<70) {
358 if(verbose>2) printf("tm_mday=%d\n", date->tm_mday);
359 if(verbose>1) printf("mktime() fails\n");
360 /* Date and time format was previously verified, so lets put
361 1970-01-01 01:00:00 instead */
362 date->tm_year=70; date->tm_mday=1; date->tm_mon=0;
363 date->tm_hour=1; date->tm_min=0; date->tm_sec=0;
364 date->tm_yday=0;
365 date->tm_isdst=-1;
366 mktime(date);
367 }
368 if(verbose>1) printf(" tm_hour=%d\n", date->tm_hour);
369 return(0);
370}
371/*****************************************************************************/
372
373/*****************************************************************************/
381 char *str,
383 struct tm *date
384) {
385 char buf[32];
386 int ret, n, YYYY=0, MM=0, DD=0;
387
388 if(strlen(str)<8) return 1;
389 if((ret=isdate(str))<=0) {
390 strncpy(buf, str, 10); buf[10]=(char)0;
391 } else {
392 ret=isdate2(str, buf);
393 if(ret>0) ret=isdate3(str, buf);
394 }
395 if(ret>0) return 2;
396 n=sscanf(buf, "%d-%d-%d", &YYYY, &MM, &DD);
397 if(n!=3) return(3);
398 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
399 date->tm_hour=0; date->tm_min=0; date->tm_sec=0; date->tm_isdst=-1;
400 ret=strftime(buf, 32, "%Y-%m-%d %H:%M:%S", date);
401 if(ret==0) return(4);
402 return(0);
403}
404/*****************************************************************************/
405
406/*****************************************************************************/
409long int math_div(
411 long int a,
413 long int b
414) {
415 return a/b - (a%b < 0);
416}
417/*****************************************************************************/
418
419/*****************************************************************************/
425 long int year
426) {
427 return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0);
428}
429/*****************************************************************************/
430
431/*****************************************************************************/
437 long int year1,
439 long int year2
440) {
441 long int leaps1, leaps2;
442
443 leaps1 = math_div(year1-1, 4) - math_div(year1-1, 100) + math_div(year1-1, 400);
444 leaps2 = math_div(year2-1, 4) - math_div(year2-1, 100) + math_div(year2-1, 400);
445 return(leaps2-leaps1);
446}
447/*****************************************************************************/
448
449/*****************************************************************************/
455 time_t totalsecs,
457 int offset,
459 struct tm *result
460) {
461 if(offset==0) {gmtime_r(&totalsecs, result); return;}
462
463
464 long int days, rem, y, yg;
465 const unsigned short *ip;
466
467 days=totalsecs/86400; rem=totalsecs%86400; rem+=offset;
468 while(rem<0) {rem+=86400; --days;}
469 while(rem>=86400) {rem-=86400; ++days;}
470 result->tm_hour=rem/3600;
471 rem%=3600; result->tm_min=rem/60;
472 result->tm_sec=rem%60;
473
474 /* January 1, 1970 was a Thursday. */
475 result->tm_wday=(4+days)%7;
476 if(result->tm_wday<0) result->tm_wday+=7;
477 y=1970;
478 while(days<0 || days>=(isleapyear(y)?366:365)) {
479 /* Guess a corrected year, assuming 365 days per year. */
480 yg=y+math_div(days, 365);
481 /* Adjust days and y to match the guessed year. */
482 days-=(yg-y)*365 + leaps_between(y, yg);
483 y=yg;
484 }
485 result->tm_year=y-1900; result->tm_yday=days;
486 ip=__mon_yday[isleapyear(y)];
487 for(y=11; days<ip[y]; y--) continue;
488 days-=ip[y];
489 result->tm_mon=y;
490 result->tm_mday=days+1;
491 result->tm_isdst=-1;
492#if defined(HAVE_TM_GMTOFF)
493 result->tm_gmtoff=0L;
494#endif
495}
496/*****************************************************************************/
497
498/*****************************************************************************/
504 struct tm *tm1,
506 struct tm *tm0
507) {
508 return(difftime(mktime(tm1), mktime(tm0)));
509}
510/*****************************************************************************/
511
512/*****************************************************************************/
514void tmAdd(
516 int s,
518 struct tm *d
519) {
520 if(d==NULL) return;
521 d->tm_sec+=s;
522 //mktime(d); // this automatically normalizes sec to hours etc if necessary
523 timegm(d); // this automatically normalizes sec to hours etc if necessary
524}
525/*****************************************************************************/
526
527/*****************************************************************************/
int get_datetime(char *str, struct tm *date, int verbose)
Definition datetime.c:322
char * ctime_r_int(const time_t *t, char *buf)
Convert calendard time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:110
int isdate2(char *str, char *intdate)
Definition datetime.c:168
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:69
void tmAdd(int s, struct tm *d)
Definition datetime.c:514
int isleapyear(long int year)
Definition datetime.c:423
int isdate(char *str)
Definition datetime.c:146
void time_to_tm(time_t totalsecs, int offset, struct tm *result)
Definition datetime.c:452
int istime(char *str)
Definition datetime.c:259
int get_date(char *str, struct tm *date)
Definition datetime.c:377
int isdate4(int dateint, int *year, int *month, int *day)
Definition datetime.c:230
long int math_div(long int a, long int b)
Definition datetime.c:409
int isdatetime(char *str, char *intdate)
Definition datetime.c:280
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:22
int isdate3(char *str, char *intdate)
Definition datetime.c:199
long int leaps_between(long int year1, long int year2)
Definition datetime.c:435
struct tm * localtime_r(const time_t *t, struct tm *tm)
Convert time_t to local time in struct tm.
Definition datetime.c:46
double tmDifference(struct tm *tm1, struct tm *tm0)
Definition datetime.c:502
Header file for libtpcmisc.