home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / prog / source / dates2.lha / dates2.h next >
C/C++ Source or Header  |  1987-07-27  |  9KB  |  277 lines

  1. /******************************************************************************
  2.    dates2.h
  3.  
  4.    written by:  Kevin Rahe, Reliable Software
  5.  
  6.    special thanks to:
  7.         Jim Miles for help with the Macintosh
  8.  
  9. -------------------------------------------------------------------------------
  10.    Functions for date calculation and conversion.  Inspired by DATE.C from
  11.    John A. Hodgson, and a need for date calculation routines in a personal
  12.    project.  These routines should be error-free until the beginning of the
  13.    22nd century.  Please see the text above each routine for notes and comments
  14.    on usage.  I've spent much time developing and testing these routines.
  15.  
  16.    V2 NOTE:  date format changed from JULDATE structure to long integer.  This
  17.    makes the date functions easier to use and more logical, and the date is
  18.    easier to manipulate in this fashion.  It also allowed me to remove the
  19.    Date_Span function, as all you need to do is subtract one julian date from
  20.    another to get the # of days between them when they're in long integer
  21.    format.
  22.  
  23.    NOTE #2:  Please refer to the text above the function get_date() before
  24.    attempting to use this #include file.
  25.  
  26.  
  27.  
  28.     Functions:
  29.  
  30.     get_date() - returns the current system date in Julian (long integer)
  31.             form.
  32.     jultogreg() - converts a Julian date to Gregorian (MM-DD-YYYY) form.
  33.     gregtojul() - converts a Gregorian (MM-DD-YY or MM-DD-YYY) date to
  34.             Julian form.
  35.     dayofweek() - returns the day of week of a Julian date.
  36.     datestat() - returns information about a Julian date such as the day of
  37.             the month, month number, number of days in the month,
  38.             and year.
  39. ******************************************************************************/
  40.  
  41. /*  NOTE:  Your compiler (ie. Aztec) may not support strchr(), but it may
  42.     support index() instead, in which case de-comment the following line  */
  43.  
  44. /* #define strchr index */
  45.  
  46. #ifdef MAC
  47. #ifndef _OSUTIL
  48. #include <osutil.h>
  49. #endif
  50. #endif
  51.  
  52.  
  53. /*  # of days preceding each month  */
  54. short days_before[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  55. char *dayname[] = {"Fri","Sat","Sun", "Mon", "Tue", "Wed", "Thu"};
  56.  
  57. long gregtojul();    /**  declared here so it can be used in the Macintosh
  58.                 version of get_date()  **/
  59.  
  60. /******************************************************************************
  61.     FUNCTION:  get_date()
  62.  
  63.     This function should return the current system date.  It is obviously
  64.     going to be very system-dependent, so you may have to dig out your
  65.     tech. manuals and write this one yourself.  Amiga and Mac versions are
  66.     present here, one being used at compilation based on the constants
  67.     defined.  If AMIGA is defined, the Amiga version is used (Amiga Lattice
  68.     defines AMIGA - not sure about Manx).  If MAC is defined, then the
  69.     Macintosh version is used.  Note that they aren't mutually-exclusive.  If
  70.     both AMIGA *AND* MAC are defined, it will attempt to compile both versions,
  71.     resulting in an error.  If you write a version for a different system, by
  72.     all means add a #ifdef for it, add to this text explaining which constant
  73.     should be defined for its use, and of course, add your name to the
  74.     credits.
  75.  *****************************************************************************/
  76.  
  77. #ifdef AMIGA
  78. long get_date()
  79. {
  80.     long datestmp[3];
  81.  
  82.     DateStamp(&datestmp[0]);        /*  get the date  */
  83.     return (datestmp[0] + 722465);        /*  add 1 for Jan. 1, 1978  */
  84.         /**  there were 722464 days (since year 0) before Jan. 1, 1978.
  85.              Since Amiga's internal date format starts one day (24 hrs)
  86.              after the beginning of 1978, we have to add one day so we
  87.              can work on even-year boundaries.  In other words,
  88.              datestamp[0] is the # of days since 12:00am on Jan. 2,
  89.              1978.  **/
  90. }
  91. #endif
  92.  
  93. #ifdef MAC
  94. long get_date()
  95. {
  96.     DateTimeRec daterec;
  97.     char greg_date[11], string[6];
  98.  
  99.     GetTime(&daterec);
  100.     sprintf(greg_date, "%d", daterec.month);
  101.     strcat(greg_date, "-");
  102.     sprintf(string, "%d", daterec.day);
  103.     strcat(greg_date, string);        /*  add day to greg_date  */
  104.     strcat(greg_date, "-");
  105.     sprintf(string, "%d", daterec.year);
  106.     strcat(greg_date, string);        /*  add year to greg_date  */    
  107.     return(gregtojul(greg_date));
  108. }
  109. #endif
  110.  
  111.  
  112.  
  113. /******************************************************************************
  114.     This function accepts two arguments:  a string pointer and a long integer
  115.     (Julian date).  The routine will convert the Julian date to Gregorian
  116.     (MM-DD-YYYY) format.  The string pointer must point to a space at least
  117.     11 characters long.
  118. ******************************************************************************/
  119.  
  120. void jultogreg(greg_date, date)
  121. char *greg_date;
  122. long date;
  123. {
  124.     short year, month, day;
  125.     short julday, leapyears;
  126.     char string[6];
  127.  
  128.     year = date / 365;
  129.     julday = date % 365;
  130.     leapyears = year / 4;
  131.     julday -= leapyears;
  132.     while (julday < 1)
  133.     {
  134.         if (year % 4 == 0)
  135.             julday += 366;
  136.         else
  137.             julday += 365;
  138.         year -= 1;
  139.     }
  140.  
  141.     if ( !(year % 4) && julday > 60)  julday -= 1;
  142.         /*  subtract 1 if we are in a leap year & past Feb.  */
  143.  
  144.     for (month = 0; (days_before[month] < julday) && (month < 12); month++);
  145.         /*  find month  */
  146.  
  147.     day = julday - days_before[month-1];    /*  get current day  */
  148.     sprintf(greg_date, "%d", month);
  149.     strcat(greg_date, "-");
  150.     sprintf(string, "%d", day);
  151.     strcat(greg_date, string);        /*  add day to greg_date  */
  152.     strcat(greg_date, "-");
  153.     sprintf(string, "%d", year);
  154.     strcat(greg_date, string);        /*  add year to greg_date  */    
  155. }
  156.  
  157.  
  158. /******************************************************************************
  159.     The following function accepts one argument:  A pointer to a string.
  160.     It evaluates the string to determine if it is a valid date, then converts
  161.     it to Julian form which it returns as a long integer.  If the date is
  162.     invalid, a 0 will be returned.  It is not 100% accurate in its
  163.     date-checking, as it only checks to make sure that the date is not greater
  164.     than 31, without checking what the maximum value should be for that month.
  165.  
  166.     NOTE:  The Gregorian date passed to this routine must be delimited by
  167.            slashes '/' or dashes '-', and can be in MM-DD-YY or MM-DD-YYYY
  168.            form.  The century will be assumed to be the 20th if the form is
  169.        the former.  (no pun intended)
  170. ******************************************************************************/
  171.  
  172. long gregtojul(greg_date)
  173. char *greg_date;
  174. {
  175.     char *strchr();
  176.  
  177.     long month, day, year;
  178.     long date = 0;
  179.     char *stptr, *temptr;
  180.  
  181.     if ((stptr = strchr(greg_date,'-')) == 0)
  182.         stptr = strchr(greg_date,'/');        /* find delimiter */
  183.     if (stptr > 0)
  184.     {
  185.         sscanf(greg_date, "%ld", &month);    /* extract month */
  186.         if ( month >= 1 && month <= 12)
  187.         {
  188.             stptr += 1;            /*  skip delimiter  */
  189.             sscanf(stptr, "%ld", &day);
  190.             if ((temptr = strchr(stptr,'-')) == 0)
  191.                 temptr = strchr(stptr,'/');    /* 2nd delimiter */
  192.             if ( temptr > 0 && day >=1 && day <=31)
  193.             {
  194.                 stptr = temptr + 1;        /* skip delimiter */
  195.                 sscanf(stptr, "%ld", &year);
  196.                 if ( year > 0 )
  197.                 {
  198.                     if ( year < 100 )
  199.                         year += 1900;    /*  only 2 digits */
  200.                     date = year * 365 + year / 4;
  201.                     date += days_before[month - 1];
  202.                     date += day;
  203.                     if ( !(year % 4) && month > 2)    /* > Feb */
  204.                         date += 1;    /*  leap year */
  205.                 }
  206.             }
  207.         }
  208.     }
  209.     return(date);    
  210. }
  211.  
  212.  
  213. /******************************************************************************
  214.     The following function, supplied with a Julian date in long integer
  215.     format, will return a pointer to a 3-letter abbreviation of the day of the
  216.     week.
  217. ******************************************************************************/
  218.  
  219. char *dayofweek(date)
  220. long date;
  221. {
  222.     return(dayname[date % 7]);
  223. }
  224.  
  225.  
  226. /******************************************************************************
  227.     The following function accepts a Julian date in long integer form and 
  228.     returns a short integer that is the day of the month.  It also assigns
  229.     to num the number of days in the current month, to yr the current year,
  230.     and to mn the month #.  These 3 parameters are optional.  Pass them as
  231.     (short) NULL if you don't need them.
  232. ******************************************************************************/
  233.  
  234. short datestat(date, mn, yr, num)
  235. long date;
  236. short *mn, *yr, *num;
  237. {
  238.     short month, year, julday, leapyears;
  239.  
  240.     year = date / 365;
  241.     julday = date % 365;
  242.     leapyears = year / 4;
  243.     julday -= leapyears;
  244.  
  245.     while (julday < 1)
  246.     {
  247.         if (year % 4 == 0)
  248.             julday += 366;
  249.         else
  250.             julday += 365;
  251.         year -= 1;
  252.     }
  253.  
  254.     if (year % 4 == 0 && julday > 60) julday -= 1;
  255.     for (month = 0; (days_before[month] < julday) && (month < 12); month++);
  256.         /*  find month  */
  257.  
  258.     /****  Optional parameter assignments  ****/
  259.     if (num)    /*  not = NULL  */
  260.     {
  261.         if (month == 12)
  262.             *num = 31;
  263.         else
  264.             {
  265.             *num = days_before[month] - days_before[month - 1];
  266.             if (year % 4 == 0 && month == 2)
  267.                 *num += 1;
  268.             }
  269.     }
  270.     if (mn)
  271.         *mn = month;
  272.     if (yr)
  273.         *yr = year;
  274.  
  275.     return(julday - days_before[month-1]);        /**  date  **/
  276. }
  277.