home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / unix_c / calendrs / calcdate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-21  |  7.4 KB  |  397 lines

  1. /****************************************************************************
  2.  
  3. Program:    calcdate
  4.  
  5. Synopsis:    calcdate mmddyy { -o [-]offset | -d mmddyy }
  6.  
  7. Purpose:    Calculate the target date when given an initial date and an
  8.         offset in days, or the difference between two dates when
  9.         given two dates.
  10.  
  11. Options:    There are two options as listed below.  One or the other must
  12.         be entered.
  13.  
  14.         -o [-]offset    Allows the user to enter an offset (in days)
  15.                 and returns the initial date plus the offset.
  16.                 Negative offsets are permitted.
  17.  
  18.         -d mmddyy    Allows the user to enter a second date, and
  19.                 returns the difference between the two dates
  20.                 relative to the first date.
  21.  
  22. Author:        Gordon A. Runkle                ORI/Calculon
  23.         ...uunet!men2a!1solaria!gordon
  24.  
  25. *********************************************************************}********/
  26.  
  27. #include <stdio.h>
  28.  
  29. #define REG    0
  30. #define LEAP    1
  31. #define NEG    0
  32. #define POS    1
  33.  
  34. /* Version and usage information.  usage is used to print */
  35. char *version = "calcdate v2.01, 17 May 88, Gordon A. Runkle, ORI/Calculon\n";
  36. char *usage =   "Usage: calcdate mmddyy { -o [-]offset | -d mmddyy }\n\n";
  37. char *prog = "calcdate";
  38.  
  39. /* External variables for holding results of parsing of date values */
  40. int month_1, day_1, year_1, month_2, day_2, year_2;
  41.  
  42. /* no_days[0] is for reg yrs, no_days[1] is for leap yrs */
  43. int no_days[2][12] = 
  44.         {
  45.         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
  46.         { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
  47.         };
  48.  
  49.  
  50.  
  51. main(argc, argv)
  52. int argc;
  53. char *argv[];
  54. {
  55. extern char *version, *usage;
  56.  
  57.  
  58. /* Test for the proper number of args. */
  59. if (argc != 4)
  60.     {
  61.     fprintf(stderr, version);
  62.     fprintf(stderr, usage);
  63.     exit(-1);
  64.     }
  65.  
  66. /* Tests first date for valid format and contents */
  67. if (valid_date(argv[1], 1) != 0)
  68.     exit(-1);           /* The error message is in the function */
  69.  
  70. /* Test for an option flag in the second arg */
  71. if (argv[2][0] != '-')
  72.     {
  73.     fprintf(stderr, usage);
  74.     exit(-1);
  75.     }
  76.  
  77. /* Make a decision based on the option */
  78. if (argv[2][1] == 'o')
  79.     {
  80.     if (off_calc(argv[3]) != 0)
  81.         exit(-1);
  82.     }
  83. else if (argv[2][1] == 'd')
  84.     {
  85.     if (valid_date(argv[3], 2) != 0)
  86.         exit(-1);
  87.     else
  88.         {
  89.         if (dates_calc() != 0)    /* no arg is needed - valid_date */
  90.             exit (-1);    /* takes care of the dates */
  91.         }
  92.     }
  93. else
  94.     {
  95.     fprintf(stderr, usage);
  96.     exit(-1);
  97.     }
  98.  
  99. return(0);
  100. }
  101.  
  102.  
  103. /***************************************/
  104. valid_date(tst_date, date_flag)
  105. char tst_date[];
  106. int date_flag;
  107. {
  108. extern int month_1, day_1, year_1;
  109. extern int month_2, day_2, year_2;
  110. extern char *prog;
  111.  
  112. int i, leap_flag, month, day, year;
  113.  
  114.  
  115. if (strlen(tst_date) != 6)
  116.     {
  117.     fprintf(stderr, "%s: date must be entered as mmddyy\n", prog);
  118.     return(-1);
  119.     }
  120.  
  121. for (i = 0; i < 6; i++)
  122.     if (tst_date[i] < '0' || tst_date[i] > '9')
  123.         {
  124.         fprintf(stderr, "%s: date must be entered as mmddyy\n", prog);
  125.         return(-1);
  126.         }
  127.  
  128.  
  129. sscanf(tst_date, "%2d%2d%2d", &month, &day, &year);
  130.  
  131. if (month > 12)
  132.     {
  133.     fprintf(stderr, "%s: invalid month %d\n", prog, month);
  134.     return(-1);
  135.     }
  136.  
  137. if (year % 4 == 0)
  138.     leap_flag = LEAP;
  139.   else
  140.     leap_flag = REG;
  141.  
  142. if (day > no_days[leap_flag][month - 1])
  143.     {
  144.     fprintf(stderr, "%s: invalid day %d\n", prog, day);
  145.     return(-1);
  146.     }
  147.  
  148. /* This determines where our carefully-checked values are stored */
  149. if (date_flag == 1)
  150.     {
  151.     day_1 = day;
  152.     month_1 = month;
  153.     year_1 = year;
  154.     }
  155. else if (date_flag == 2)
  156.     {
  157.     day_2 = day;
  158.     month_2 = month;
  159.     year_2 = year;
  160.     }
  161. else
  162.     {
  163.     fprintf(stderr, "%s: unexpected error assigning date values\n", prog);
  164.     return(-1);
  165.     }
  166.  
  167. return(0);
  168. }
  169.         
  170.  
  171. /***************************************/
  172. off_calc(offset)
  173. char offset[];
  174. {
  175. extern int no_days[2][12];
  176. extern int month_1, day_1, year_1;
  177. extern char *prog;
  178.  
  179. int atoi();
  180. int i_offset, n_month, n_day, n_year, month_bal;
  181. int i, leap_flag;
  182.  
  183. char newdate[7];
  184.  
  185.  
  186. /* This checks for a valid offset value.  Negative values are allowed
  187.    and checked for.  It stops at the first null. */
  188. for (i = 0; i < 4; i++)
  189.     {
  190.     if (offset[i] == '\0')
  191.         break;
  192.  
  193.     if (i == 0 && offset[i] == '-')
  194.         continue;
  195.  
  196.     if (offset[i] < '0' || offset[i] > '9')
  197.         {
  198.         fprintf(stderr, "%s: offset must be entered as an integer\n", prog);
  199.         exit(-1);
  200.         }
  201.     }
  202.  
  203. i_offset = atoi(offset);
  204.  
  205. /* This is the beginning of the neat stuff.  I hope it works! */
  206. /* leap year is when =>>  year % 4 == 0  */
  207.  
  208. n_year = year_1;    /* the *_1 is used, as this is the value of the */
  209. n_month = month_1;    /* first date entered */
  210. n_day = day_1;
  211.  
  212. if (i_offset >= 0)
  213.     {
  214.     while (i_offset > 0)
  215.         {
  216.         if (n_year % 4 == 0)
  217.             leap_flag = LEAP;
  218.           else
  219.             leap_flag = REG;
  220.  
  221.         month_bal = no_days[leap_flag][n_month - 1] - n_day;
  222.  
  223.         if (i_offset > month_bal)
  224.             {
  225.             i_offset -= month_bal;
  226.             n_month++;
  227.  
  228.             if (n_month > 12)
  229.                 {
  230.                 n_month = 1;
  231.                 n_year++;
  232.  
  233.                 if (n_year > 99)
  234.                     n_year = 0;
  235.                 }
  236.  
  237.             n_day = 0;
  238.             }
  239.           else
  240.             {
  241.             n_day += i_offset;
  242.             i_offset = 0;
  243.             }
  244.         }
  245.     }
  246. else
  247.     {
  248.     while (i_offset < 0)        /* this loop processes neg offsets */
  249.         {
  250.         if (n_year % 4 == 0)
  251.             leap_flag = LEAP;
  252.           else
  253.             leap_flag = REG;
  254.  
  255.         month_bal = n_day - 1;
  256.  
  257.         if (abs(i_offset) > month_bal)
  258.             {
  259.             i_offset += month_bal;
  260.             n_month--;
  261.  
  262.             if (n_month < 1)
  263.                 {
  264.                 n_month = 12;
  265.                 n_year--;
  266.  
  267.                 if (n_year < 0)
  268.                     n_year = 99;
  269.                 }
  270.  
  271.             n_day = no_days[leap_flag][n_month - 1] + 1;
  272.             }
  273.           else
  274.             {
  275.             n_day += i_offset;
  276.             i_offset = 0;
  277.             }
  278.         }
  279.     }
  280.  
  281. sprintf(newdate, "%2d%2d%2d", n_month, n_day, n_year);
  282.  
  283. for (i = 0; i < 7; i++)
  284.     if (newdate[i] == ' ')
  285.         newdate[i] = '0';
  286.  
  287. fprintf(stdout, "%s\n", newdate);
  288.  
  289. return(0);
  290. }
  291.  
  292.  
  293. /***************************************/
  294. dates_calc()
  295. {
  296. extern int no_days[2][12];
  297. extern int month_1, day_1, year_1, month_2, day_2, year_2;
  298.  
  299. int first_rec = 0, curr_offset = 0;
  300. int leap_flag, sign_flag;
  301. int start_day, start_month, start_year, end_day, end_month, end_year;
  302.  
  303.  
  304. /****
  305.     This section determines which date is later, so that the program
  306.     may evaluate the earlier one first.  There is a flag set to indicate
  307.     what sign the end result should have based on whether the first date
  308.     entered is earlier or later than the second.
  309. ****/
  310.  
  311. /* set the default sign */
  312. sign_flag = NEG;
  313.  
  314. if (year_1 < year_2)
  315.     sign_flag = POS;
  316.   else
  317.     if (year_1 == year_2 && month_1 < month_2)
  318.         sign_flag = POS;
  319.       else
  320.         if (year_1 == year_2 && month_1 == month_2 && day_1 < day_2)
  321.             sign_flag = POS;
  322.  
  323. /* This makes the earlier date be set to start_* */
  324. if (sign_flag == POS)
  325.     {
  326.     start_day = day_1;
  327.     start_month = month_1;
  328.     start_year = year_1;
  329.     end_day = day_2;
  330.     end_month = month_2;
  331.     end_year = year_2;
  332.     }
  333.   else
  334.     {
  335.     start_day = day_2;
  336.     start_month = month_2;
  337.     start_year = year_2;
  338.     end_day = day_1;
  339.     end_month = month_1;
  340.     end_year = year_1;
  341.     }
  342.  
  343. /* The calculations below keep incrementing curr_offset and start_* until
  344.    start_* == end_*  */
  345.  
  346. for (;;)
  347.     {
  348.     if (start_year % 4 == 0)
  349.         leap_flag = LEAP;
  350.       else
  351.         leap_flag = REG;
  352.  
  353.     if (first_rec == 0)
  354.         {
  355.         /* This is for when the month and year start out the same, and 
  356.            the user just wants the days (ie.  051688 052688 */
  357.         if (start_month == end_month && start_year == end_year)
  358.             {
  359.             curr_offset = end_day - start_day;
  360.             break;
  361.             }
  362.  
  363.         curr_offset = no_days[leap_flag][start_month - 1] - start_day;
  364.         first_rec = 1;
  365.         }
  366.       else if (start_month == end_month && start_year == end_year)
  367.         {
  368.         curr_offset += end_day;
  369.         break;            /* This is the end of it */
  370.         }
  371.       else
  372.         curr_offset += no_days[leap_flag][start_month - 1];
  373.  
  374.  
  375.     start_month++;
  376.  
  377.     if (start_month > 12)
  378.         {
  379.         start_month = 1;
  380.         start_year++;
  381.  
  382.         if (start_year > 99)
  383.             start_year = 0;
  384.         }
  385.     }
  386.  
  387. if (sign_flag == NEG)
  388.     curr_offset = -curr_offset;
  389.  
  390. fprintf(stdout, "%d\n", curr_offset);
  391.  
  392. return(0);
  393. }
  394. /* end of calcdate.c  -=gordon=- */
  395.  
  396.  
  397.