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
53struct tm* localtime_r(
55 const time_t *t,
57 struct tm *tm
58) {
59 struct tm *ltm=localtime(t);
60 if(ltm==NULL || tm==NULL) return(NULL);
61 *tm=*ltm; tm->tm_isdst=-1;
62 return tm;
63}
64#endif // HAVE_LOCALTIME_R
65/*****************************************************************************/
66
67/*****************************************************************************/
68#ifndef HAVE_TIMEGM
76time_t timegm(
78 struct tm *tm
79) {
80#if defined HAVE_GMTIME_R
81 {
82 time_t temp_lt;
83 struct tm temp_gm;
84 if(!tm) temp_lt=0; else temp_lt=mktime(tm);
85 if(gmtime_r(&temp_lt, &temp_gm)==NULL) return((time_t)-1);
86 return(time_t)(temp_lt + (temp_lt - mktime(&temp_gm)));
87 }
88#else
89 time_t temp_lt;
90 struct tm *temp_gm;
91 if(!tm) temp_lt=0; else {tm->tm_isdst=-1; temp_lt=mktime(tm);}
92 temp_gm=gmtime(&temp_lt); if(temp_gm) temp_gm->tm_isdst=-1;
93 return(time_t)(temp_lt + (temp_lt - mktime(temp_gm)));
94#endif
95}
96#endif // HAVE_TIMEGM
97/*****************************************************************************/
98
99/*****************************************************************************/
110 const time_t *t,
113 char *buf
114) {
115 if(buf==NULL) return(NULL);
116 buf[0]=(char)0;
117 struct tm tm;
118 if(!gmtime_r(t, &tm)) return(NULL);
119 if(!strftime(buf, 20, "%Y-%m-%d %H:%M:%S", &tm)) return(NULL);
120 return(buf);
121}
122/*****************************************************************************/
123
124/*****************************************************************************/
126
127static const unsigned short __mon_yday[2][13] = {
129 {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
131 {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
132};
134/*****************************************************************************/
135
136/*****************************************************************************/
146 const char *str
147) {
148 if(str==NULL || strnlen(str, 10)<10) return 1;
149 if(str[4]!='-' || str[7]!='-') return 2;
150 if(strncasecmp(str, "YYYY-MM-DD", 10)==0) return -1;
151 int Y, M, D, n;
152 n=sscanf(str, "%4d-%2d-%2d", &Y, &M, &D); if(n!=3) return 3;
153 if(M>12 || D>31) return -1;
154 if(Y<0 || M<1 || D<1) return -1;
155 return 0;
156}
157/*****************************************************************************/
158
159/*****************************************************************************/
170 const char *str,
173 char *intdate
174) {
175 if(str==NULL || strnlen(str, 10)<8) return 1;
176 int n; char *cptr;
177 cptr=(char*)str; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
178 cptr+=n+1; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
179 cptr+=n+1; n=strcspn(cptr, "./- \t\n\r"); if(n!=4) return 2;
180 if(strncasecmp(str, "DD.MM.YYYY", 10)==0 || strncasecmp(str, "DD/MM/YYYY", 10)==0) {
181 return -1;
182 }
183 int Y, M, D;
184 n=sscanf(str, "%d/%d/%4d", &D, &M, &Y);
185 if(n<3) n=sscanf(str, "%d.%d.%4d", &D, &M, &Y);
186 if(n!=3) return 3;
187 if(M>12 || D>31) return -1;
188 if(Y<0 || M<1 || D<1) return -1;
189 if(intdate!=NULL) sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
190 return 0;
191}
192/*****************************************************************************/
193
194/*****************************************************************************/
205 const char *str,
208 char *intdate
209) {
210 if(str==NULL || strnlen(str, 8)<6) return 1;
211 int n; char *cptr;
212 cptr=(char*)str; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
213 cptr+=n+1; n=strcspn(cptr, "./"); if(n<1 || n>2) return 2;
214 cptr+=n+1; n=strcspn(cptr, "./- \t\n\r"); if(n!=2) return 2;
215 if(strncasecmp(str, "DD.MM.YY", 8)==0 || strncasecmp(str, "DD/MM/YY", 8)==0) {
216 return -1;
217 }
218 int Y, M, D;
219 n=sscanf(str, "%d/%d/%2d", &D, &M, &Y);
220 if(n<3) n=sscanf(str, "%d.%d.%2d", &D, &M, &Y);
221 if(n!=3) return 3;
222 if(Y>99 || M>12 || D>31) return -1;
223 if(Y<0 || M<1 || D<1) return -1;
224 if(intdate!=NULL) {
225 if(Y>=70) Y+=1900; else Y+=2000;
226 sprintf(intdate, "%04d-%02d-%02d", Y, M, D);
227 }
228 return 0;
229}
230/*****************************************************************************/
231
232/*****************************************************************************/
241 int dateint,
244 char *intdate,
246 int *year,
248 int *month,
250 int *day
251) {
252 if(dateint<18000101 || dateint>99991231) return 1;
253 int Y, M, D, n;
254 n=dateint/100; D=dateint-100*n; Y=n/100; M=n-100*Y;
255 if(M>12 || D>31) return -1;
256 if(Y<1 || M<1 || D<1) return -1;
257 if(year!=NULL) *year=Y;
258 if(month!=NULL) *month=M;
259 if(day!=NULL) *day=D;
260 if(intdate!=NULL) {sprintf(intdate, "%04d-%02d-%02d", Y, M, D);}
261 return 0;
262}
263/*****************************************************************************/
264
265/*****************************************************************************/
275 const char *str
276) {
277 if(str==NULL || strnlen(str, 8)<8) return 1;
278 if(str[2]!=':' || str[5]!=':') return 2;
279 if(strncasecmp(str, "hh:mm:ss", 8)==0) return -1;
280 int h, m, s, n;
281 n=sscanf(str, "%d:%d:%d", &h, &m, &s); if(n!=3) return 3;
282 if(h<0 || h>23 || m<0 || m>59 || s<0 || s>59) return -1;
283 return 0;
284}
285/*****************************************************************************/
286
287/*****************************************************************************/
299 const char *str,
303 char *intdate
304) {
305 int ret1, ret2, len;
306 char correct_date[20], *time_ptr=NULL, tmp[20];
307
308 if(str==NULL) return 1;
309 // 1/1/70 00:00:00 or 1970-01-01 00:00:00
310 if(strnlen(str, 19)<15) return 1;
311 /* Separate date and time */
312 len=strcspn(str, " \t");
313 if(len<6 || len>10) return 1;
314 strlcpy(tmp, str, len+1); time_ptr=(char*)str+len+1;
315 /* and check the date */
316 correct_date[0]=(char)0;
317 if((ret1=strDateValid(tmp))<=0) {strlcpy(correct_date, tmp, 20);}
318 else if((ret1=strDateValid2(tmp, correct_date))<=0) {}
319 else if((ret1=strDateValid3(tmp, correct_date))<=0) {}
320 else {return 2;}
321
322 /* the check the time */
323 ret2=strTimeValid(time_ptr);
324 if(ret1>0) {if(ret2>=0) return(100*ret1+ret2); else return(100*ret2);}
325 if(ret2>0) return(10*ret2);
326 if(ret1<0) {if(ret2<0) return(-3); else return(-1);}
327 if(ret2<0) return(-2);
328 if(intdate!=NULL) sprintf(intdate, "%10.10s %8.8s", correct_date, time_ptr);
329 return 0;
330}
331/*****************************************************************************/
332
333/*****************************************************************************/
342 const char *str,
345 struct tm *date
346) {
347 char buf[32];
348 int ret, n, YYYY=0, MM=0, DD=0, hh=0, mm=0, ss=0;
349
350 ret=strDateTimeValid(str, buf); if(ret!=0) return(ret);
351 n=sscanf(buf, "%d-%d-%d %d:%d:%d", &YYYY, &MM, &DD, &hh, &mm, &ss);
352 if(n!=6) return(40);
353 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
354 date->tm_hour=hh; date->tm_min=mm; date->tm_sec=ss; date->tm_isdst=-1;
355#ifdef HAVE_TM_GMTOFF
356 date->tm_gmtoff=0L;
357#endif
358 ret=strftime(buf, 32, "%Y-%m-%d %H:%M:%S", date);
359 if(ret==0) return(50);
360 return(0);
361}
362/*****************************************************************************/
363
364/*****************************************************************************/
373 const char *str,
376 struct tm *date
377) {
378 char buf[32];
379 int ret, n, YYYY=0, MM=0, DD=0;
380
381 if(strnlen(str, 10)<8) return 1;
382 if((ret=strDateValid(str))<=0) {
383 strlcpy(buf, str, 11);
384 } else {
385 ret=strDateValid2(str, buf);
386 if(ret>0) ret=strDateValid3(str, buf);
387 }
388 if(ret>0) return 2;
389 n=sscanf(buf, "%d-%d-%d", &YYYY, &MM, &DD);
390 if(n!=3) return(3);
391 date->tm_year=YYYY-1900; date->tm_mday=DD; date->tm_mon=MM-1;
392 date->tm_hour=0; date->tm_min=0; date->tm_sec=0; date->tm_isdst=-1;
393 ret=strftime(buf, 32, "%Y-%m-%d %H:%M:%S", date);
394 if(ret==0) return(4);
395 return(0);
396}
397/*****************************************************************************/
398
399/*****************************************************************************/
401
402long int math_div(long int a, long int b)
403{
404 return a/b - (a%b < 0);
405}
406/*****************************************************************************/
407
408/*****************************************************************************/
410int isleapyear(long year)
411{
412 return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0);
413}
414/*****************************************************************************/
415
416/*****************************************************************************/
418long int leaps_between(long int year1, long int year2)
419{
420 long int leaps1, leaps2;
421
422 leaps1=math_div(year1-1, 4) - math_div(year1-1, 100) + math_div(year1-1, 400);
423 leaps2=math_div(year2-1, 4) - math_div(year2-1, 100) + math_div(year2-1, 400);
424 return(leaps2-leaps1);
425}
426/*****************************************************************************/
427
428/*****************************************************************************/
430
438 time_t totalsecs,
440 int offset,
442 struct tm *result
443) {
444 long int days, rem, y, yg;
445 const unsigned short *ip;
446
447 days=totalsecs/86400; rem=totalsecs%86400; rem+=offset;
448 while(rem<0) {rem+=86400; --days;}
449 while(rem>=86400) {rem-=86400; ++days;}
450 result->tm_hour=rem/3600;
451 rem%=3600; result->tm_min=rem/60;
452 result->tm_sec=rem%60;
453
454 /* January 1, 1970 was a Thursday. */
455 result->tm_wday=(4+days)%7;
456 if(result->tm_wday<0) result->tm_wday+=7;
457 y=1970;
458 while(days<0 || days>=(isleapyear(y)?366:365)) {
459 /* Guess a corrected year, assuming 365 days per year. */
460 yg=y+math_div(days, 365);
461 /* Adjust days and y to match the guessed year. */
462 days-=(yg-y)*365 + leaps_between(y, yg);
463 y=yg;
464 }
465 result->tm_year=y-1900; result->tm_yday=days;
466 ip=__mon_yday[isleapyear(y)];
467 for(y=11; days<ip[y]; y--) continue;
468 days-=ip[y]; result->tm_mon=y; result->tm_mday=days+1;
469 result->tm_isdst=-1;
470}
471/*****************************************************************************/
472
473/*****************************************************************************/
480 struct tm *tm1,
482 struct tm *tm0
483) {
484 return(difftime(mktime(tm1), mktime(tm0)));
485}
486/*****************************************************************************/
487
488/*****************************************************************************/
492void tmAdd(
494 int s,
496 struct tm *d
497) {
498 if(d==NULL) return;
499 d->tm_sec+=s;
500 //mktime(d); // this automatically normalizes sec to hours etc if necessary
501 timegm(d); // this automatically normalizes sec to hours etc if necessary
502}
503/*****************************************************************************/
504
505/*****************************************************************************/
513 const char *dt1,
515 const char *dt0
516) {
517 if(dt1==NULL || dt0==NULL) return(0.0);
518 struct tm tm1, tm0;
519 if(strDateTimeRead(dt1, &tm1) || strDateTimeRead(dt0, &tm0)) return(0.0);
520 return(tmDifference(&tm1, &tm0));
521}
522/*****************************************************************************/
523
524/*****************************************************************************/
531 int s,
534 char *dt
535) {
536 if(dt==NULL) return(1);
537 struct tm tm0;
538 if(strDateTimeRead(dt, &tm0)) return(1);
539 if(s==0) return(0);
540 tmAdd(s, &tm0);
541 if(!strftime(dt, 20, "%Y-%m-%d %H:%M:%S", &tm0)) return(2);
542 return(0);
543}
544/*****************************************************************************/
545
546/*****************************************************************************/
552 struct timespec const *ts2,
554 struct timespec const *ts1
555) {
556 if(ts1==NULL || ts2==NULL) return(nan(""));
557 if(ts2->tv_sec < ts1->tv_sec)
558 return(-timespecDifference(ts1, ts2));
559 else
560 return((double)(ts2->tv_sec - ts1->tv_sec) + (ts2->tv_nsec - ts1->tv_nsec)*1E-09);
561}
562/*****************************************************************************/
563
564/*****************************************************************************/
double timespecDifference(struct timespec const *ts2, struct timespec const *ts1)
Definition datetime.c:550
int strDateValid3(const char *str, char *intdate)
Definition datetime.c:203
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:108
int strDateValid(const char *str)
Definition datetime.c:144
int strDateTimeRead(const char *str, struct tm *date)
Definition datetime.c:339
int strDateRead(const char *str, struct tm *date)
Definition datetime.c:370
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:76
double strDateTimeDifference(const char *dt1, const char *dt0)
Definition datetime.c:511
void tmAdd(int s, struct tm *d)
Definition datetime.c:492
int strTimeValid(const char *str)
Definition datetime.c:273
void time_to_tm(time_t totalsecs, int offset, struct tm *result)
Definition datetime.c:435
int strDateValid2(const char *str, char *intdate)
Definition datetime.c:168
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:297
int strDateValid4(int dateint, char *intdate, int *year, int *month, int *day)
Definition datetime.c:239
int strDateTimeAdd(int s, char *dt)
Definition datetime.c:529
struct tm * localtime_r(const time_t *t, struct tm *tm)
Convert time_t to local time in struct tm.
Definition datetime.c:53
double tmDifference(struct tm *tm1, struct tm *tm0)
Definition datetime.c:478
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:635
Header file for library libtpcextensions.