TPCCLIB
Loading...
Searching...
No Matches
datetime.c File Reference

Date and time functions. More...

#include "libtpcmisc.h"
#include <locale.h>
#include <unistd.h>
#include <time.h>

Go to the source code of this file.

Functions

struct tm * gmtime_r (const time_t *t, struct tm *tm)
 Convert time_t to GMT struct tm.
 
struct tm * localtime_r (const time_t *t, struct tm *tm)
 Convert time_t to local time in struct tm.
 
time_t timegm (struct tm *tm)
 Inverse of gmtime, converting struct tm to time_t.
 
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, with length of 19 characters and the null.
 
int isdate (char *str)
 
int isdate2 (char *str, char *intdate)
 
int isdate3 (char *str, char *intdate)
 
int isdate4 (int dateint, int *year, int *month, int *day)
 
int istime (char *str)
 
int isdatetime (char *str, char *intdate)
 
int get_datetime (char *str, struct tm *date, int verbose)
 
int get_date (char *str, struct tm *date)
 
long int math_div (long int a, long int b)
 
int isleapyear (long int year)
 
long int leaps_between (long int year1, long int year2)
 
void time_to_tm (time_t totalsecs, int offset, struct tm *result)
 
double tmDifference (struct tm *tm1, struct tm *tm0)
 
void tmAdd (int s, struct tm *d)
 

Detailed Description

Date and time functions.

Author
Vesa Oikonen
Todo
Use strptime function, when available, to convert string to struct tm.

Definition in file datetime.c.

Function Documentation

◆ ctime_r_int()

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, with length of 19 characters and the null.

This is a replacement of the thread-safe ctime_r function which converts to date and time in english format.

Author
Vesa Oikonen
Returns
Returns pointer to the string, or null in case of an error.
Parameters
tPointer to calendar time ; do not give pointer to int here, like &e7mhdr.scan_start_time
bufPointer to string where the date and time will be written. It must be pre-allocated for at least 20 characters.

Definition at line 110 of file datetime.c.

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}
struct tm * gmtime_r(const time_t *t, struct tm *tm)
Convert time_t to GMT struct tm.
Definition datetime.c:22

Referenced by atnMake(), ecat7MHeaderToIFT(), ecat7PrintMainheader(), fitWrite(), imgGetEcat63MHeader(), imgInfo(), imgSetEcat63MHeader(), imgWriteEcat63Frame(), imgWriteFrame(), plotdata(), resWrite(), resWriteHTML_table(), and sifPrint().

◆ get_date()

int get_date ( char * str,
struct tm * date )

Reads date from a standard string representation of date.

Returns
Returns 0 when successful, <>0 in case of an error.
Parameters
strPointer to string that contains date in one of the formats YYYY-MM-DD, DD/MM/YYYY, DD.MM.YYYY, DD/MM/YY, or DD.MM.YYYY. This string is not modified.
datePointer to allocated struct tm where the date is written

Definition at line 377 of file datetime.c.

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}
int isdate2(char *str, char *intdate)
Definition datetime.c:168
int isdate(char *str)
Definition datetime.c:146
int isdate3(char *str, char *intdate)
Definition datetime.c:199

Referenced by resRead().

◆ get_datetime()

int get_datetime ( char * str,
struct tm * date,
int verbose )

Reads time and date from a standard string representation of date and time.

Returns
Returns 0 when successful, <>0 in case of an error.
Parameters
strPointer to string that contains date and time in one of the formats YYYY-MM-DD hh:mm:ss, DD.MM.YYYY hh:mm:ss, or DD/MM/YY hh:mm:ss This string is not modified.
datePointer to allocated struct tm where date and time is written
verboseVerbose level; if <=0, then nothing is printed into stdout

Definition at line 322 of file datetime.c.

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}
time_t timegm(struct tm *tm)
Inverse of gmtime, converting struct tm to time_t.
Definition datetime.c:69
int isdatetime(char *str, char *intdate)
Definition datetime.c:280

