TPCCLIB
Loading...
Searching...
No Matches
datetime.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "tpcclibConfig.h"
7/*****************************************************************************/
8#include <stdio.h>
9#include <stdlib.h>
10#include <time.h>
11#include <string.h>
12#include <locale.h>
13#include <ctype.h>
14#include <unistd.h>
15#include <math.h>
16/*****************************************************************************/
17
18/*****************************************************************************/
19#include "tpcextensions.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23#ifndef HAVE_GMTIME_R
31struct tm* gmtime_r(
33 const time_t *t,
35 struct tm *tm
36) {
37 struct tm *ltm=gmtime(t);
38 if(ltm==NULL || tm==NULL) return(NULL);
39 *tm=*ltm; tm->tm_isdst=-1;
40 return tm;
41}
42#endif // HAVE_GMTIME_R
43/*****************************************************************************/
44
45/*****************************************************************************/
46#ifndef HAVE_LOCALTIME_R
54struct tm* localtime_r(
56 const time_t *t,
58 struct tm *tm
59) {
60 struct tm *ltm=localtime(t);
61 if(ltm==NULL || tm==NULL) return(NULL);
62 *tm=*ltm; tm->tm_isdst=-1;
63 return tm;
64}
65#endif // HAVE_LOCALTIME_R
66/*****************************************************************************/
67
68/*****************************************************************************/
69#ifndef HAVE_TIMEGM
77time_t timegm(
79 struct tm *tm
80) {
81#ifdef HAVE_GMTIME_R
82 {
83 time_t temp_lt;
84 struct tm temp_gm;
85 if(!tm) temp_lt=0; else temp_lt=mktime(tm);
86 if(gmtime_r(&temp_lt, &temp_gm)==NULL) return((time_t)-1);
87 return(time_t)(temp_lt + (temp_lt - mktime(&temp_gm)));
88 }
89#endif
90
91#ifdef HAVE_GMTIME_S
92 {
93 time_t temp_lt;
94 struct tm temp_gm;
95 if(!tm) temp_lt=0; else temp_lt=mktime(tm);
96 if(gmtime_s(&temp_gm, &temp_lt)!=0) return(time_t)-1);
97 return(time_t)(temp_lt + (temp_lt - mktime(&temp_gm)));
98 }
99#endif
100
101 time_t temp_lt;
102 struct tm *temp_gm;
103 if(!tm) temp_lt=0; else {tm->tm_isdst=-1; temp_lt=mktime(tm);}
104 temp_gm=gmtime(&temp_lt); if(temp_gm) temp_gm->tm_isdst=-1;
105 return(time_t)(temp_lt + (temp_lt - mktime(temp_gm)));
106}
107#endif // HAVE_TIMEGM
108/*****************************************************************************/
109
110/*****************************************************************************/
121 const time_t *t,
124 char *buf
125) {
126 if(buf==NULL) return(NULL);
127 buf[0]=(char)0;
128 struct tm tm;
129 if(!gmtime_r(t, &tm)) return(NULL);
130 if(!strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &tm)) return(NULL);
131 return(buf);
132}
133/*****************************************************************************/
134
135/*****************************************************************************/
137
138static const unsigned short __mon_yday[2][13] = {
140 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
142 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
143};
145/*****************************************************************************/
146
147/*****************************************************************************/
157 const char *str
158) {
159 if(str==NULL || strnlen(str, 10)<10) return 1;
160 if(str[4]!='-' || str[7]!='-') return 2;
161 if(strncasecmp(str, "YYYY-MM-DD", 10)==0) return -1;
162 int Y, M, D, n;
163 n=sscanf(str, "%4d-%2d-%2d", &Y, &M, &D); if(n!=3) return 3;
164 if(M>12 || D>31) return -1;
165 if(Y<0 || M<1 || D<1) return -1;
166 return 0;
167}
168/*****************************************************************************/
169
170/*****************************************************************************/
181 const char *str,
184 char *intdate
185) {
186 if(str==NULL || strnlen(str, 10)<8) return 1;
187 int n; char *cptr;
188 cptr=(char*)str; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
189 cptr+=n+1; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
190 cptr+=n+1; n=strcspn(cptr, "./- \t\n\r"); if(n!=4) return 2;
191 if(strncasecmp(str, "DD.MM.YYYY", 10)==0 || strncasecmp(str, "DD/MM/YYYY", 10)==0) {
192 return -1;
193 }
194 int Y, M, D;
195 n=sscanf(str, "%d/%d/%4d", &D, &M, &Y);
196 if(n<3) n=sscanf(str, "%d.%d.%4d", &D, &M, &Y);
197 if(n!=3) return 3;
198 if(M>12 || D>31) return -1;
199 if(Y<0 || M<1 || D<1) return -1;
200 if(intdate!=NULL) sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
201 return 0;
202}
203/*****************************************************************************/
204
205/*****************************************************************************/
216 const char *str,
219 char *intdate
220) {
221 if(str==NULL || strnlen(str, 8)<6) return 1;
222 int n; char *cptr;
223 cptr=(char*)str; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
224 cptr+=n+1; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
225 cptr+=n+1; n=strcspn(cptr, "./- \t\n\r"); if(n!=2) return 2;
226 if(strncasecmp(str, "DD.MM.YY", 8)==0 || strncasecmp(str, "DD/MM/YY", 8)==0) {
227 return -1;
228 }
229 int Y, M, D;
230 n=sscanf(str, "%d/%d/%2d", &D, &M, &Y);
231 if(n<3) n=sscanf(str, "%d.%d.%2d", &D, &M, &Y);
232 if(n!=3) return 3;
233 if(Y>99 || M>12 || D>31) return -1;
234 if(Y<0 || M<1 || D<1) return -1;
235 if(intdate!=NULL) {
236 if(Y>=70) Y+=1900; else Y+=2000;
237 sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
238 }
239 return 0;
240}
241/*****************************************************************************/
242
243/*****************************************************************************/
252 int dateint,
255 char *intdate,
257 int *year,
259 int *month,
261 int *day
262) {
263 if(dateint<18000101 || dateint>99991231) return 1;
264 int Y, M, D, n;
265 n=dateint/100; D=dateint-100*n; Y=n/100; M=n-100*Y;
266 if(M>12 || D>31) return -1;
267 if(Y<1 || M<1 || D<1) return -1;
268 if(year!=NULL) *year=Y;
269 if(month!=NULL) *month=M;
270 if(day!=NULL) *day=D;
271 if(intdate!=NULL) {sprintf(intdate, "%04d-%02d-%02d", Y, M, D);}
272 return 0;
273}
274/*****************************************************************************/
275
276/*****************************************************************************/
286 const char *str
287) {
288 if(str==NULL || strnlen(str, 8)<8) return 1;
289 if(str[2]!=':' || str[5]!=':') return 2;
290 if(strncasecmp(str, "hh:mm:ss", 8)==0) return -1;
291 int h, m, s, n;
292 n=sscanf(str, "%d:%d:%d", &h, &m, &s); if(n!=3) return 3;
293 if(h<0 || h>23 || m<0 || m>59 || s<0 || s>59) return -1;
294 return 0;
295}
296/*****************************************************************************/
297
298/*****************************************************************************/
310 const char *str,
314 char *intdate
315) {
316 int ret1, ret2, len;
317 char correct_date[20], *time_ptr=NULL, tmp[20];
318
319 if(str==NULL) return 1;
320 // 1/1/70 00:00:00 or 1970-01-01 00:00:00
321 if(strnlen(str, 19)<15) return 1;
322 /* Separate date and time */
323 len=strcspn(str, " \t");
324 if(len<6 || len>10) return 1;
325 strlcpy(tmp, str, len+1); time_ptr=(char*)str+len+1;
326 /* and check the date */
327 correct_date[0]=(char)0;
328 if((ret1=strDateValid(tmp))<=0) {strlcpy(correct_date, tmp, 20);}
329 else if((ret1=strDateValid2(tmp, correct_date))<=0) {}
330 else if((ret1=strDateValid3(tmp, correct_date))<=0) {}
331 else {return 2;}
332
333 /* the check the time */
334 ret2=strTimeValid(time_ptr);
335 if(ret1>0) {if(ret2>=0) return(100*ret1+ret2); else return(100*ret2);}
336 if(ret2>0) return(10*ret2);
337 if(ret1<0) {if(ret2<0) return(-3); else return(-1);}
338 if(ret2<0) return(-2);
339 if(intdate!=NULL) sprintf(intdate, "%10.10s %8.8s", correct_date, time_ptr);
340 return 0;
341}
342/*****************************************************************************/
343
344/*****************************************************************************/
353 const char *str,
356 struct tm *date
357) {
358 char buf[32];
359 int ret, n, YYYY=0, MM=0, DD=0, hh=0, mm=0, ss=0;
360
361 ret=strDateTimeValid(str, buf); if(ret!=0) return(ret);
362 n=sscanf(buf, "%d-%d-%d %d:%d:%d", &YYYY, &MM, &DD, &hh, &mm, &ss);
363 if(n!=6) return(40);
364 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
365 date->tm_hour=hh; date->tm_min=mm; date->tm_sec=ss; date->tm_isdst=-1;
366 ret=strftime(buf, 32, "%Y-%m-%d %H:%M:%S", date);
367 if(ret==0) return(50);
368 return(0);
369}
370/*****************************************************************************/
371
372/*****************************************************************************/
381 const char *str,
384 struct tm *date
385) {
386 char buf[32];
387 int ret, n, YYYY=0, MM=0, DD=0;
388
389 if(strnlen(str, 10)<8) return 1;
390 if((ret=strDateValid(str))<=0) {
391 strlcpy(buf, str, 11);
392 } else {
393 ret=strDateValid2(str, buf);
394 if(ret>0) ret=strDateValid3(str, buf);
395 }
396 if(ret>0) return 2;
397 n=sscanf(buf, "%d-%d-%d", &YYYY, &MM, &DD);
398 if(n!=3) return(3);
399 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
400 date->tm_hour=0; date->tm_min=0; date->tm_sec=0; date->tm_isdst=-1;
401 ret=strftime(buf, 32, "%Y-%m-%d %H:%M:%S", date);
402 if(ret==0) return(4);
403 return(0);
404}
405/*****************************************************************************/
406
407/*****************************************************************************/
409
410long int math_div(long int a, long int b)
411{
412 return a/b - (a%b < 0);
413}
414/*****************************************************************************/
415
416/*****************************************************************************/
418int isleapyear(long year)
419{
420 return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0);
421}
422/*****************************************************************************/
423
424/*****************************************************************************/
426long int leaps_between(long int year1, long int year2)
427{
428 long int leaps1, leaps2;
429
430 leaps1=math_div(year1-1, 4) - math_div(year1-1, 100) + math_div(year1-1, 400);
431 leaps2=math_div(year2-1, 4) - math_div(year2-1, 100) + math_div(year2-1, 400);
432 return(leaps2-leaps1);
433}
434/*****************************************************************************/
435
436/*****************************************************************************/
438
446 time_t totalsecs,
448 int offset,
450 struct tm *result
451) {
452 long int days, rem, y, yg;
453 const unsigned short *ip;
454
455 days=totalsecs/86400; rem=totalsecs%86400; rem+=offset;
456 while(rem<0) {rem+=86400; --days;}
457 while(rem>=86400) {rem-=86400; ++days;}
458 result->tm_hour=rem/3600;
459 rem%=3600; result->tm_min=rem/60;
460 result->tm_sec=rem%60;
461
462 /* January 1, 1970 was a Thursday. */
463 result->tm_wday=(4+days)%7;
464 if(result->tm_wday<0) result->tm_wday+=7;
465 y=1970;
466 while(days<0 || days>=(isleapyear(y)?366:365)) {
467 /* Guess a corrected year, assuming 365 days per year. */
468 yg=y+math_div(days, 365);
469 /* Adjust days and y to match the guessed year. */
470 days-=(yg-y)*365 + leaps_between(y, yg);
471 y=yg;
472 }
473 result->tm_year=y-1900; result->tm_yday=days;
474 ip=__mon_yday[isleapyear(y)];
475 for(y=11; days<ip[y]; y--) continue;
476 days-=ip[y]; result->tm_mon=y; result->tm_mday=days+1;
477 result->tm_isdst=-1;
478}
479/*****************************************************************************/
480
481/*****************************************************************************/
488 struct tm *tm1,
490 struct tm *tm0
491) {
492 return(difftime(mktime(tm1), mktime(tm0)));
493}
494/*****************************************************************************/
495
496/*****************************************************************************/
500void tmAdd(
502 int s,
504 struct tm *d
505) {
506 if(d==NULL) return;
507 d->tm_sec+=s;
508 //mktime(d); // this automatically normalizes sec to hours etc if necessary
509 timegm(d); // this automatically normalizes sec to hours etc if necessary
510}
511/*****************************************************************************/
512
513/*****************************************************************************/
521 const char *dt1,
523 const char *dt0
524) {
525 if(dt1==NULL || dt0==NULL) return(0.0);
526 struct tm tm1, tm0;
527 if(strDateTimeRead(dt1, &tm1) || strDateTimeRead(dt0, &tm0)) return(0.0);
528 return(tmDifference(&tm1, &tm0));
529}
530/*****************************************************************************/
531
532/*****************************************************************************/
539 int s,
542 char *dt
543) {
544 if(dt==NULL) return(1);
545 struct tm tm0;
546 if(strDateTimeRead(dt, &tm0)) return(1);
547 if(s==0) return(0);
548 tmAdd(s, &tm0);
549 if(!strftime(dt, 20, "%Y-%m-%d %H:%M:%S", &tm0)) return(2);
550 return(0);
551}
552/*****************************************************************************/
553
554/*****************************************************************************/
int strDateValid3(const char *str, char *intdate)
Definition datetime.c:214
char * ctime_r_int(const time_t *t, char *buf)
Convert calendar time t into a null-terminated string of the form YYYY-MM-DD hh:mm:ss,...
Definition datetime.c:119
int strDateValid(const char *str)
Definition datetime.c:155
int strDateTimeRead(const char *str, struct tm *date)
Definition datetime.c:350
int strDateRead(const char *str, struct tm *date)
Definition datetime.c:378
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:77
double strDateTimeDifference(const char *dt1, const char *dt0)
Definition datetime.c:519
void tmAdd(int s, struct tm *d)
Definition datetime.c:500
int strTimeValid(const char *str)
Definition datetime.c:284
void time_to_tm(time_t totalsecs, int offset, struct tm *result)
Definition datetime.c:443
int strDateValid2(const char *str, char *intdate)
Definition datetime.c:179
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:31
int strDateTimeValid(const char *str, char *intdate)
Definition datetime.c:308
int strDateValid4(int dateint, char *intdate, int *year, int *month, int *day)
Definition datetime.c:250
int strDateTimeAdd(int s, char *dt)
Definition datetime.c:537
struct tm * localtime_r(const time_t *t, struct tm *tm)
Convert time_t to local time in struct tm.
Definition datetime.c:54
double tmDifference(struct tm *tm1, struct tm *tm0)
Definition datetime.c:486
size_t strnlen(const char *s, size_t n)
Definition stringext.c:566
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
Header file for library libtpcextensions.