You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

686 lines
22 KiB

/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
// DJB's libtai was modified for the tai code
#include "OS_portable.h"
#define DISABLE_LEAPS
#define TAI_PACK 8
#define TAI_UTC_DIFF ((uint64_t)4611686018427387914ULL)
//#define UTC_ADJUST -36
#define tai_approx(t) ((double) ((t)->x))
#define tai_less(t,u) ((t)->x < (u)->x)
int32_t leapsecs_sub(struct tai *);
static struct tai First_TAI;
uint32_t First_utc;
int32_t UTC_ADJUST;
#ifdef _WIN32
struct tm *gmtime_r(const time_t *timep,struct tm *result)
{
struct tm *p = gmtime(timep);
memset(result,0,sizeof(*result));
if ( p != 0 )
{
*result = *p;
p = result;
}
return(p);
}
struct tm *_gmtime32(const time_t *timep,struct tm *result) { return(gmtime_r(timep,result)); }
time_t _time32(struct tm *tm) { return(time(NULL)); }
time_t _localtime32(struct tm *tm) { return(time(NULL)); }
#include <windows.h>
#include <stdint.h> // portable: uint64_t MSVC: __int64
// MSVC defines this in winsock2.h!?
/*typedef struct timeval {
long tv_sec;
long tv_usec;
} timeval;
int gettimeofday(struct timeval * tp, struct timezone * tzp)
{
// Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's
static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL);
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t time;
GetSystemTime( &system_time );
SystemTimeToFileTime( &system_time, &file_time );
time = ((uint64_t)file_time.dwLowDateTime ) ;
time += ((uint64_t)file_time.dwHighDateTime) << 32;
tp->tv_sec = (long) ((time - EPOCH) / 10000000L);
tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
return 0;
}*/
#endif
double OS_portable_milliseconds()
{
struct timeval tv; double millis;
gettimeofday(&tv,NULL);
millis = ((double)tv.tv_sec * 1000. + (double)tv.tv_usec / 1000.);
//printf("tv_sec.%ld usec.%d %f\n",tv.tv_sec,tv.tv_usec,millis);
return(millis);
}
// portable time functions
int32_t is_DST(int32_t datenum)
{
int32_t year,month,day;
year = datenum / 10000, month = (datenum / 100) % 100, day = (datenum % 100);
if ( month >= 4 && month <= 9 )
return(1);
else if ( month == 3 && day >= 29 )
return(1);
else if ( month == 10 && day < 25 )
return(1);
return(0);
}
struct taidate taidate_set(int32_t year,int32_t month,int32_t day)
{
struct taidate cd;
memset(&cd,0,sizeof(cd));
cd.year = year, cd.month = month, cd.day = day;
return(cd);
}
struct taidate taidate_frommjd(int32_t day,int32_t *pwday,int32_t *pyday)
{
int32_t year,month,yday; struct taidate cd;
year = day / 146097L;
day %= 146097L;
day += 678881L;
while (day >= 146097L) { day -= 146097L; ++year; }
// year * 146097 + day - 678881 is MJD; 0 <= day < 146097
// 2000-03-01, MJD 51604, is year 5, day 0
if ( pwday != 0 )
*pwday = (day + 3) % 7;
year *= 4;
if (day == 146096L) { year += 3; day = 36524L; }
else { year += day / 36524L; day %= 36524L; }
year *= 25;
year += day / 1461;
day %= 1461;
year *= 4;
yday = (day < 306);
if (day == 1460) { year += 3; day = 365; }
else { year += day / 365; day %= 365; }
yday += day;
day *= 10;
month = (day + 5) / 306;
day = (day + 5) % 306;
day /= 10;
if (month >= 10) { yday -= 306; ++year; month -= 10; }
else { yday += 59; month += 2; }
cd.year = year;
cd.month = month + 1;
cd.day = day + 1;
if ( pyday != 0 )
*pyday = yday;
return(cd);
}
struct taitime tai2time(struct tai t,int32_t *pwday,int32_t *pyday)
{
uint64_t u; int32_t leap,s; struct taitime ct;
memset(&ct,0,sizeof(ct));
ct.millis = fmod(t.millis,999.999999);
//if ( First_TAI.x != 0 && t.x > First_TAI.x )
// t.x = (t.millis / 1000.) + First_TAI.x;
leap = leapsecs_sub(&t);
u = t.x;
u += 58486; // was off by a minute (or 3?)
s = u % 86400ULL;
ct.second = (s % 60) + leap; s /= 60;
ct.minute = s % 60; s /= 60;
ct.hour = s;
u /= 86400ULL;
ct.date = taidate_frommjd((int32_t)(u - 53375995543064ULL),pwday,pyday);
ct.offset = 0;
// printf("origt.x %llu t.x %llu %3.3f -> %02d:%02d:%02d %3.3f\n",(long long)origt.x,(long long)t.x,t.millis,ct.second,ct.minute,ct.second,ct.millis);
//printf("TAI millis: %lld -1st.%lld %f - %f -> %f | %f\n",(long long)t.x,(long long)First_TAI.x,t.millis,First_TAI.millis,t.millis-First_TAI.millis,ct.millis);
return(ct);
}
struct taidate tai2date(struct tai t)
{
struct taitime ct = tai2time(t,0,0);
return(ct.date);
}
struct taitime taitime_set(struct taidate cd,int32_t hour,int32_t minute,int32_t seconds)
{
struct taitime ct;
memset(&ct,0,sizeof(ct));
ct.date = cd;
ct.hour = hour, ct.minute = minute, ct.second = seconds;
return(ct);
}
/*int32_t taitime_scan(char *s,struct taitime *ct)
{
int32_t z,c,sign; char *t = s;
t += taidate_scan(t,&ct->date);
while ((*t == ' ') || (*t == '\t') || (*t == 'T')) ++t;
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
ct->hour = z;
if (*t++ != ':') return 0;
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
ct->minute = z;
if (*t != ':')
ct->second = 0;
else
{
++t;
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
ct->second = z;
}
while ((*t == ' ') || (*t == '\t')) ++t;
if (*t == '+') sign = 1; else if (*t == '-') sign = -1; else return 0;
++t;
c = (uint8_t) (*t++ - '0'); if (c > 9) return 0; z = c;
c = (uint8_t) (*t++ - '0'); if (c > 9) return 0; z = z * 10 + c;
c = (uint8_t) (*t++ - '0'); if (c > 9) return 0; z = z * 6 + c;
c = (uint8_t) (*t++ - '0'); if (c > 9) return 0; z = z * 10 + c;
ct->offset = z * sign;
printf("t.%p s.%p\n",t,s);
return((int32_t)((long)t - (long)s));
}*/
int32_t taidate_str(char *s,struct taidate cd)
{
int32_t x,len,i = 0;
x = cd.year; if (x < 0) x = -x; do { ++i; x /= 10; } while(x);
len = (cd.year < 0) + i + 6;
if ( s != 0 )
{
x = cd.year;
if (x < 0) { x = -x; *s++ = '-'; }
s += i; do { *--s = '0' + (x % 10); x /= 10; } while(x); s += i;
x = cd.month;
s[0] = '-'; s[2] = '0' + (x % 10); x /= 10; s[1] = '0' + (x % 10);
x = cd.day;
s[3] = '-'; s[5] = '0' + (x % 10); x /= 10; s[4] = '0' + (x % 10);
s[len] = 0;
}
return(len);
}
char *taitime_str(char *s,struct taitime ct)
{
int32_t result,x,len;
result = taidate_str(s,ct.date);
len = result + 15;
if ( s != 0 )
{
s += result;
x = ct.hour;
s[0] = ' ';
s[2] = '0' + (x % 10); x /= 10;
s[1] = '0' + (x % 10);
s += 3;
x = ct.minute;
s[0] = ':';
s[2] = '0' + (x % 10); x /= 10;
s[1] = '0' + (x % 10);
s += 3;
x = ct.second;
s[0] = ':';
s[2] = '0' + (x % 10); x /= 10;
s[1] = '0' + (x % 10);
s += 3;
s[0] = ' ';
x = ct.offset;
if (x < 0) { s[1] = '-'; x = -x; } else s[1] = '+';
s[5] = '0' + (x % 10); x /= 10;
s[4] = '0' + (x % 6); x /= 6;
s[3] = '0' + (x % 10); x /= 10;
s[2] = '0' + (x % 10);
s[6] = 0;
}
return(s);
}
void tai_pack(char *s,struct tai *t)
{
uint64_t x;
x = t->x;
s[7] = x & 255; x >>= 8;
s[6] = x & 255; x >>= 8;
s[5] = x & 255; x >>= 8;
s[4] = x & 255; x >>= 8;
s[3] = x & 255; x >>= 8;
s[2] = x & 255; x >>= 8;
s[1] = x & 255; x >>= 8;
s[0] = x;
}
void tai_unpack(char *s,struct tai *t)
{
uint64_t x;
x = (uint8_t) s[0];
x <<= 8; x += (uint8_t) s[1];
x <<= 8; x += (uint8_t) s[2];
x <<= 8; x += (uint8_t) s[3];
x <<= 8; x += (uint8_t) s[4];
x <<= 8; x += (uint8_t) s[5];
x <<= 8; x += (uint8_t) s[6];
x <<= 8; x += (uint8_t) s[7];
t->x = x;
}
void tai_add(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x + v->x; }
void tai_sub(struct tai *t,struct tai *u,struct tai *v) { t->x = u->x - v->x; }
// {"leapseconds":["+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30"]}
char *leapseconds[] = { "+1972-06-30", "+1972-12-31", "+1973-12-31", "+1974-12-31", "+1975-12-31", "+1976-12-31", "+1977-12-31", "+1982-06-30", "+1983-06-30", "+1985-06-30", "+1987-12-31", "+1989-12-31", "+1990-12-31", "+1992-06-30", "+1993-06-30", "+1994-06-30", "+1995-12-31", "+1997-06-30", "+1998-12-31", "+2005-12-31", "+2008-12-31", "+2012-06-30", "+2015-06-30" };
struct tai leaptais[sizeof(leapseconds)/sizeof(*leapseconds)];
char *dayname[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" } ;
static int32_t times365[4] = { 0, 365, 730, 1095 } ;
static int32_t times36524[4] = { 0, 36524, 73048, 109572 } ;
static int32_t montab[12] = { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 } ;
// month length after february is (306 * m + 5) / 10
int32_t taidate_mjd(struct taidate cd)
{
int32_t y,m,d;
d = cd.day - 678882L;
m = cd.month - 1;
y = cd.year;
d += 146097L * (y / 400);
y %= 400;
if (m >= 2) m -= 2; else { m += 10; --y; }
y += (m / 12);
m %= 12;
if (m < 0) { m += 12; --y; }
d += montab[m];
d += 146097L * (y / 400);
y %= 400;
if (y < 0) { y += 400; d -= 146097L; }
d += times365[y & 3];
y >>= 2;
d += 1461L * (y % 25);
y /= 25;
d += times36524[y & 3];
return d;
}
struct tai utc2tai(uint32_t timestamp) { struct tai t; memset(&t,0,sizeof(t)); t.x = (timestamp + TAI_UTC_DIFF); return(t); }
uint32_t tai2utc(struct tai t) { t.x -= TAI_UTC_DIFF; return((uint32_t)t.x); }
uint64_t tai2utime(struct tai t)
{
uint64_t mjd; uint64_t timestamp; struct taitime ct = tai2time(t,0,0);
mjd = taidate_mjd(ct.date);
timestamp = ((uint64_t)(mjd * 24*3600 + ct.hour*3600 + ct.minute*60 + ct.second));
return(timestamp);
}
struct tai tai_now()
{
struct tai t; uint64_t now = time(NULL);
t.x = TAI_UTC_DIFF + now;
t.millis = OS_milliseconds() - First_TAI.millis;
if ( First_TAI.x == 0 )
{
First_TAI = t, First_utc = (uint32_t)now;
#ifndef DISABLE_LEAPS
UTC_ADJUST = -36;
#endif
printf("TAINOW.%llu %03.3f UTC.%u vs %u [diff %d]\n",(long long)t.x,t.millis,First_utc,tai2utc(t),UTC_ADJUST);
}
return(t);
}
struct tai leapsecs_add(struct tai t,int32_t hit)
{
#ifndef DISABLE_LEAPS
int32_t i; uint64_t u;
u = t.x;
if ( t.x > leaptais[(sizeof(leaptais)/sizeof(*leaptais)) - 1].x )
u += (sizeof(leaptais)/sizeof(*leaptais));//, printf("add leap.%ld\n",(sizeof(leaptais)/sizeof(*leaptais)));
else
{
for (i=0; i<sizeof(leaptais)/sizeof(*leaptais); i++)
{
if ( u < leaptais[i].x )
break;
if ( hit == 0 || u > leaptais[i].x )
u++;
}
}
t.x = u;
#endif
return(t);
}
struct tai taitime2tai(struct taitime ct)
{
int32_t day,s; struct tai t;
day = taidate_mjd(ct.date);
s = ct.hour * 60 + ct.minute;
s = (s - ct.offset) * 60 + ct.second;
t.x = day * 86400ULL + 4611686014920671114ULL + (uint64_t)s;
t.millis = ct.millis;
return(leapsecs_add(t,ct.second == 60));
}
double tai_diff(struct tai reftai,struct tai cmptai)
{
double diff;
//char str[111],str2[111]; printf("start [%f %f] %s vs %s\n",reftai.millis,cmptai.millis,tai_str(str,reftai),tai_str(str2,cmptai));
reftai = taitime2tai(tai2time(reftai,0,0));
cmptai = taitime2tai(tai2time(cmptai,0,0));
diff = (cmptai.x - reftai.x) * 1000. + (cmptai.millis - reftai.millis);
//printf("%s vs %s -> diff [%d] %f [%llu - %llu]\n\n",tai_str(str,reftai),tai_str(str2,cmptai),(int32_t)(cmptai.x - reftai.x),diff,(long long)cmptai.x,(long long)reftai.x);
return(diff);
}
struct tai taidate_scan(char *s,int32_t numleaps)
{
int32_t z,c,sign = 1; char *t = s; struct taidate cd; struct tai st;
st.x = 0;
if (*t == '-') { ++t; sign = -1; }
else if ( *t == '+' )
t++;
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
cd.year = z * sign;
if (*t++ != '-') return(st);
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
cd.month = z;
if (*t++ != '-') return(st);
z = 0; while ((c = (uint8_t) (*t - '0')) <= 9) { z = z * 10 + c; ++t; }
cd.day = z;
//printf("year.%d month.%d day.%d numleaps.%d\n",cd.year,cd.month,cd.day,numleaps);
st.x = (taidate_mjd(cd) + 1) * 86400ULL + 4611686014920671114ULL + numleaps;
return(st);
}
int32_t leapsecs_sub(struct tai *lt)
{
#ifndef DISABLE_LEAPS
char out[101],x[TAI_PACK]; double packerr;
int32_t weekday,yearday,i,j,s; uint64_t u; struct tai t,t2; struct taitime ct2;
if ( leaptais[0].x == 0 )
{
for (i=0; i<sizeof(leapseconds)/sizeof(*leapseconds); i++)
{
t = taidate_scan(leapseconds[i],i);
if ( t.x == 0 )
printf("unable to parse.(%s)\n",leapseconds[i]);
else
{
//t = taitime2tai(ct);
leaptais[i] = t;
ct2 = tai2time(t,&weekday,&yearday);
tai_pack(x,&t);
tai_unpack(x,&t2);
tai_sub(&t2,&t2,&t);
packerr = tai_approx(&t2);
for (j=0; j<TAI_PACK; j++)
printf("%2.2x",(uint32_t)(uint8_t)x[j]);
if ( packerr != 0 )
printf(" packerr=%f",packerr);
taitime_str(out,ct2);
printf(" %03d %s %s",yearday,dayname[weekday],out);
printf("\n");
}
}
}
u = lt->x;
if ( u > leaptais[sizeof(leaptais)/sizeof(*leaptais)-1].x )
lt->x -= (sizeof(leaptais)/sizeof(*leaptais) - 1);
else
{
s = 0;
for (i=0; i<sizeof(leaptais)/sizeof(*leaptais); i++)
{
if ( u < leaptais[i].x )
break;
++s;
if ( u == leaptais[i].x )
{
lt->x = u - s;
return(1);
}
}
lt->x = u - s;
}
#endif
return(0);
}
char *tai_str(char *str,struct tai t)
{
struct taitime ct;
ct = tai2time(t,0,0);
sprintf(str,"%d-%02d-%02d %02d:%02d:%02d %03.3f",ct.date.year,ct.date.month,ct.date.day,ct.hour,ct.minute,ct.second,ct.millis);
return(str);
}
/*char *utc_str(char *str,struct tai t)
{
t.x += UTC_ADJUST;
return(tai_str(str,t));
}*/
char *utc_str(char *str,uint32_t utc)
{
struct taitime ct; struct tai t;
t = utc2tai(utc);
t.x += UTC_ADJUST;
ct = tai2time(t,0,0);
sprintf(str,"%d-%02d-%02dT%02d:%02d:%02dZ",ct.date.year,ct.date.month,ct.date.day,ct.hour,ct.minute,ct.second);
return(str);
}
double OS_milliseconds()
{
return(OS_portable_milliseconds());
}
int32_t calc_datenum(int32_t year,int32_t month,int32_t day)
{
return((year * 10000) + (month * 100) + day);
}
int32_t extract_datenum(int32_t *yearp,int32_t *monthp,int32_t *dayp,int32_t datenum)
{
*yearp = datenum / 10000, *monthp = (datenum / 100) % 100, *dayp = (datenum % 100);
if ( *yearp >= 2000 && *yearp <= 2038 && *monthp >= 1 && *monthp <= 12 && *dayp >= 1 && *dayp <= 31 )
return(datenum);
else return(-1);
}
uint32_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t second) // datenum+H:M:S -> unix time
{
int32_t year,month,day; struct tai t; struct taitime ct;
if ( 1 )
{
if ( extract_datenum(&year,&month,&day,datenum) > 0 )
{
ct = taitime_set(taidate_set(year,month,day),hour,minute,second);
t = taitime2tai(ct);
//char str[65]; printf("conv.(y%d m%d d%d %d:%d:%d) %s\n",year,month,day,hour,minute,second,tai_str(str,t));
return((uint32_t)tai2utc(t));//tai2utime(t)+788250398LL - 4294967296LL);
}
return(0);
}
else
{
#ifdef __PNACL
return(0);
#else
struct tm t;
memset(&t,0,sizeof(t));
t.tm_year = (datenum / 10000) - 1900, t.tm_mon = ((datenum / 100) % 100) - 1, t.tm_mday = (datenum % 100);
t.tm_hour = hour, t.tm_min = minute, t.tm_sec = second;
return((uint32_t)timegm(&t));
#endif
}
}
int32_t OS_conv_unixtime(struct tai *tp,int32_t *secondsp,time_t timestamp) // gmtime -> datenum + number of seconds
{
struct tm tm,*ptr; int32_t datenum; uint32_t checktime; char buf[64]; struct tai t; struct taitime ct;
if ( 1 )
{
*tp = t = utc2tai((uint32_t)timestamp);
ct = tai2time(t,0,0);
*secondsp = (ct.hour*3600 + ct.minute*60 + ct.second);
return(calc_datenum(ct.date.year,ct.date.month,ct.date.day));
}
else
{
if ( (ptr= gmtime(&timestamp)) != 0 )
tm = *ptr;;
strftime(buf,sizeof(buf), "%Y-%m-%dT%H:%M:%SZ",&tm); //printf("%s\n",buf);
datenum = conv_date(secondsp,buf);
if ( (checktime= OS_conv_datenum(datenum,*secondsp/3600,(*secondsp%3600)/60,*secondsp%60)) != timestamp )
{
printf("error: timestamp.%u -> (%d + %d) -> %u\n",(uint32_t)timestamp,datenum,*secondsp,checktime);
return(-1);
}
return(datenum);
}
}
int32_t conv_date(int32_t *secondsp,char *date)
{
char origdate[64],tmpdate[64]; int32_t year,month,day,hour,min,sec,len;
strcpy(origdate,date), strcpy(tmpdate,date), tmpdate[8 + 2] = 0;
year = atoi(tmpdate), month = atoi(tmpdate+5), day = atoi(tmpdate+8);
*secondsp = 0;
if ( (len= (int32_t)strlen(date)) <= 10 )
hour = min = sec = 0;
if ( len >= 18 )
{
tmpdate[11 + 2] = 0, tmpdate[14 + 2] = 0, tmpdate[17 + 2] = 0;
hour = atoi(tmpdate+11), min = atoi(tmpdate + 14), sec = atoi(tmpdate+17);
if ( hour >= 0 && hour < 24 && min >= 0 && min < 60 && sec >= 0 && sec < 60 )
*secondsp = (3600*hour + 60*min + sec);
else printf("ERROR: seconds.%d %d %d %d, len.%d\n",*secondsp,hour,min,sec,len);
}
//printf("(%s) -> Y.%d M.%d D.%d %d:%d:%d\n",date,year,month,day,hour,min,sec);
sprintf(origdate,"%d-%02d-%02d",year,month,day); //2015-07-25T22:34:31Z
if ( strcmp(tmpdate,origdate) != 0 )
{
printf("conv_date date conversion error (%s) -> (%s)\n",origdate,date);
return(-1);
}
return((year * 10000) + (month * 100) + day);
}
uint32_t OS_conv_utime(char *utime)
{
int32_t datenum,seconds;
datenum = conv_date(&seconds,utime);
return((uint32_t)OS_conv_datenum(datenum,seconds/3600,(seconds%3600)/60,seconds%60));
}
int32_t expand_datenum(char *date,int32_t datenum)
{
int32_t year,month,day; date[0] = 0;
if ( extract_datenum(&year,&month,&day,datenum) != datenum)
return(-1);
sprintf(date,"%d-%02d-%02d",year,month,day);
return(0);
}
int32_t ecb_decrdate(int32_t *yearp,int32_t *monthp,int32_t *dayp,char *date,int32_t datenum)
{
static int lastday[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
int32_t year,month,day;
year = datenum / 10000, month = (datenum / 100) % 100, day = (datenum % 100);
//printf("%d -> %d %d %d\n",datenum,year,month,day);
if ( --day <= 0 )
{
if ( --month <= 0 )
{
if ( --year < 2000 )
{
printf("reached epoch start\n");
return(-1);
}
month = 12;
}
day = lastday[month];
if ( month == 2 && (year % 4) == 0 )
day++;
}
sprintf(date,"%d-%02d-%02d",year,month,day);
//printf("%d -> %d %d %d (%s)\n",datenum,year,month,day,date);
*yearp = year, *monthp = month, *dayp = day;
return((year * 10000) + (month * 100) + day);
}
#ifdef ENABLE_TEST
#include <unistd.h>
int main(int argc, const char * argv[])
{
int i; char str[111],str2[111],str3[111],str4[111]; struct taitime ct;
struct tai t,start = tai_now();
for (i=0; i<100; i++)
{
sleep(1);
t = tai_now();
taidate_str(str2,tai2date(t));
printf("(%s) time.%s date.%s %ld start.%ld %s %u %u\n",tai_str(str3,t),taitime_str(str,ct),str2,(long)tai2utime(t),(long)tai2utime(start),utime_str(str4,t),tai2utc(t),(uint32_t)time(NULL));
}
// insert code here...
{
char str[65]; struct tai t; double startmillis; int32_t datenum,seconds; uint64_t i,checkval,timestamp,now = (uint32_t)time(NULL);
startmillis = OS_milliseconds();
for (i=0; i<1000000; i++)
{
timestamp = now - (rand() % 100000000LL); // range -100000000LL to +500000000LL
datenum = OS_conv_unixtime(&t,&seconds,timestamp); // gmtime -> datenum + number of seconds
checkval = OS_conv_datenum(datenum,seconds/3600,(seconds/60)%60,seconds%60); // datenum+H:M:S -> unix time
if ( checkval != timestamp )
printf("%s i.%lld timestamp.%-12llu -> (%d:%06d) -> checkval.%-12llu diff.[%lld]\n",tai_str(str,t),(long long)i,(long long)timestamp,datenum,seconds,(long long)checkval,(long long)(timestamp-checkval));
}
printf("million tai compares in %.3f microseconds per encode/decode\n",1000. * (OS_milliseconds()-startmillis)/i);
}
/* struct tai t = tai_now(); double diff,lastdiff = 0.;
for (i=0; i<1000000; i++)
{
diff = tai_diff(t,tai_now());
if ( diff < lastdiff )
printf("embargo.x %f %llu.%3.3f %llu.%3.3f\n",tai_diff(t,tai_now()),(long long)t.x,t.millis,(long long)tai_now().x,tai_now().millis);
lastdiff = diff;
//usleep(100000);
} getchar();
*/
return 0;
}
#endif