Referenced by ecat7EditMHeader(), fitRead(), resRead(), and selectEcat931Calibrationfile().

◆ gmtime_r()

struct tm * gmtime_r ( const time_t * t,
struct tm * tm )

Convert time_t to GMT struct tm.

This version of gmtime_r function is here for systems (at least Windows) where it is not defined. Uses gmtime, which is threadsafe in Windows.

Returns
Pointer to struct tm, or null in case of an error.
Parameters
tPointer to time_t; do not give pointer to int here, like &e7mhdr.scan_start_time
tmPointer to struct tm, to be filled here

Definition at line 22 of file datetime.c.

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}

Referenced by ctime_r_int(), ecat63AddImg(), ecat63WriteAllImg(), ecat7EditMHeader(), ecat7ReadMainheader(), ecatCopy7to63mainheader(), imgSetAnalyzeHeader(), imgSetEcat63MHeader(), imgWriteAnalyze(), res2ift(), sifWrite(), time_to_tm(), and timegm().

◆ isdate()

int isdate ( char * str)

Check if specified string contains date in correct international format (YYYY-MM-DD). String must start with date, but any contents after it is ignored.

Returns
Returns 0 if date is in correct format, -1 if format is correct but date is invalid, and otherwise <>0.
Parameters
strString to be checked; not changed in this routine

Definition at line 146 of file datetime.c.

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}

Referenced by dcmDA2intl(), get_date(), and isdatetime().

◆ isdate2()

int isdate2 ( char * str,
char * intdate )

Check if specified string contains date in correct format (DD.MM.YYYY or DD/MM/YYYY). String must start with date, but any contents after it is ignored.

Returns
Returns 0 if date is in correct format, -1 if format is correct but date is invalid, and otherwise <>0.
Parameters
strString to be checked; not changed in this routine
intdatePointer to allocated string where date is written in international format; enter NULL, if not needed.

Definition at line 168 of file datetime.c.

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}

Referenced by get_date(), and isdatetime().

◆ isdate3()

int isdate3 ( char * str,
char * intdate )

Check if specified string contains date in correct format (DD.MM.YY or DD/MM/YY). String must start with date, but any contents after it is ignored.

Returns
Returns 0 if date is in correct format, -1 if format is correct but date is invalid, and otherwise <>0.
Parameters
strString to be checked; not changed in this routine
intdatePointer to allocated string where date is written in international format; enter NULL, if not needed.

Definition at line 199 of file datetime.c.

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}

Referenced by get_date(), and isdatetime().

◆ isdate4()

int isdate4 ( int dateint,
int * year,
int * month,
int * day )

Check if specified integer contains date in format YYYYMMDD.

Returns
Returns 0 if date is in correct format, -1 if format is correct but date is invalid, and otherwise <>0.
Parameters
dateintInteger to be checked; not changed in this routine
yearYear is written in this pointer; enter NULL if not needed
monthMonth is written in this pointer; enter NULL if not needed
dayDay is written in this pointer; enter NULL if not needed

Definition at line 230 of file datetime.c.

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}

Referenced by ecat7ReadMainheader().

◆ isdatetime()

int isdatetime ( char * str,
char * intdate )

Check if specified string contains date and time in correct format (YYYY-MM-DD hh:mm:ss, DD.MM.YYYY hh:mm:ss, or DD.MM.YY hh:mm:ss). String must start with date, but any contents after time is ignored.

Returns
Returns 0 if date and time are in correct format, <0 if format is correct but date or time is invalid, and otherwise <>0.
Parameters
strString to be checked; not changed in this routine
intdatePointer to allocated string where date and time is written in international format (YYYY-MM-DD hh:mm:ss); enter NULL, if not needed.

Definition at line 280 of file datetime.c.

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}
int istime(char *str)
Definition datetime.c:259

Referenced by dcmDT2intl(), and get_datetime().

