home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 007.lha / settime / date.c < prev    next >
C/C++ Source or Header  |  1986-11-10  |  6KB  |  172 lines

  1. /* This function module provides three functions for manipulating dates:
  2. /*   LegalDays -- adjusts dates to reflect actual number of days per month
  3. /*   FromDosDate -- converts information provided via AmigaDos DateStamp to
  4. /*     MM, DD, YYYY, Hour, Minute, Second information
  5. /*   ToDosDate -- converts MM, DD, YYYY, Hour, Minute and Second data to
  6. /*     AmigaDos DateStamp format */
  7.  
  8. /* First we need to get various structure and DEFINE info... */
  9. #include <libraries/dos.h>
  10. #include <lattice/stdio.h>
  11.  
  12. /* Right now, AmigaDos' day zero is midnight, 1 January 1978 */
  13. #define STARTYEAR 1978
  14.  
  15. /* This keeps the compiler happy; DateStamp() is an AmigaDos function */
  16. void DateStamp();
  17.  
  18. /* This function takes three arguments and returns a 'legal' day number,
  19. /* defined as follows:
  20. /*   - the supplied day number if it is legitimate (e.g., March 31, or 
  21. /*     Feb 29 in a leap year)
  22. /*   - the last legitimate day of the specified month (e.g., Feb 28 if Feb 29
  23. /*     is supplied and Year is not a leap year 
  24. /*   - 1 if the supplied day number is less than or equal to zero
  25. /* January is month number 1. */
  26.  
  27. int LegalDays(Month,Day,Year)
  28.   int Month,Day,Year;
  29.   {
  30.    /* First make sure we have a positive date */
  31.    Day=Day<=0?1:Day;
  32.    /* What we do depends on what month we're in */
  33.    switch(Month)
  34.      {
  35.       /* February...*/
  36.       case 2:
  37.       /* Leap years.  Years divisible by 400, e.g., 2000, are not leap years */
  38.         if(Year%4==0 && Year%400!=0)
  39.           {
  40.            if(Day>29)
  41.              Day=29;
  42.           }
  43.       /* Normal years */
  44.         else
  45.           {
  46.            if(Day>28)
  47.              Day=28;
  48.           }
  49.         break;
  50.       /* Months with 30 days */
  51.       case 4:
  52.       case 6:
  53.       case 9:
  54.       case 11:
  55.         if(Day>30)
  56.           Day=30;
  57.         break;
  58.       /* Months with 31 days, which is everything else */
  59.       default:
  60.         if(Day>31)
  61.           Day=31;
  62.         break;
  63.      }
  64.    return(Day);
  65.   }
  66.  
  67. /* This function 'returns' pointers to integers specifying month, day, year,
  68. /* hour, minute and second as known by AmigaDos.  'Returns' is in quotes
  69. /* because we are doing call by reference (I think) here to get around
  70. /* C's limitation on only returning one value from a function.*/
  71.  
  72. void FromDosDate(DosPtr,MPtr,DPtr,YPtr,HPtr,MinPtr,SPtr)
  73.   struct DateStamp *DosPtr;
  74.   int *MPtr,*DPtr,*YPtr,*HPtr,*MinPtr,*SPtr;
  75.   {
  76.    int NumLeap,NumReg;
  77.    
  78.    /* Number of leap years between 1978 and current date.  Dos returns the
  79.    /* number of days between 1/1/1978 and current date.  What we do here is
  80.    /* calculate the number of 1461 day periods (4 years, including the leap)
  81.    /* since 1/1/1978.  We need to adjust for the fact that the first leap
  82.    /* after 1/1/1978 was only two years later, in 1980.*/
  83.    
  84.    NumLeap=(DosPtr->ds_Days+((STARTYEAR-1)%4)*365)/1461;
  85.  
  86.    /* The number of regular years is the number of days left after we subtract
  87.    /* 366 days for each leap year divided by 365 days */
  88.  
  89.    NumReg=(DosPtr->ds_Days-366*NumLeap)/365;
  90.  
  91.    /* If we've calculated a year beyond 2000 we need to adjust for the fact
  92.    /* that the year 2000 is not a leap year.*/
  93.    *YPtr=STARTYEAR+NumLeap+NumReg;
  94.    if(*YPtr>2000)
  95.      {
  96.       --NumLeap;
  97.       NumReg=(DosPtr->ds_Days-366*NumLeap)/365;
  98.       *YPtr=STARTYEAR+NumLeap+NumReg;
  99.      }
  100.      
  101.    /* Now we'll subtract out the number of days in each month of the year  
  102.    /* until we go nonpositive, at which point we'll have reached the correct
  103.    /* month.  To start, we need to reduce the day count by the number of days
  104.    /* in the years between 1/1/1978 and current time and reset the month 
  105.    /* counter.*/
  106.  
  107.    *DPtr=DosPtr->ds_Days-366*NumLeap-365*NumReg+1;
  108.    *MPtr=0;
  109.    while(*DPtr>0)
  110.      {
  111.       *DPtr-=LegalDays(*MPtr,99,*YPtr);
  112.       ++*MPtr;
  113.      }
  114.      
  115.    /* Actually, we've skipped to the end of the correct month, so add back
  116.    /* its number of days.*/
  117.  
  118.    *DPtr+=LegalDays(*MPtr-1,99,*YPtr);
  119.  
  120.    /* Now do seconds, minutes and hours. */
  121.    *SPtr=DosPtr->ds_Tick/TICKS_PER_SECOND;
  122.    *HPtr=DosPtr->ds_Minute/60;
  123.    *MinPtr=DosPtr->ds_Minute-*HPtr*60;
  124.   }
  125.   
  126. /* This function 'returns' a pointer to a DateStamp structure which is
  127. /* initialized according to user-supplied date and time information.  The
  128. /* returned pointer could have been returned by value, rather than by
  129. /* reference, but I wanted to keep the parameter list identical to 
  130. /* FromDosDate().*/
  131.  
  132. void ToDosDate(DosPtr,MPtr,DPtr,YPtr,HPtr,MinPtr,SPtr)
  133.   struct DateStamp *DosPtr;
  134.   int *MPtr,*DPtr,*YPtr,*HPtr,*MinPtr,*SPtr;
  135.   {
  136.    int NumLeap,Month=0;
  137.  
  138.    /* The number of leap years since 1/1/1978 is modulo 4 the number of years
  139.    /* between the current date and 1978.  However, we must adjust for the fact
  140.    /* that the first leap year after 1978 was only two years later in 1980.*/
  141.   
  142.    NumLeap=(*YPtr-STARTYEAR+(STARTYEAR-1)%4)/4;
  143.  
  144.    /* Once again, we adjust for 2000 not being a leap year */
  145.  
  146.    if(*YPtr>2000)
  147.      --NumLeap;
  148.  
  149.    /* The number of days since 1978 is, to begin with, 366 for every leap
  150.    /* year since then and 365 for every other year since then. */
  151.  
  152.    DosPtr->ds_Days=NumLeap*366+(*YPtr-STARTYEAR-NumLeap)*365;
  153.  
  154.    /* Now we add in the days for each month up to the month before the
  155.    /* current one.*/
  156.  
  157.    while(Month<(*MPtr-1))
  158.      {
  159.       DosPtr->ds_Days+=LegalDays(Month,99,*YPtr);
  160.       ++Month;
  161.      }
  162.  
  163.    /* Now add the day number within the current month.  We must subtract 1
  164.    /* because AmigaDos treats 1/1/1978 as 0 days away from its time zero.*/
  165.    DosPtr->ds_Days+=*DPtr-1;
  166.  
  167.    /* Convert seconds to ticks */
  168.    DosPtr->ds_Tick=*SPtr*TICKS_PER_SECOND;
  169.    /* Convert hours and minutes to minutes since midnight */
  170.    DosPtr->ds_Minute=*HPtr*60+*MinPtr;
  171.   }
  172.