Listing 6 Extended functions

/*********************************************************/
/*            Extended Date Functions                    */
/*                                                       */
/*            (c) Copyright 1993 by Stan Milam           */
/*********************************************************/

date_t to_date( char *string, int type ) {

   date_t rv;
   struct dt dt = { 0, 0, 0, 0, 0, 0 };
   int    len, i, mday, yday, month, year;
   char   wrkbuf[161], **months = full_month;

   year = month = yday = mday = 0;
   switch ( type ) {

      case DDMMCCYY :
         i = sscanf(string, "%2d%2d%4d", &mday, &month,
                  &year);
         if ( i != 3 ) return (date_t) -1L;
         month--;
         break;
      case MMDDCCYY :
         i = sscanf(string, "%2d%2d%4d", &month, &mday,
                  &year);
         if ( i != 3 ) return (date_t) -1L;
         month--;
         break;

      case GREGDATE :
         i = sscanf(string, "%d%*c%d%*c%d", &month, &mday,
                  &year);
         if ( i != 3 ) return (date_t) -1L;
         month--;
         break;

      case MILDATE :
         i = sscanf(string,"%d%*c%d%*c%d",&mday, &month, &year);
         if ( i != 3) return (date_t) -1L;
         month--;
         break;

      case SPELLDATE :
         i = sscanf(string, "%d%*c%3c%*c%d", &mday, wrkbuf,
                  &year);
         if (i != 3) return (date_t) -1L;
         for (month = 0, len = 3; month < 12; month++) {

            if ( compare( wrkbuf, months[month], len ) == 0 )
               break;
         }
         if ( month == 12 ) return (date_t) -1;
         break;

      case JULDATE :
         len = strlen( string );
         if ( len == 5 || len == 7 ) {
            len = 3;
            sprintf(wrkbuf, "%%%dd%%%dd", len, 3);
            i = sscanf(string, wrkbuf, &year, &yday);
            if ( i != 2 ) return (date_t) -1L;
            yday--;
         }
         else return (date_t) -1L;
         break;

      case SYSDATE :
         len = strlen( string );
         if ( len == 8 || len == 6 ) {
            len -= 4;
            sprintf(wrkbuf. "%%%dd%%%dd%%%dd", len, 2, 2);
            i = sscanf(string, wrkbuf, &year, &month, &mday);
            if ( i != 3 ) return (date_t) -1L;
            month--;
         }
         else return ( date_t ) -1L;
         break;

      default :
         return (date_t) -1L;

   }

   /***********************************************************/
   /* If the year is a two digit year, adjust for the century */
   /* change. Anything less than 80 is considered to be in    */
   /* 21st century.                                           */
   /***********************************************************/

   if ( year < 100 )
      year += year < 80 ? 2000 : 1900;

   /***********************************************************/
   /* Setup and call mkdate() to get the sequential day number*/
   /***********************************************************/

   dt.dt_year = year;
   db.dt_mday = mday;
   dt.dt_yday = yday;
   dt.dt_month= month;
   rv = mkdate( &dt );
   return rv;
}

char *date_to_string(char *buffer, date_t day, int type) {

   int size;
   struct dt *dt;
   char wrkbuf[25], *format;

   wrkbuf[0] = '\0';
   size   = sizeof(wrkbuf);

   switch ( type ) {

      case GREGDATE  :
         format = "%x";
         break;

      case MILDATE   :
         format = "%d/%m/%Y";
         break;

      case SPELLDATE :
         format = "%d-%b-%Y";
         break;

      case JULDATE  :
         format = "%Y%j";
         break;

      case SYSDATE  :
         format = "%Y%m%d";
         break;

      case DDMMCCYY :
         format = "%d%m%Y";
         break;

      case MMDDCCYY  :
         format = "%m%d%Y";
         break;

      default       :
         format = NULL;
   }

   if ( format != NULL ) {
      if (( dt = localdate( &day ))  != NULL )
         strfdate(wrkbuf, size, format, dt);
   }
   return (strcpy(buffer, wrkbuf));
}

char *to_char(char *buffer, date_t day, int type) {

   return date_to_string(buffer, day, type);
}

