home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
nisttime.carsoncity.k12.mi.us
/
nisttime.carsoncity.k12.mi.us.tar
/
nisttime.carsoncity.k12.mi.us
/
pub
/
lockclock
/
diftim_l.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-18
|
8KB
|
295 lines
#include "sizint.h"
int diftim(buf,mjd,fday,difp,ls)
char buf[280]; /*time string received from ACTS*/
LONG *mjd; /*MJD of calibration */
LONG *fday; /*time of calibration in seconds */
double *difp; /*time difference, local-ACTS*/
int *ls; /*leap second flag read from received data*/
{
#include "getdif.h"
#include <stdio.h>
#ifdef IBMPC
#include <dos.h>
#endif
char c;
float xx,interp(); /* holds tick fraction */
LONG cvt2jd(); /*converts yr,mo,day to MJD */
int j,yr,mo,day,hr,min,sec,dst; /* holds parsed NIST time */
int yribm,moibm,dayibm,hribm,minibm,secibm,hunibm; /* holds computer time */
#ifdef IBMPC
int yrat,moat,dayat,hrat,minat,secat;/* holds CMOS time for AT*/
#endif
int iterr = 0;
#ifdef IBMPC
int lday[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; /*last day of month*/
#endif
static int tday[13] = {0,0,31,59,90,120,151,181,212,243,273,304,334};
int done = 0; /* flag to show when comparison is complete */
#ifdef IBMPC
int dsdone=0; /* flag to show conversion for daylight sav.*/
int ks; /*value to be transmitted to interp*/
#endif
#ifdef SUN
#include <sys/time.h>
struct timeval tvv,*tp;
struct tm gvv,*gv;
LONG kin; /*value to be transmitted to interp*/
#endif
double diff; /*local copy of time difference*/
LONG itdiff; /*integer version of diff*/
/*
this subroutine receives a time string in character
array buf. it is parsed and compared with the system
clock. the origin of the parser is the - character between
the year and the month so that leading stuff will simply be
ignored.
the IBMPC version performs the comparison using local time
this subroutine uses global variables dsflag to check for
daylight savings time and utcdif to convert from UTC to local
time
the SUN version performs the comparison using UTC directly
since that is available from the system
this version differs from the version used for ACTS in that
it does not print the time difference on the screen but
rather returns it to the caller
the subroutine normally returns a status of 0, and it
will return a status of -1 if there is a syntax error
on the input time string.
begin by getting computer time now.
*/
#ifdef IBMPC
_AH=0;
geninterrupt(0x1a); /*get time as number of ticks*/
ks=_DX; /*save low half to send to interp*/
_AH=0x2c;
geninterrupt(0x21);
hribm=_CH;
minibm=_CL;
secibm=_DH;
hunibm=_DL;
/*
also get tick fraction now for interpolating later
*/
#if INTERP
xx=interp((LONG)ks);
#endif
_AH=0x2a;
geninterrupt(0x21);
yribm=_CX;
moibm=_DH;
dayibm=_DL;
yribm -= 1900;
/*
if this is an at-type machine, read CMOS clock too
*/
if(atflag != 0)
{
_AH=2;
geninterrupt(0x1a);
hrat=_CH;
minat=_CL;
secat=_DH;
_AH=4;
geninterrupt(0x1a);
yrat=_CL;
moat=_DH;
dayat=_DL;
}
#endif
#ifdef SUN
tp= &tvv;
gv= &gvv;
gettimeofday(tp,0);
kin=tp->tv_usec;
/*
get tick fraction from interp. send current microsecond
value in case value changes while call transfer is in
progress.
*/
#if INTERP
xx=interp(kin);
#endif
gv=gmtime(tp);
yribm=gv->tm_year;
moibm=gv->tm_mon + 1;
dayibm=gv->tm_mday;
hribm=gv->tm_hour;
minibm=gv->tm_min;
secibm=gv->tm_sec;
hunibm=tp->tv_usec/10000;
#endif
/*
now parse line from NIST transmission
*/
for(j=0; (buf[j] != 0) && (buf[j] != '-') ; j++) ;
sscanf(&buf[j-2],"%2d-%2d-%2d %2d:%2d:%2d %d %d",&yr,&mo,&day,
&hr,&min,&sec,&dst,ls);
/*
check for obvious transmission errors
*/
if( (mo < 1) || (mo > 12) || (day < 1) ||
(day>31) || (hr < 0 ) || (hr >23) ||
(min< 0) || (min> 59) || (sec < 0) ||
(sec>59) || (dst< 0 ) || (dst > 99)||
(*ls< 0) || (*ls> 2 ) ) return (-1);
/*
if the leap second flag is set then see if the
leap second is due today. if yes, return 10x ls.
the leap seconds can occur only at the end of
the months of june or december
*/
if(*ls != 0) /* if leap second due*/
{
if( ( (mo == 6) && (day == 30) ) ||
( (mo ==12) && (day == 31) ) ) *ls *= 10;
}
/*
for IBMPC version, convert to local time and
daylight savings time if necessary
note that this conversion is not necessary for the
SUN which performs the comparison directly on UTC
*/
#ifdef IBMPC
/*
make standard-time portion of dst flag contiguous
*/
if(dst == 0) dst = 100;
/*
convert from utc to local time. note that minute and second
are already correct.
daylight savings time flag must also be updated
if conversion to local time changes the day
*/
if( (yr & 3) == 0 ) lday[2]=29; /* 29 days for Feb in leap year */
hr += utcdif; /* convert hour to local time */
/*
also do first part of conversion to daylight savings time
see parset and arcdif where same problem is dealt with
*/
if( (dsflag != 0) && (dst <= 50) && (dst > 1) )
{
hr++;
dsdone=1;
}
if(hr < 0)
{
hr += 24;
day--;
dst++; /* update daylight savings flag for change of day*/
if(day < 1)
{
mo--;
if(mo < 1)
{
mo=12;
yr--;
}
day=lday[mo];
}
}
if(hr > 23)
{
hr -= 24;
day++;
dst--; /* update daylight saving flag for change of day */
if(day > lday[mo])
{
day=1;
mo++;
if(mo > 12)
{
mo=1;
yr++;
}
}
}
/*
now finish up daylight savings time if enabled
*/
if( (dsflag != 0) && (dsdone == 0) )
{
if( (dst == 51) && (hr >= 2) ) hr++;
if( (dst == 1) && (hr < 2) ) hr++;
}
#endif
/*
save time of calibration in input parameters mjd and
fday
*/
*mjd=cvt2jd(yr,mo,day);
*fday=3600*hr + 60*min + sec;
/*
ready to begin comparing the clocks
first see if the days are the same
*/
itdiff=365*(yribm - yr) + tday[moibm] - tday[mo] + dayibm - day;
if( ( (yribm & 3) == 0) && (moibm > 2) ) itdiff++;
if( ( (yr & 3) == 0) && (mo > 2) ) itdiff--;
if( (itdiff > 1) || (itdiff < -1) )
{
diff = itdiff;
diff *= 86400; /*convert days to seconds */
done=1;
}
if(done == 0)
{
itdiff= 24*itdiff + hribm - hr;
if( (itdiff > 2) || (itdiff < -2) )
{
diff=itdiff;
diff *= 3600; /*convert hours to seconds */
done=1;
}
}
if(done == 0)
{
itdiff=60*itdiff + minibm - min;
if( (itdiff > 40) || (itdiff < -40) )
{
diff=itdiff;
diff *= 60; /*convert minutes to seconds */
done=1;
}
}
if(done == 0)
{
diff=60*itdiff + secibm - sec;
#ifdef IBMPC
diff += 0.01*(float)hunibm;
#endif
#ifdef SUN
diff += (double)kin*1e-6;
#endif
/*
Add the fraction of a tick computed by interp. this value
tends to make the local clock later, since this value must be
added to the integer values read from the system.
If this is a SUN system, the interval between ticks is defined
in the header file nistime.h. It is typically 20 msec on a Sun,
10 msec on a VAX and 3906 usec on a DEC RISC machine. This number
is always given in microseconds and is converted to seconds
here. Note that the value in paretheses is a tick fraction
expressed as a percent. All MS DOS machines uses the same clock
rate of roughly 18.2 ticks/second or about 55 msec betweek
ticks.
*/
#if INTERP
#ifdef IBMPC
diff += 0.000549*(100-xx);
#endif
#ifdef SUN
diff += ( (double) tickus) *(100-xx)*1e-8;
#endif
#endif
}
*difp=diff;
return(0); /*return status okay*/
}