◆ isleapyear()

int isleapyear ( long int year)

Check for leap year.

Returns
Nonzero if 'year' is a leap year.
Parameters
yearYear

Definition at line 423 of file datetime.c.

426 {
427 return (year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0);
428}

Referenced by time_to_tm().

◆ istime()

int istime ( char * str)

Check if specified string contains time in correct format (hh:mm:ss). String must start with time, but any contents after it is ignored.

Returns
Returns 0 if time is in correct format, -1 if format is correct but time is invalid, and otherwise <>0.
Parameters
strString to be checked; not changed in this routine

Definition at line 259 of file datetime.c.

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}

Referenced by dcmTM2intl(), iftRead(), and isdatetime().

◆ leaps_between()

long int leaps_between ( long int year1,
long int year2 )

Calculates the number of leap years between year1 and year2.

Returns
Nr of leap years.
Parameters
year1Year 1
year2Year 2

Definition at line 435 of file datetime.c.

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}
long int math_div(long int a, long int b)
Definition datetime.c:409

Referenced by time_to_tm().

◆ localtime_r()

struct tm * localtime_r ( const time_t * t,
struct tm * tm )

Convert time_t to local time in struct tm.

This version of localtime_r function is here for systems (at least Windows) where it is not defined. Uses localtime, which is threadsafe in Windows.

See also
gmtime_r
Returns
Pointer to struct tm, or null in case of an error.
Parameters
tPointer to time_t; do not give pointer to int here, like &e7mhdr.scan_start_time
tmPointer to struct tm, to be filled here

Definition at line 46 of file datetime.c.

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}

◆ math_div()

long int math_div ( long int a,
long int b )

Division for long integers.

Returns
a/b
Parameters
aA/b
ba/B

Definition at line 409 of file datetime.c.

414 {
415 return a/b - (a%b < 0);
416}

Referenced by leaps_between(), and time_to_tm().

◆ time_to_tm()

void time_to_tm ( time_t totalsecs,
int offset,
struct tm * result )

Convert calendar time to local broken-down time. This function is copied from GNU C Library with tiny modifications.

Parameters
totalsecsnumber of seconds elapsed since 00:00:00 on January 1, 1970, UTC; can be negative to represent times before 1970
offsetoffset seconds adding to totalsecs (e.g. -timezone)
resultpointer to struct tm variable to receive broken-down time

Definition at line 452 of file datetime.c.

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}
int isleapyear(long int year)
Definition datetime.c:423
long int leaps_between(long int year1, long int year2)
Definition datetime.c:435

◆ timegm()

time_t timegm ( struct tm * tm)

Inverse of gmtime, converting struct tm to time_t.

Otherwise same as mktime, except that mktime uses local time. Uses gmtime_r or gmtime_s, if available, otherwise gmtime, which is threadsafe in Windows.

Returns
Returns the time_t, or -1 in case of an error.
Parameters
tmPointer to struct tm

Definition at line 69 of file datetime.c.

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}

Referenced by ecat63Scanstarttime(), ecat63ScanstarttimeToTm(), ecat7EditMHeader(), fitRead(), get_datetime(), imgGetMicropetHeader(), resRead(), sifRead(), tmAdd(), and upetScanStart().

◆ tmAdd()

void tmAdd ( int s,
struct tm * d )

Add given time in seconds to the date and time.

Parameters
sTime to add in seconds; can be negative
dPointer to tm struct

Definition at line 514 of file datetime.c.

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}

◆ tmDifference()

double tmDifference ( struct tm * tm1,
struct tm * tm0 )

Calculate the difference in seconds between two given dates and times.

Returns
Returns tm1-tm0 in seconds.
Parameters
tm1Pointer to tm struct
tm0Pointer to tm struct

Definition at line 502 of file datetime.c.

507 {
508 return(difftime(mktime(tm1), mktime(tm0)));
509}

Referenced by selectEcat931Calibrationfile().