date_t next_day_of_week( date_t value, int day ) {

   date_t rv;
   struct dt *dt;

   /***********************************************************/
   /* See if we have a valid date value.                      */
   /***********************************************************/

   if ((dt = localdate( &value )) == NULL )
      rv = (date_t) -1L;
   else if ( day < SUNDAY || day > SATURDAY )
      rv = (date_t) -1L;
   else {
      /*******************************************************/
      /* Compute how many days until the next specifed day of*/
      /* the week. Make sure we are within our limits too.   */
      ********************************************************/
      rv = (date_t) 7 - dt->dt_wday + day;
      if ( rv > (date_t) 7) rv -= (date_t) 7;
      rv = rv + value > MAXDATE ? (date_t) -1L : rv + value;
   }

   return rv;
}

date_t previous_day_of_week( date_t value, int day ) {

   date_t rv;
   struct dt *dt;

   /***********************************************************/
   /* Check for a valid date value.                           */
   ************************************************************/

   if ((dt = localdate( &value )) == NULL)
      rv = (date_t) -1L;
   else if ( day < SUNDAY || day > SATURDAY )
      rv = (date_t) -1L;
   else {
      ********************************************************/
      /* Compute the date value for previous specified day   */
      /* and do sanity check.                                */
      ********************************************************/
      rv = (date_t) day - dt->dt_wday;
      if ( rv > = (date_t) 0 ) rv -= (date_t) 7L;
      rv += value;
      if ( rv < (date_t) 1L ) rv = (date_t) -1L;
   }

   return rv;
}

date_t last_day_of_month( date_t value ) {

   date_t rv;
   struct dt *dt = localdate( &value );

   /***********************************************************/
   /* See if date value was valid.                            */
   /***********************************************************/

   if ( dt == NULL )
      rv = (date_t) -1L;
   else {
      /*******************************************************/
      /* Determine last day of the month, compute the        */
      /* difference and add to the date value.               */
      /*******************************************************/
      rv = month_table[ dt -> dt_month ];
      if ( dt -> dt_month == 1 ) rv += dt -> dt_leap_year;
      rv = rv - dt -> dt_mday + value;
   }
   return rv;

}

date_t first_day_of_month( date_t value ) {

   date_t rv;
   struct dt *dt = localdate( &value );
   rv = ( dt == NULL ) ? -1L : (date_t) 1 - dt -> dt_mday + value;
   return rv;
}

date_t compute_date(date_t value, int years, int months, int weeks, int days) {

   date_t rv;                         /* Return value */
   int ld1, ld2;                      /* Last days of months */
   struct dt *wrk;                    /* A date structure */

   wrk = localdate( &value );         /* Get a date structure */
   if ( wrk == NULL ) return (date_t) -1L;

   /***********************************************************/
   /* Go ahead and compute the weeks and days.                */
   /***********************************************************/

   rv = (weeks * 7) + days;

   /***********************************************************/
   /* Now compute the months. We may have to adjust the years */
   /* value.                                                  */
   /***********************************************************/

   if ( months ) {
      if (abs(months) > 11 ) {
         years += months / 12;
         months = months % 12;
      }

      /***********************************************************/
      /* Now compute the target month and handle wrap-around.*/
      /***********************************************************/

      months += wrk -> dt_month;
      if ( months <0 ) {
         months += 12;
         years += -1;
      }
      else if ( months > 11 ) {
         months -= 12;
         years += 1;
      }

      /***********************************************************/
      /* Now we have to make adjustment if we are on the last    */
      /* day of the month. For instance if date is 31 May        */
      /* and we add 1 month the result should be 30 June.        */
      /***********************************************************/

      ld1 = month_table[wrk ->dt_month];
      if ( wrk->dt_month == 1 ) ld1 += wrk->dt_leap_year;
      if ( wrk->dt_mday == ld1 ) {
         ld2 = month_table[months];
         if ( months == 1 ) ld2 +=
            is_it_a_leap_year(years + wrk->dt_year);
         if (1d1 > ld2 ) wrk->dt_mday = ld2;
      }
      wrk->dt_month = months;
   }

   wrk->dt_year += years;

   /***********************************************************/
   /* The following is a fixup in case we started on Feb 29   */
   /* and we are computing into another year.                 */
   /***********************************************************/

   ld1 = month_table[wrk->dt_month];
   if ( wrk->dt_month == 1 ) ld1 +=
      is_it_a_leap_year(wrk->dt_year);
   if (wrk->dt_mday > ld1) wrk->dt_mday = ld1;

   /***********************************************************/
   /* Call mkdate( ) to do the work.                           */
   /***********************************************************/

   rv += mkdate( wrk );
   return rv;
}
/* End of File */