home *** CD-ROM | disk | FTP | other *** search
/ nisttime.carsoncity.k12.mi.us / nisttime.carsoncity.k12.mi.us.tar / nisttime.carsoncity.k12.mi.us / pub / acts / arcdif.c next >
C/C++ Source or Header  |  1997-12-08  |  8KB  |  344 lines

  1. void arcdif(buf)
  2. char buf[280];
  3. {
  4. #include "nistime.h"
  5. #include <stdio.h>
  6. #ifdef IBMPC
  7. #include <dos.h>
  8. #endif
  9. #ifdef SUN
  10. #include <sys/time.h>
  11. #include <math.h>
  12. #endif
  13. char c;
  14. int j,yr,mo,day,hr,min,sec,dst;   /* holds parsed NIST time */
  15. #ifdef IBMPC
  16. int yribm,moibm,dayibm,hribm,minibm,secibm,hunibm; /* holds computer time*/
  17. int yrat,moat,dayat,hrat,minat,secat;/* holds CMOS time for AT*/
  18. #endif
  19. #ifdef SUN
  20. LONG mjd;
  21. LONG mjd0 = 40587;     /* mjd of 1/1/70 */
  22. struct timeval tvv,*tp;    /* holds time in SUN format */
  23. extern int hs;             /* 1 if dialing at 1200, 0 if at 300 */
  24. LONG cvt2jd();         /* convert yr-mo-day to MJD for sun  */
  25. #endif
  26. double diff;
  27. #ifdef IBMPC
  28. extern int utcdif;           /* local time - utc in hours */
  29. extern int dsflag;           /* daylight saving time? 1=yes, 0=no */
  30. extern int atflag;           /* AT-type machine? 1=yes, 0=no */
  31. #endif
  32. extern FILE *jop;            /* file handle for writing difference*/
  33. #ifdef IBMPC
  34. int lday[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; /*last day of month*/
  35. int tday[13] = {0,0,31,59,90,120,151,181,212,243,273,304,334};
  36. int unpbcd();
  37. int dsdone = 0;              /* flag to show day. sav. time corr. done */
  38. #endif
  39. int done   = 0;              /* flag to show when comparison is done */
  40. float xx,interp();           /* interpolate fraction of a tick */
  41. /*
  42.     this subroutine receives a time string in character
  43.     array buf.  it is parsed and compared with the system
  44.     clock.  the origin of the parser is the - character between
  45.     the year and the month so that leading stuff (possible a lf)
  46.     will simply be ignored.
  47.  
  48.     if IBMPC is true, then the comparison is made using local
  49.     time as defined by global variables dsflag to check for
  50.     daylight savings time and utcdif to convert from UTC to local
  51.     time. if SUN is true then the conversion is done using UTC
  52.     directly.
  53.  
  54.     begin by getting computer time now. also get tick fraction
  55.     via interp.
  56. */
  57. #ifdef IBMPC
  58.     _AH=0x2c;
  59.     geninterrupt(0x21);
  60.     hribm=_CH;
  61.     minibm=_CL;
  62.     secibm=_DH;
  63.     hunibm=_DL;
  64.     xx=interp();         /* get tick fraction now */
  65.     _AH=0x2a;
  66.     geninterrupt(0x21);
  67.     yribm=_CX;
  68.     moibm=_DH;
  69.     dayibm=_DL;
  70.     yribm -= 1900;    /*number of years since 1900*/
  71. /*
  72.     if this is an at-type machine, read CMOS clock too
  73. */
  74.     if(atflag != 0)
  75.     {
  76.     _AH=2;
  77.     geninterrupt(0x1a);
  78.     hrat=_CH;
  79.     minat=_CL;
  80.     secat=_DH;
  81.     _AH=4;
  82.     geninterrupt(0x1a);
  83.     yrat=_CL;
  84.     moat=_DH;
  85.     dayat=_DL;
  86.     }
  87. #endif
  88. #ifdef SUN
  89.     tp= &tvv;
  90.     gettimeofday(tp,0);
  91.     xx=interp();
  92. #endif
  93. /*
  94.     now parse line from NIST transmission
  95.  
  96.     first find - between year and month
  97. */
  98.     for(j=0; (buf[j] != 0) && (buf[j] != '-') ; j++) ;
  99.     sscanf(&buf[j-2],"%2d-%2d-%2d %2d:%2d:%2d %d",&yr,&mo,&day,
  100.     &hr,&min,&sec,&dst);
  101.     if(yr < 90) yr += 100;    /*number of years since 1900*/
  102. #ifdef SUN
  103. /*
  104.     1200 bit/s transmission includes MJD -- therefore parse it
  105.     from input line.  300 bit/s transmission does not include
  106.     MJD and we must get it from yr-mo-day via a call to cvt2jd
  107. */
  108.     if(hs == 1) sscanf(&buf[j-8],"%5ld",&mjd);   /* also get mjd for SUN */
  109.     else        mjd=cvt2jd(yr,mo,day);
  110. /*
  111.     convert nist time to number of seconds since 1/1/70
  112. */
  113.     mjd= 86400*(mjd - mjd0);
  114.     mjd= mjd + 3600*hr + 60*min + sec;
  115. #endif
  116. #ifdef IBMPC
  117. /*
  118.     for the IBMPC version, the comparison is made against
  119.     local time -- thus nist time must be converted to local
  120.     time using utcdif and dst flags.
  121. */
  122. /*
  123.     make standard-time portion of dst flag contiguous
  124. */
  125.     if(dst == 0) dst = 100;
  126. /*
  127.     convert from utc to local time. note that minute and second
  128.     are already correct.
  129.     daylight savings time flag must also be updated
  130.     if conversion to local time changes the day
  131.  
  132.     **
  133.     ** version of 12 may -- compiled and tested 31 may
  134.     daylight savings time correction must be done in two
  135.     parts since adding hour may cause hour/day to overflow.
  136.     therefore deal with part of it now -- if day changes then
  137.     correction flag dst will change and therefore correction
  138.     for transition days must be done after final day is known.
  139.     also see subroutine parset where same problem appears.
  140. */
  141.     if( (yr & 3) == 0 ) lday[2]=29;  /* 29 days for Feb in leap year*/
  142.     hr += utcdif;              /* convert hour to local standard time */
  143. /*
  144.     see comments in parset.c regarding the following code, which
  145.     is basically copied from there
  146. */
  147.     if( (dsflag != 0) && (dst <= 50) && (dst > 1) )
  148.     {
  149.     hr++;
  150.     dsdone=1;
  151.     }              /* do first part of daylight savings time */
  152.     if( (dsflag != 0) && (dst == 1) && (hr < 1)  )
  153.        {
  154.        hr++;
  155.        dsdone=1;
  156.     }
  157.     if(hr < 0)
  158.     {
  159.     hr += 24;
  160.     day--;
  161.     dst++;         /* update daylight savings flag for change of day*/
  162.     if(day < 1)
  163.        {
  164.        mo--;
  165.        if(mo < 1)
  166.           {
  167.           mo=12;
  168.           yr--;
  169.           }
  170.        day=lday[mo];
  171.        }
  172.     }
  173.     if(hr > 23)
  174.     {
  175.     hr -= 24;
  176.     day++;
  177.     dst--;        /* update daylight saving flag for change of day */
  178.     if(day > lday[mo])
  179.        {
  180.        day=1;
  181.        mo++;
  182.        if(mo > 12)
  183.           {
  184.           mo=1;
  185.           yr++;
  186.           }
  187.        }
  188.     }
  189. /*
  190.     now finish up daylight savings time if enabled
  191.     note that the correction when dst=1 uses the test
  192.     hr < 1 even though the transition is at 0200 because
  193.     the hour has been set to standard time above by default.
  194.     also see comments in parset.c
  195. */
  196.     if ( (dsflag != 0) && (dsdone == 0) )
  197.     {
  198.        if( (dst == 51) && (hr >= 2) ) hr++;
  199.        if( (dst ==  1) && (hr <  1) ) hr++;
  200.     }
  201. #endif
  202. /*
  203.     ready to begin comparing the clocks
  204.     note that we only write a 2-digit year here,
  205.     but that yr actually is the number of years since
  206.     1900.
  207. */
  208.     fprintf(jop,"%2d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
  209.           yr%100,mo,day,hr,min,sec);
  210. #ifdef SUN
  211. /*
  212.     sun comparison is done directly as difference
  213.     of two longs giving number of seconds since 1/1/70
  214. */
  215.     diff= tp->tv_sec - mjd;
  216.     done=0;
  217.     if(fabs(diff) > 100000.)
  218.        {
  219.        fprintf(jop," %8.2fd\n",diff/86400.);
  220.        done=1;
  221.        }
  222.     if( (done == 0) && (fabs(diff) > 10000.) )
  223.        {
  224.        fprintf(jop," %8.2fh\n",diff/3600.);
  225.        done=1;
  226.        }
  227.     if( (done == 0) && (fabs(diff) > 1000.) )
  228.        {
  229.        fprintf(jop," %8.2fm\n",diff/60.);
  230.        done=1;
  231.        }
  232.     if( (done == 0) && (fabs(diff) <= 1000.) )
  233.        {
  234.        diff += (float) tp->tv_usec/1000000.;
  235. /*
  236.     add the fraction of a tick computed by interp.  this value
  237.     tends to make the sun clock later, since this value must be
  238.     added to the integer values read from the system.
  239.     The interval between ticks is defined in the header file
  240.     nistime.h.  It is typically 20 msec on a Sun, 10 msec on a
  241.     VAX and 3906 usec on a DEC RISC machine.  This number is
  242.     always given in microseconds and is converted to seconds
  243.     here.  Note that the value in paretheses is a tick fraction
  244.     expressed as a percent.
  245. */
  246.        diff += ( (double) tickus) *(100-xx)*1e-8;
  247.  
  248.        fprintf(jop," %9.4fs\n",diff);
  249.        }
  250. #endif
  251. #ifdef IBMPC
  252. /*
  253.     ibm comparison is done bit by bit to preserve
  254.     resolution
  255. */
  256.     diff=365*(yribm - yr) + tday[moibm] - tday[mo] + dayibm - day;
  257.     if( ( (yribm & 3) == 0)  && (moibm > 2) ) diff++;
  258.     if( ( (yr    & 3) == 0)  && (mo    > 2) ) diff--;
  259.     if( (diff > 1) || (diff < -1) )
  260.     {
  261.     fprintf(jop," %8.2fd",diff);
  262.     done=1;
  263.     }
  264.     if(done == 0)
  265.     {
  266.        diff= 24*diff + hribm - hr;
  267.        if( (diff > 2) || (diff < -2) )
  268.        {
  269.           fprintf(jop," %8.2fh",diff);
  270.           done=1;
  271.        }
  272.     }
  273.     if(done == 0)
  274.     {
  275.        diff=60*diff + minibm - min;
  276.        if( (diff > 10) || (diff < -10) )
  277.        {
  278.        fprintf(jop," %8.2fm",diff);
  279.        done=1;
  280.        }
  281.     }
  282.     if(done == 0)
  283.     {
  284. /*
  285.     compute difference, adding tick fraction computed by interp
  286. */
  287.        diff=60*diff + secibm - sec +  0.01*(float)hunibm
  288.          +  0.000549*(100-xx);
  289.        fprintf(jop," %8.3fs",diff);
  290.     }
  291.     if(atflag == 0)
  292.     {
  293.     fprintf(jop,"     0.00\n");
  294.     fclose(jop);
  295.     return;
  296.     }
  297. /*
  298.     begin comparison of CMOS time -- first convert from packed
  299.     BCD to normal binary, then compare as above.
  300. */
  301.     yrat=unpbcd(yrat);
  302.     if(yrat < 80) yrat += 100;    /*number of years since 1900*/
  303.     moat=unpbcd(moat);
  304.     dayat=unpbcd(dayat);
  305.     hrat=unpbcd(hrat);
  306.     minat=unpbcd(minat);
  307.     secat=unpbcd(secat);
  308.     diff=365*(yrat - yr) + tday[moat] - tday[mo] + dayat - day;
  309.     if( ( (yrat & 3) == 0) && (moat > 2) )  diff++;
  310.     if( ( (yr   & 3) == 0) && (mo   > 2) )  diff--;
  311.     done=0;
  312.     if( (diff > 1) || (diff < -1) )
  313.     {
  314.        fprintf(jop," %8.2fd\n",diff);
  315.        done=1;
  316.     }
  317.     if(done == 0)
  318.     {
  319.     diff=24*diff + hrat - hr;
  320.     if( (diff > 2) || (diff < -2) )
  321.        {
  322.        fprintf(jop," %8.2fh\n",diff);
  323.        done=1;
  324.        }
  325.     }
  326.     if(done == 0)
  327.     {
  328.     diff=60*diff + minat - min;
  329.     if( (diff > 10) || (diff < -10) )
  330.        {
  331.        fprintf(jop," %8.2fm\n",diff);
  332.        done=1;
  333.        }
  334.     }
  335.     if(done == 0)
  336.     {
  337.     diff=60*diff +secat - sec;
  338.     fprintf(jop," %8.2fs\n",diff);
  339.     }
  340. #endif
  341.     fclose(jop);
  342. }
  343.  
  344.