home *** CD-ROM | disk | FTP | other *** search
/ Jason Aller Floppy Collection / 125.img / PRO-C4.ZIP / BENCH1.ZIP / BENCH / DATE.C < prev    next >
C/C++ Source or Header  |  1990-05-28  |  11KB  |  554 lines

  1. /* ==( bench/date.c )== */
  2.  
  3. /* ----------------------------------------------- */
  4. /* Pro-C  Copyright (C) 1988 - 1990 Vestronix Inc. */
  5. /* Modification to this source is not supported    */
  6. /* by Vestronix Inc.                               */
  7. /*            All Rights Reserved                  */
  8. /* ----------------------------------------------- */
  9. /* Written   PRS   1-Jan-88                        */
  10. /* Modified  DM   17-Jan-90  See comments below    */
  11. /* ----------------------------------------------- */
  12. /* %W%  (%H% %T%) */
  13.  
  14. /*
  15.  *  Modifications
  16.  *
  17.  *  22-Apr-90  JH - bug fixes
  18.  *  17-Jan-90  DM - v2.0 Enhancement
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <bench.h>
  23. #include <time.h>
  24.  
  25. # define BADDATE    "Invalid Date"
  26. # define BADYEAR    "Invalid Year"
  27. # define BADMONTH   "Invalid Month"
  28. # define BADDAY     "Invalid Days"
  29. # define BADHOUR    "Invalid Hours"
  30. # define BADMINUTE  "Invalid Minutes"
  31. # define BADSECOND  "Invalid Seconds"
  32.  
  33. /*
  34.  * Written  - DM, JZ
  35.  *
  36.  * The following date arithmetic routines employ 3 types of date formats.
  37.  * Dates are stored internally as the number of seconds since startyear.
  38.  * Using an unsigned long type, this allows a span of 136 years from
  39.  * startyear to be available in calculations.
  40.  * For calculation purposes, the seconds since Startyear is used.
  41.  * A constant in the form YYMMDDHHNNSS needs to be represented as
  42.  * seconds too.  This calculation is determined by the current system date.
  43.  * ie. 1 month from Feb 3 is 28 days but 1 month from Mar 3 is 31 days.
  44.  * The final date format is as a character string (not necessarily null
  45.  * terminated).  The string is composed of sets of 2 digits, each of which
  46.  * describes one of year, month, date, hour, minute or second.  The specific
  47.  * layout of the string is given by a mask string.  The mask string can
  48.  * contain any of Y, M, D, H, N, or S, and must be null terminated.  Any
  49.  * other characters are ignored.
  50.  *
  51.  * The types of arithmetic expected are
  52.  *            datestring + constant ==> datestring
  53.  * and     long + constant         ==> datestring.
  54.  * These additions are achieved by converting the datestring and/or constant
  55.  * to a long using the routines dstrtol or contol.  The results of
  56.  * these conversions are then added to each other and converted back to a
  57.  * date using ltocon. */
  58.  
  59.  
  60. /*
  61.  *  Static Function Prototypes
  62. */
  63. #ifdef ANSI
  64.  static int gpair(char **);
  65.  static void intcat(int, char *);
  66. #else
  67.  static int gpair();
  68.  static void intcat();
  69. #endif
  70.  
  71. /*
  72.  * Additional support function for UNIX 
  73. */
  74. # ifdef UNIX
  75. char *itoa(n, str, base)
  76. int n;
  77. char *str;
  78. int base;
  79. {
  80.     if (base == 10)
  81.     sprintf(str, "%d", n);
  82.     return (str);
  83. }
  84. # endif
  85.  
  86. /*
  87.  *  Global Variables
  88. */
  89.  
  90. int startyear = 1970;
  91. extern int day_tab[][13];
  92.  
  93. static int gpair(cp)
  94. char **cp;
  95. {
  96.     register int c, d;
  97.  
  98.     if (**cp == 0)
  99.         return(-1);
  100.     c = (**cp - '0') * 10;
  101.     (*cp)++;
  102.     if (c<0 || c>100)
  103.         return(-2);
  104.     if(**cp == 0)
  105.         return(-3);
  106.     d = **cp - '0';
  107.     (*cp)++;
  108.     if (d<0 || d>9)
  109.         return(-4);
  110.     return (c+d);
  111. }
  112.  
  113. /*
  114.  * Catenate the integer num onto the end of buffer 
  115.  * ensuring that num is at least 2 digits.
  116. */
  117. static void intcat(num, buffer)
  118. int num;
  119. char *buffer;
  120. {
  121.     char pair[3];
  122.  
  123.     if (strlen(itoa(num, pair, 10)) == 1)
  124.         strcat(buffer, "0");
  125.     strcat(buffer, pair);
  126. }
  127.  
  128. /*
  129.  * todaystr() modifies a char string passed in to contain todays date 
  130.  * in the form of a string of the form "YYYYMMDDHHNNSS" 
  131. */
  132. void todaystr(tstr)
  133. char *tstr;
  134. {
  135.     time_t secs;
  136.     struct tm *tim;
  137.  
  138.     time(&secs);
  139.  
  140.     tim = localtime(&secs);
  141.  
  142.     tim->tm_year += 1900;
  143.  
  144.     sprintf(tstr, "%04d%02d%02d%02d%02d%02d", tim->tm_year, tim->tm_mon+1, tim->tm_mday, tim->tm_hour, tim->tm_min, tim->tm_sec);
  145.  
  146.     return;
  147. }
  148.  
  149. /*
  150.  * Converts the constant dtcon to the number of seconds since Jan. 1 of
  151.  * startyear using the constant basedt as the base date for adding dtcon.
  152. */
  153. unsigned long contol(dtcon)
  154. char *dtcon;   /* Assumed form of date constant is "YYMMDDHHNNSS" */
  155. {
  156.     int i;
  157.     int y1, m1, d1, h1, n1, s1;
  158.     int tdyy, tdym;
  159.     unsigned long timbuf = 0L;
  160.     char tdydtstr[15];
  161.     char *tdydtstr_ptr;
  162.  
  163.     if (*dtcon == '\0')
  164.         return (0L);
  165.  
  166.     todaystr(tdydtstr); /* get today's date in YYYYMMDDHHNNSS */
  167.     tdydtstr_ptr = tdydtstr;
  168.     tdyy = gpair(&tdydtstr_ptr);    /* pick apart */
  169.     tdyy *= 100;
  170.     tdyy += gpair(&tdydtstr_ptr);    /* pick apart */
  171.     tdym = gpair(&tdydtstr_ptr)-1;  /* today's date into tdyy and tdym */
  172.  
  173.     y1 = gpair(&dtcon);
  174.     if (y1<0 || y1>99) 
  175.     {
  176.         errmsg(BADDATE);
  177.         return(0L);
  178.     }
  179.     m1 = gpair(&dtcon);
  180.     if (m1<0 || m1>99) 
  181.     {
  182.         errmsg(BADDATE);
  183.         return(0L);
  184.     }
  185.     d1 = gpair(&dtcon);
  186.     if (d1<0 || d1>99) 
  187.     {
  188.         errmsg(BADDATE);
  189.         return(0L);
  190.     }
  191.     h1 = gpair(&dtcon);
  192.     if (h1<0 || h1>99) 
  193.     {
  194.         errmsg(BADDATE);
  195.         return(0L);
  196.     }
  197.     n1 = gpair(&dtcon);
  198.     if (n1<0 || n1>99) 
  199.     {
  200.         errmsg(BADDATE);
  201.         return(0L);
  202.     }
  203.     s1 = gpair(&dtcon);
  204.     if (s1<0 || s1>99) 
  205.     {
  206.         errmsg(BADDATE);
  207.         return(0L);
  208.     }
  209.  
  210.     /* Calculate constant in terms of number of seconds since today's date. */
  211.  
  212.     /* Add the years to the months i.t.o. months */
  213. /*
  214.  * I don't understand why this calculation was here !!
  215.  *
  216.     m1 += (y1-(startyear%100))*12-1;
  217. */
  218.     m1 += (y1 * 12);
  219.  
  220.     /* adds month sizes to timbuf for the number of months in constant */
  221.  
  222.     for ( i = tdym; i < tdym+m1; i++)
  223.         timbuf += day_tab[ !((tdyy+i/12)%4) ][ i%12+1 ];
  224.  
  225.     /* Break days down into seconds and add in remaining time in seconds.     */
  226.     timbuf += d1;
  227.     timbuf *= 24;
  228.     timbuf += h1;
  229.     timbuf *= 60;
  230.     timbuf += n1;
  231.     timbuf *= 60;
  232.     timbuf += s1;
  233.     return(timbuf);
  234. }
  235.  
  236. /* 
  237.  * Converts a date string (as formatted by mask) to
  238.  * long integer representing the number of seconds since Jan. 1 1970
  239. */
  240. unsigned long dstrtol(dtstring, mask)
  241. char *dtstring;
  242. char *mask;
  243. {
  244.     int i;
  245.     int y=0, m=1, d=1, h=0, n=0, s=0;
  246.     unsigned long timbuf = 0L;
  247.  
  248.     if (*dtstring == '\0')
  249.         return (0L);
  250.  
  251. /*
  252. errmsg("dstrtol(): dtsring '%s' mask '%s'", dtstring, mask);
  253. */
  254.     /* 
  255.      * Use mask to put dtstring into y, m, and d.
  256.      * Also, check validity of values.
  257.     */
  258.     while (*mask)
  259.     {
  260.         switch (*mask)
  261.         {
  262.         case 'Y' :
  263.             if (*(mask+3) == 'Y')
  264.             {
  265.                 /* 
  266.                  * 4 Character Year
  267.                 */
  268.                 y = gpair(&dtstring);
  269.                 y *= 100;
  270.                 y += gpair(&dtstring);
  271.                 mask += 3;
  272.             }
  273.             else if (*(mask+2) == 'Y')
  274.             {
  275.                 /*
  276.                  * All 2 Character Years are assumed
  277.                  * to be 1900 and something
  278.                 */
  279.                 y = 1900;
  280.                 dtstring++;
  281.                 y += gpair(&dtstring);
  282.                 mask += 2;
  283.             }
  284.             else if (*(mask+1) == 'Y')
  285.               {
  286.                 /*
  287.                  * All 2 Character Years are assumed
  288.                  * to be 1900 and something
  289.                 */
  290.                 y = 1900;
  291.                 y += gpair(&dtstring);
  292.                 mask++;
  293.             }
  294.             if (y < startyear) 
  295.             {
  296.                 errmsg(BADYEAR);
  297.                 y = startyear;
  298.             }
  299.             break;
  300.  
  301.         case 'M' :
  302.             m = gpair(&dtstring);
  303.             if (m<1 || m>12) 
  304.             {
  305.                 errmsg(BADMONTH);
  306.                 m = 1;
  307.             }
  308.             if (*(mask+1) == 'M') mask++;
  309.             break;
  310.  
  311.         case 'D' :
  312.             d = gpair(&dtstring);
  313.             if (*(mask+1) == 'D') mask++;
  314.             break;
  315.  
  316.         case 'H' :
  317.             h = gpair(&dtstring);
  318.             if (h < 0 || h > 23) 
  319.             {
  320.                 errmsg(BADHOUR);
  321.                 h = 0;
  322.             }
  323.             if (*(mask+1) == 'H') mask++;
  324.             break;
  325.  
  326.         case 'N' :
  327.             n = gpair(&dtstring);
  328.             if (n < 0 || n > 59) 
  329.             {
  330.                 errmsg(BADMINUTE);
  331.                 n = 0;
  332.             }
  333.             if (*(mask+1) == 'N') mask++;
  334.             break;
  335.  
  336.         case 'S' :
  337.             s = gpair(&dtstring);
  338.             if (s < 0 || s > 59) 
  339.             {
  340.                 errmsg(BADSECOND);
  341.                 s = 0;
  342.             }
  343.             if (*(mask+1) == 'S') mask++;
  344.             break;
  345.         }
  346.         mask++;
  347.     }
  348. /*
  349. errmsg("dstrtol() : y %d m %d d %d h %d n %d s %d", y, m, d, h, n, s);
  350. */
  351.  
  352.     if (d<1 || d > day_tab[ y%4 == 0 ][ m ]) 
  353.     {
  354.         errmsg(BADDAY);
  355.         d = 1;
  356.     }
  357.  
  358.     /* Convert y, m, and d to time quantity forms for constant.                */
  359.     y -= startyear;
  360.     m--;
  361.     /* this messes up compares on dates JH
  362.     d--;
  363.     */
  364.  
  365.     m += y*12;    /* Add the number of years in terms of months */
  366. /*
  367. errmsg("m %d y %d", m, y);
  368. */
  369.     for ( i = 0; i < m; i++)
  370.         timbuf += day_tab[ !((startyear+i/12)%4) ][ i%12+1 ];
  371.  
  372.     /* Break days down into seconds and add in remaining time in seconds.     */
  373.     timbuf += d;
  374.     timbuf *= 24;
  375.     timbuf += h;
  376.     timbuf *= 60;
  377.     timbuf += n;
  378.     timbuf *= 60;
  379.     timbuf += s;
  380. /*
  381. errmsg("dstrtol() : timbuf %ld", timbuf);
  382. */
  383.     return( timbuf);
  384.  
  385. }
  386.  
  387. /* 
  388.  * Converts the number `seconds' (the number of seconds since Jan. 1 of
  389.  * startyear) to a date constant of the form given by mask.
  390. */
  391. char *ltocon(seconds, mask, dtype)
  392. unsigned long seconds;
  393. char *mask;
  394. int dtype;
  395. {
  396.     static char datbuf[15];
  397.     unsigned int days;
  398.     int yr, mo=0;
  399.     long time;
  400.     int hr, mn, sd;
  401.  
  402. # ifdef DDEBUG
  403. errmsg("ltocon() : seconds %ld mask '%s', type %d", seconds, mask, dtype);
  404. # endif
  405.  
  406.     if (seconds == 0L)
  407.         return ("");
  408.  
  409.     /* Calculate full number of days in terms of years, months, and days. */
  410.     days = (int) (seconds/86400L);
  411.  
  412. # ifdef DDEBUG
  413. errmsg("1> days = %u", days);
  414. # endif
  415.  
  416.     yr = startyear - 1900;
  417.     mo = 0;
  418.     while (days >= day_tab[ !(yr%4) ][ mo+1 ])
  419.     {
  420.         days -= day_tab[ !(yr%4) ][ mo+1 ];
  421.         mo++;
  422.         yr += mo/12;
  423.         mo %= 12;
  424.         yr %= 100;
  425.     }
  426.  
  427. # ifdef DDEBUG
  428. errmsg("2> days = %u", days);
  429. # endif
  430.  
  431.     yr += ((1900 + yr) < startyear) ? 2000 : 1900;
  432.  
  433.     /* 
  434.      * Convert days to the day of the month
  435.      * ie. after 9 days of January it's Jan. 10
  436.      * and changes month to range 1 to 12 from 0 to 11 
  437.     */
  438.     /*   This messes up compares on dates  JH 
  439.     days++;
  440.     */
  441.     mo++;
  442.  
  443.     if (dtype == 0)    /* Result expected is a Constant */
  444.     {
  445.         mo--;
  446.         yr -= startyear;
  447.     }
  448.  
  449.     /*
  450.      * Convert time less than a full day.
  451.     */
  452.     time = seconds % 86400L;
  453.     hr = (int) (time/3600L);
  454.     time = time%3600L;
  455.     mn = (int) (time/60L);
  456.     sd = (int) (time%60L);
  457.  
  458. # ifdef DDEBUG
  459. errmsg("ltocon() : yr %d mo %d days %d hr %d mn %d sd %d", yr, mo, days, hr, mn, sd);
  460. # endif
  461.  
  462.     /* 
  463.      * Create string constant.
  464.      * use mask to create a dtstring from the integer values for year etc
  465.     */
  466.     *datbuf = '\0';
  467.     while (*mask) 
  468.     {
  469.         switch (*mask)
  470.          {
  471.         case 'Y' :
  472.             if (*(mask+3) == 'Y')
  473.              {
  474.                 intcat(yr/100, datbuf);
  475.                 intcat(yr%100, datbuf);
  476.                  mask += 3;
  477.              }
  478.             else if (*(mask+2) == 'Y')
  479.             {
  480.                 intcat(yr%100, datbuf);
  481.                 mask += 2;
  482.             }
  483.             else if (*(mask+1) == 'Y')
  484.               {
  485.                 intcat(yr%100, datbuf);
  486.                 mask++;
  487.             }
  488.             else
  489.                 intcat(yr%100, datbuf);
  490.             break;
  491.  
  492.         case 'M' :
  493.             intcat(mo, datbuf);
  494.             if (*(mask+1) == 'M') mask++;
  495.             break;
  496.  
  497.         case 'D' :
  498.             intcat(days, datbuf);
  499.             if (*(mask+1) == 'D') mask++;
  500.             break;
  501.  
  502.         case 'H' :
  503.             intcat(hr, datbuf);
  504.             if (*(mask+1) == 'H') mask++;
  505.             break;
  506.  
  507.         case 'N' :
  508.             intcat(mn, datbuf);
  509.             if (*(mask+1) == 'N') mask++;
  510.             break;
  511.  
  512.         case 'S' :
  513.             intcat(sd, datbuf);
  514.             if (*(mask+1) == 'S') mask++;
  515.             break;
  516.        }
  517.         mask++;
  518.     }
  519.     strcat(datbuf, "\0");
  520.  
  521.     return(datbuf);
  522. }
  523.  
  524. /*
  525.  * today() returns todays date as the number of seconds since
  526.  * Jan 1. 1970 
  527. */
  528. unsigned long today()
  529. {
  530.     char tstr[15];
  531.  
  532.     todaystr(tstr);
  533.  
  534.     return (dstrtol(tstr, "YYYYMMDDHHNNSS"));
  535. }
  536.  
  537.  
  538. /*
  539.  * Eliminate this routine a.s.a.p
  540. */
  541. char    *fmt_date(dstr, mask)
  542. char    *dstr, *mask;
  543. {
  544.     static char datestr[15];
  545.     char *dp = datestr;
  546.  
  547.     todaystr(datestr);
  548.     dp += 2;
  549.     datestr[8] = '\0';
  550.  
  551.     return (dp);
  552. }
  553.  
  554.