A dateplus AWK program is also available.
              
           static char SccsId[] = "@(#)dateplus.c 2.3 03/19/10";
           /*--------------------------------------------------------------------*/
           /*                            dateplus.c                              */
           /*--------------------------------------------------------------------*/
           /*                                                                    */
           /*  Copyright (c) 1995-2010 by Bob Orlando.  All rights reserved.     */
           /*                                                                    */
           /*  Permission to use, copy, modify and distribute this software      */
           /*  and its documentation for any purpose and without fee is hereby   */
           /*  granted, provided that the above copyright notice appear in all   */
           /*  copies, and that both the copyright notice and this permission    */
           /*  notice appear in supporting documentation, and that the name of   */
           /*  Bob Orlando not be used in advertising or publicity pertaining    */
           /*  to distribution of the software without specific, written prior   */
           /*  permission.  Bob Orlando makes no representations about the       */
           /*  suitability of this software for any purpose.  It is provided     */
           /*  "as is" without express or implied warranty.                      */
           /*                                                                    */
           /*  BOB ORLANDO DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS          */
           /*  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY     */
           /*  AND FITNESS.  IN NO EVENT SHALL BOB ORLANDO BE LIABLE FOR ANY     */
           /*  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES         */
           /*  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER   */
           /*  IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,    */
           /*  ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF    */
           /*  THIS SOFTWARE.                                                    */
           /*                                                                    */
           /* ------------------------------------------------------------------ */
           /*          Program documentation and notes located in the            */
           /*                   show_documentation() function.                   */
           /*--------------------------------------------------------------------*/

           /*====================================================================*/
           /*                       D E C L A R A T I O N S                      */
           /*====================================================================*/
           #include <stdio.h>
           #include <stdlib.h>       /* abs, atoi, exit */
           #include <string.h>       /* strlen, strncpy */
           #include <ctype.h>        /* isdigit         */
           #include <time.h>         /* time routines   */

           #define H24SSS 86400      /* Number of seconds in a day */
           #define FALSE  0
           #define TRUE   1
           #define STRNCPY(to, from, n) {strncpy(to, from, n);to[n] = 0x0;}

           /*====================================================================*/
           /*                         P R O T O T Y P E S                        */
           /*====================================================================*/
           long calc_basedate(int yyyy, int mm, int dd);
           int  leap_year(int yyyy);
           void show_documentation(char *progname);
           int  this_years_days(int yyyy);
           void usage(char *progname);
           void validate_mm_dd(int mm, int dd);

           /*====================================================================*/
           /*                  G L O B A L    V A R I A B L E S                  */
           /*====================================================================*/
           int  yyyy;
           int  ddddd;
           const char *months[] = /* Month names */
                 {
                   "January",  "February",  "March"    ,
                   "April"  ,  "May"     ,  "June"     ,
                   "July"   ,  "August"  ,  "September",
                   "October",  "November",  "December"
                 };

           /*====================================================================*/
           /*                              M A I N                               */
           /*====================================================================*/
           main(int argc, char *argv[])
           {
             int julian_days[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
             int julian_leap[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
             int *accum_days = &julian_days[0]; /* julian_days address to ptr */

           /*--------------------------------------------------------------------*/
           /* Variables for weekday calculations                                 */
           /*                                                                    */
             const char *weekdays_abbr[]
               = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
             const char *weekdays_long[]
               = {"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"};
             int weekday_wanted      = FALSE;              /* Initially false.   */
             int weekday_abbr_wanted = FALSE;              /*    ''      ''      */
             int weekday_long_wanted = FALSE;              /*    ''      ''      */
           /*                                                                    */
           /*--------------------------------------------------------------------*/

             int  i, n; /* Counters */
             int  mm;
             int  dd;
             int  since_1970          = 0; /* Option flag */
             int  Since_yyyymmdd      = 0; /*   ''    ''  */
             int  since_yyyymmdd      = 0; /*   ''    ''  */
             int  basedate            = 0;

             long ddddd               = 0;
             long ddddd_yyyy          = 0;
             int  iterations          = 1;
             int  yyyymmdd_to_jjj     = 0;
             int  yyyyjjj_to_yyyymmdd = 0;

             int  adj_days            = 0;
             int  abs_adj             = 0;
             int  valid_opt           = FALSE; /* Pessimistic by nature I am. */

             char yyyymmdd[9];
             char four_char[5];
             char two_char[3];
             char opt = 0x0;                /* Command line option            */
             char *p_argv      = argv[0];   /* Instantiate pointer to argv[0] */
             char progname[64] = {0x0};

             /*---------------------------------------------------------------*/
             /* Begin by placing today's date into yyyymmdd string variable.  */
             /*---------------------------------------------------------------*/
             struct tm *time_now;
             time_t secs_now;
             time(&secs_now); /* Convert calendar time to local */
             time_now = localtime(&secs_now);
             strftime(yyyymmdd,9,"%Y""%m""%d",time_now);

             /*-------------------------------------------------*/
             /* Parse today's date and calc its ddddd value.    */
             /*-------------------------------------------------*/
             STRNCPY(four_char,  yyyymmdd,       4); yyyy = atoi(four_char);
             STRNCPY(two_char, (&yyyymmdd[0]+4), 2); mm   = atoi(two_char );
             STRNCPY(two_char, (&yyyymmdd[0]+6), 2); dd   = atoi(two_char );
             ddddd = calc_basedate(yyyy, mm, dd);

             /*---------------------------------------------------------*/
             /* Lowercase argv[0] and assign the basename to progname.  */
             /*---------------------------------------------------------*/
             for (n=i=0; *(p_argv+n); *(p_argv+n)=tolower(*(p_argv+n)), n++)
               if ((*(p_argv+n) == '/') || (*(p_argv+n) == '\\'))
                 i = n + 1;

             strcpy(progname,argv[0]+i); /* Portion that follows last / (or \). */

             /*-----------------------------------------------------------------*/
             /* If user supplies no args (argc == 1) then show usage and exit.  */
             /* Else, see if they gave us options.  If so, process accordingly. */
             /*-----------------------------------------------------------------*/
             if (argc == 1)        /* This zero-based numbering drives me nuts! */
             {
               usage(progname);
               exit(7);
             }

             /*-------------------------------------*/
             /* If we have iterations, validate'em. */
             /*-------------------------------------*/
             if (argc > 3)
             {
               p_argv = argv[3]; /* Instantiate pointer to argv[3] */
               for (n=0; *(p_argv+n); n++)
               {
                 if (isdigit(*(p_argv+n)))
                   continue; /* A-OK */
                 fprintf(stderr,"\nIterations (%s) invalid: must be integer.\n",
                   argv[3]);
                 fprintf(stderr,"%s terminated.\a\n", progname);
                 exit(8);
               }
               iterations = atoi(argv[3]);
             }

             /*------------------------------------------------------------*/
             /* If the first argument's leading character is a hyphen      */
             /* (indicating potential option), then see is it is, indeed   */
             /* an option, or simply a negative adjustment value.          */
             /*------------------------------------------------------------*/
             if ((opt = *argv[1]) == '-')
             {
               switch (opt = *(argv[1]+1))
               {
                 case 'h': /* User wants short help       */
                       usage(progname);
                       exit(9);
                       break;

                 case 'H': /* User wants detailed help    */
                       show_documentation(progname);
                       exit(10);
                       break;

                 case 'y': /* User wants yesterday's date */
                       if (argc > 2)
                       {
                         fprintf(stderr,"No other arguments allowed with -y "
                           "(yesterday) option.\n",argv[1]);
                         fprintf(stderr,"%s terminated.\a\n", progname);
                         exit(11);
                       }

                       secs_now -= H24SSS;
                       time_now = localtime(&secs_now);
                       strftime(yyyymmdd, 9, "%Y""%m""%d", time_now);
                       printf("%s\n", yyyymmdd);
                       exit(0);
                       break;

                 case 't': /* User wants tomorrow's date  */
                       if (argc > 2)
                       {
                         fprintf(stderr,"No other arguments allowed with -t "
                           "(tomorrow) option.\n");
                         fprintf(stderr,"%s terminated.\a\n", progname);
                         exit(12);
                       }
                       secs_now += H24SSS;
                       time_now = localtime(&secs_now);
                       strftime(yyyymmdd, 9, "%Y""%m""%d", time_now);
                       printf("%s\n", yyyymmdd);
                       exit(0);
                       break;

                 case 'S': /* Days since date (unsigned) */
                       since_1970     = 0;
                       Since_yyyymmdd = 1; /* Capitalized variable name */
                       basedate       = 0;
                       valid_opt      = TRUE;
                       break;

                 case 's': /* Days since date */
                       since_1970     = 0;
                       since_yyyymmdd = 1;
                       basedate       = 0;
                       valid_opt      = TRUE;
                       break;

                 case 'j': /* Gregorian to Julian */
                       if (argc > 2)
                       {
                         if (strlen(argv[2]) != 8)
                         {
                           fprintf(stderr,
                             "Date (%s) must be in the form: yyyymmdd\n",
                               argv[2]);
                           fprintf(stderr,"%s terminated.\a\n", progname);
                           exit(13);
                         }
                         strcpy(yyyymmdd,argv[2]);
                       }
                       yyyymmdd_to_jjj = TRUE;
                       iterations      = 1; /* Not used with Julian */
                       adj_days        = 0;
                       valid_opt       = TRUE;
                       break;

                 case 'J': /* Julian to Gregorian with yyyy */
                       if (argc < 3 || strlen(argv[2]) != 7)
                       {
                         fprintf(stderr,
                           "Julian-to-Gregorian conversion requires "
                           "yyyyJJJ julian date.\n");
                         fprintf(stderr,"%s terminated.\a\n", progname);
                         exit(14);
                       }

                       strcpy(yyyymmdd,argv[2]);
                       STRNCPY(     four_char, (&yyyymmdd[0]+4), 3);
                       ddddd = atoi(four_char);
                       STRNCPY(     four_char,   yyyymmdd, 4);
                       yyyy  = atoi(four_char);

                       if (leap_year(yyyy))
                         accum_days = &julian_leap[0];
                       /*-----------------------------------------------------*/
                       /* Rip through accum_days until we find one that is    */
                       /* too big.  Then use the preceding one as the correct */
                       /* month number and decrement ddddd by the month's     */
                       /* julian days.                                        */
                       /*-----------------------------------------------------*/
                       for (mm=1; mm<=12; mm++)
                       {
                         if ((ddddd - accum_days[mm]) <= 0)
                         {
                            ddddd -= accum_days[mm-1];
                            break;
                         }
                       }
                       printf("%04d%02d%02d\n", yyyy,mm,ddddd);
                       exit(0);
                       break;

                 case 'w': /* Weekday option (returns weekday abbreviation) */
                       weekday_wanted      = TRUE; /* Was false, now true   */
                       weekday_abbr_wanted = TRUE; /* Was false, now true   */
                       iterations          = 1;    /* Not used with Weekday */
                       adj_days            = 0;
                       valid_opt           = TRUE;
                       break;

                 case 'W': /* Weekday option (returns weekday)              */
                       weekday_wanted      = TRUE; /* Was false, now true   */
                       weekday_long_wanted = TRUE; /* Was false, now true   */
                       iterations          = 1;    /* Not used with Weekday */
                       adj_days            = 0;
                       valid_opt           = TRUE;
                       break;

                 case 'b': /* Basedate from Jan. 1, 0001  */
                       since_1970          = 0;
                       since_yyyymmdd      = 0;
                       basedate            = 1;
                       valid_opt           = TRUE;
                       break;

                 case 'u': /* Basedate from Jan. 1, 1970  */
                       since_1970          = 1;
                       since_yyyymmdd      = 0;
                       basedate            = 0;
                       valid_opt           = TRUE;
                       break;

                 default:
                       if (isdigit(opt))
                       {
                         valid_opt = TRUE;
                         /*--------------------------------------------------*/
                         /* Ensure that adjustment days are, indeed, numeric */
                         /* numeric (before the atoi).                       */
                         /*--------------------------------------------------*/
                         p_argv = argv[1];             /* Pointer to argv[1] */
                         for (n=0; *(p_argv+n); n++)
                         {
                           if (isdigit(*(p_argv+n)))
                             continue; /* A-OK */
                           if (n==0 && (*(p_argv+n)=='-' || *(p_argv+n)=='+'))
                             continue; /* A-OK */
                           fprintf(stderr,
                             "\nAdj days (%s) NOT [+-]numeric.\n", argv[0]);
                           fprintf(stderr,"%s terminated.\a\n", progname);
                           exit(15);
                         }

                         /*--------------------------------------------------*/
                         /* Now, convert 1st arg (now argv[0]) to adj days.  */
                         /*--------------------------------------------------*/
                         adj_days = atoi(argv[1]);
                       }
                       break;
               } /* switch (opt = *(argv[1]+1)) */
             } /* if ((opt = *argv[1]) == '-') */
             else if (isdigit(opt) || opt == '+')
             {
               p_argv = argv[1]; /* Instantiate pointer to argv[1] */
               for (n=0; *(p_argv+n); n++)
               {
                 if (isdigit(*(p_argv+n)))
                   continue; /* A-OK */
                 if (n==0 && *(p_argv+n)=='+')
                   continue; /* A-OK */
                 fprintf(stderr,"\nAdjust-days (%s) NOT numeric!\n", argv[1]);
                 fprintf(stderr,"%s terminated.\a\n", progname);
                 exit(16);
               }
               adj_days = atoi(argv[1]);
               valid_opt = TRUE;
             } /* else if (isdigit(opt) || opt == '+')  */

             /*---------------------------------------*/
             /* Anything else is an invalid argument. */
             /*---------------------------------------*/
             if (valid_opt != TRUE)
             {
               printf("%s: Invalid argument '%s'!\a\n\n", argv[0], argv[1]);
               usage(progname);
               exit(17);
             }

             /*-----------------------------------------------------------------*/
             /* If we have a yyyymmdd date argument, then do a basic validation */
             /* (must be 8 digits).  If it looks OK, assign it to yyyymmdd.     */
             /*-----------------------------------------------------------------*/
             if (argc > 2)
             {
               if (strlen(argv[2]) != 8)
               {
                 fprintf(stderr,
                   "Date (%s) must be in the form: yyyymmdd!\n",
                      argv[2]);
                 fprintf(stderr,"%s terminated.\a\n", argv[0]);
                 exit(18);
               }
               /*------------------------------------------------------------*/
               /* Using a pointer to 1st character in argv[2], scan the arg  */
               /* (character-by-character) confirming that each is a digit.  */
               /* If any nonnumeric value, then fuss at the user and exit.   */
               /*------------------------------------------------------------*/
               p_argv = argv[2];                       /* Pointer to argv[2] */
               for (n=0; *(p_argv+n); n++)
               {
                 if (isdigit(*(p_argv+n)))
                   continue; /* A-OK */
                 fprintf(stderr,"\nDate (%s) NOT numeric!\n", argv[0]);
                 fprintf(stderr,"%s terminated.\a\n", argv[0]);
                 exit(19);
               }
               strcpy(yyyymmdd,argv[2]); /* OK, assign argv[2] to yyyymmdd */
             } /* if (argc > 2) */

             /*----------------------------------------------------------------*/
             /* Are we returning days since a date or base dates?              */
             /*----------------------------------------------------------------*/
             if (since_yyyymmdd || since_1970 || argc > 2)
             {
               STRNCPY(four_char,  yyyymmdd,       4); yyyy = atoi(four_char);
               STRNCPY(two_char, (&yyyymmdd[0]+4), 2); mm   = atoi(two_char );
               STRNCPY(two_char, (&yyyymmdd[0]+6), 2); dd   = atoi(two_char );
               validate_mm_dd(mm, dd);
             }

             if (since_yyyymmdd || Since_yyyymmdd)  /* -S|s options */
             {
               ddddd_yyyy = calc_basedate(yyyy, mm, dd);
               ddddd -= ddddd_yyyy;
               printf("%d\n", ((Since_yyyymmdd) ? labs(ddddd) : ddddd));
               exit(0);
             }
             else if (since_1970) /* -u option */
             {
               ddddd = calc_basedate(yyyy, mm, dd);
               if (yyyy >= 1970)
               {
                 ddddd_yyyy = calc_basedate(1970, 01, 01);
                 ddddd -= ddddd_yyyy;
                 printf("%d\n", ddddd);
                 exit(0);
               }
               else
               {
                 fprintf(stderr, "This is a trick question, right?\n"
                   "The -u option with a date older than Jan. 1, 1970,\n"
                   "and you expect me to give you the basedate!  :-))\n"
                   "%s terminated.\n", progname);
                 exit(20);
               }
             }                  /*--------------------------------------------*/
             else if (basedate) /* Calculate basedate for the date specified. */
             {                  /*--------------------------------------------*/
               ddddd = calc_basedate(yyyy, mm, dd);
               printf("%d\n", ddddd);
               exit(0);
             }

             /*-------------------------------------------------------------*/
             /* No option passed, only adj-days and (optionally) yyyymmdd.  */
             /*-------------------------------------------------------------*/
             if (argc == 1 && adj_days != 0)
             {
               secs_now += (adj_days * H24SSS);
               time_now = localtime(&secs_now);
               strftime(yyyymmdd, 9, "%Y""%m""%d", time_now);
               printf("%s\n", yyyymmdd);
               exit(0);
             }

             /*---------------------------------------------------------------*/
             /* Arriving here means it was none of the above (single option   */
             /* or argument), so begin by parsing yyyymmdd into yyyy, mm, and */
             /* ddddd, then assigning them to integers (dd's value is the     */
             /* seed to ddddd, hence the assignment to ddddd, not dd).        */
             /*---------------------------------------------------------------*/
             STRNCPY(four_char,  yyyymmdd, 4)      ; yyyy  = atoi(four_char);
             STRNCPY(two_char, (&yyyymmdd[0]+4), 2); mm    = atoi(two_char );
             STRNCPY(two_char, (&yyyymmdd[0]+6), 2); ddddd = atoi(two_char );

             validate_mm_dd(mm, ddddd);

             /*---------------------------------------------------------------*/
             /* Validation OK.  Add the previous month YTD days to our ddddd. */
             /*---------------------------------------------------------------*/
             for (n=1; n <= iterations; n++)
             {
               /*------------------------------------------------------------*/
               /* If leap year, assign address of julian_leap to accum_days. */
               /*------------------------------------------------------------*/
               if (leap_year(yyyy))
                 accum_days = &julian_leap[0];

               /*------------------------------------------------------------*/
               ddddd += accum_days[mm-1]; /* January-preceding month's days  */
               /*------------------------------------------------------------*/

               /*------------------------------------------------------------*/
               /* If adjustment day(s) is negative, back up one year at a    */
               /* time -- adding that year's days to ddddd -- until we have  */
               /* enough accumulated days to handle a date that far back.    */
               /*------------------------------------------------------------*/
               if (adj_days < 0)
               {
                 abs_adj = labs(adj_days);
                 while (ddddd <= abs_adj)
                    ddddd += (leap_year(--yyyy)) ? 366 : 365;
               }

               /*-----------------------------------*/
               /* Now, add in the adjustment day(s) */
               /*-----------------------------------*/
               ddddd += adj_days;

               /*----------------------------------------------------------*/
               /* If user wants weekday, print it, and exit (a zero-based  */
               /* number: 0=Sunday, 6=Saturday).                           */
               /*----------------------------------------------------------*/
               if (weekday_wanted == 1)
               {
                 /*----------------------------------------------------------*/
                 /* In the Day of the week formula below, the divisions are  */
                 /* integer divisions, in which remainders are discarded     */
                 /*                                                          */
                 /*       14 - month                                         */
                 /*  a =  ----------                                         */
                 /*           12                                             */
                 /*                                                          */
                 /*  y = year - a                                            */
                 /*                                                          */
                 /*  m = month + 12a - 2                                     */
                 /*                                                          */
                 /*                     y    31m                             */
                 /* Jd = (5+ day + y + --- + ---) mod 7          # Julian    */
                 /*                     4     12                             */
                 /*                                                          */
                 /*                 y     y     y    31m                     */
                 /* Gd = (day + y + --- - --- + --- + ---) mod 7 # Gregorian */
                 /*                 4    100   400    12                     */
                 /*----------------------------------------------------------*/
                 while (--yyyy > 0)
                   ddddd += (leap_year(yyyy)) ? 366 : 365;

                 n = (ddddd % 7);
                 if (weekday_abbr_wanted == 1)
                   printf("%s\n", weekdays_abbr[n]);
                 else
                   printf("%s\n", weekdays_long[n]);
                 exit(n); /* n = day number [0-6] */
               }

               /*------------------------------------------------------------*/
               /* By now we have the number of days (ddddd) from a Jan. 01   */
               /* date far enough back to handle any negative adjustment(s). */
               /* Beginning there (and providing ddddd has a year's worth),  */
               /* we subtract a year's worth of days from ddddd.  (We're     */
               /* careful to any leap day.)  We do this as long as ddddd is  */
               /* greater than the current year's days. Through this process */
               /* we calculate the new year and the number of days we have   */
               /* for that year.  From there it is a simple matter to reduce */
               /* the days to month and day values.                          */
               /*------------------------------------------------------------*/
               while (ddddd > this_years_days(yyyy))
               {
                 ddddd -= this_years_days(yyyy);
                 yyyy++;
               }

               /*------------------------------------------------------------*/
               /* If the days left in our accumulator (ddddd) are > 59, and  */
               /* the year proves to be a leap year, then use a YTD monthly  */
               /* accumulator that includes a leap day.                      */
               /*------------------------------------------------------------*/
               if ((ddddd > 59) && leap_year(yyyy))
                 accum_days = &julian_leap[0];
               else
                 accum_days = &julian_days[0];

               if (yyyymmdd_to_jjj)
               {
                 printf("%03d\n", ddddd);
               }
               else
               {
                 /*-----------------------------------------------------------*/
                 /* Rip through accum_days until we find one that is too big. */
                 /* Then use the preceding one as the correct month number    */
                 /* and decrement ddddd by the month's julian days.           */
                 /*-----------------------------------------------------------*/
                 for (mm=1; mm<=12; mm++)
                 {
                   if ((ddddd - accum_days[mm]) <= 0)
                   {
                     ddddd -= accum_days[mm-1];
                     break;
                   }
                 }
                 printf("%04d%02d%02d\n", yyyy,mm,ddddd);
               }
             }

             exit(0);

             /*---------------------------------------------------------------*/
             /* Program never gets here, but this */ return 0; /* eliminates  */
             /* pesky compile message, about main not returning a value  (it  */
             /* seems that 'exit(0)' is just not good enough).                */
             /*---------------------------------------------------------------*/
           }


           /*====================================================================*/
           /*                    U S E R    F U N C T I O N S                    */
           /*                       (in alphabetical order)                      */
           /*--------------------------------------------------------------------*/
           long calc_basedate(int yyyy, int mm, int dd)
           /*--------------------------------------------------------------------*/
           {
             long ddddd;
             int  i;
             int  leap_days;
             int  cc_leapdays;
             int  cc;
             int  julian_days[] = {0,31,59,90,120,151,181,212,243,273,304,334,365};
             int  julian_leap[] = {0,31,60,91,121,152,182,213,244,274,305,335,366};
             int  *accum_days   = &julian_days[0];
             /*-------------------------------------------------------------*/
             /* We can't have a yyyy since there is no year 0000 in the CE. */
             /*-------------------------------------------------------------*/
             if ((yyyy - 1) > 0)
             {
               yyyy--;
               cc          = yyyy / 100;
               ddddd       = yyyy * 365;
               leap_days   = yyyy / 4;
               cc_leapdays = (cc > 0) ? (cc / 4) : 0;
               ddddd       = ddddd + leap_days - cc + cc_leapdays;
               yyyy++;
             }
             ddddd += dd;

             /*-------------------------------------------------------*/
             /* Add the previous month YTD days to our ddddd.  If it  */
             /* is a leap year, assign julian_leap[] to accum_days[]. */
             /* Then add in YTD days for previous months of this year */
             /*-------------------------------------------------------*/
             if (leap_year(yyyy))
               for (i = 0; i < 13; i++) accum_days[i] = julian_leap[i];
             else
               for (i = 0; i < 13; i++) accum_days[i] = julian_days[i];
             ddddd += accum_days[--mm];
             return (ddddd);
           }

           /*--------------------------------------------------------------------*/
           int leap_year(int yyyy)
           /*--------------------------------------------------------------------*/
           {
             /*-------------------------------------------------------------*/
             /* if year is evenly divisible by 4, but yyyy is not evenly    */
             /* divisible by 100, OR yyyy IS evenly divisible by 400, then  */
             /* it's a leap year.                                           */
             /*-------------------------------------------------------------*/
             return (((yyyy%4 == 0 && yyyy%100 != 0) || (yyyy%400 == 0)) ? 1 : 0);
           }

           /*--------------------------------------------------------------------*/
           void show_documentation(char *progname)
           /*--------------------------------------------------------------------*/
           {
           #define P printf
             P("#===========================================================#\n");
             P("#                 D O C U M E N T A T I O N                 #\n");
             P("#===========================================================#\n");
             P(                                                             "\n");
             P("     Author: Bob Orlando <Bob@OrlandoKuntao.com>"           "\n");
             P(                                                             "\n");
             P("       Date: July 2, 1995"                                  "\n");
             P(                                                             "\n");
             usage(progname);
             P("    Purpose: This program calculates a date (or dates) that's\n");
             P("             nnnnn days (+ or -) distant from either today's \n");
             P("             date or another user-supplied date.  We can also\n");
             P("             calculate the number of days since or until the \n");
             P("             the date specified, as well as base dates since \n");
             P("             either Jan. 1, 0001 or the Unix epoch date,"   "\n");
             P("             Jan. 1, 1970"                                  "\n");
             P(                                                             "\n");
             P("Description: For all practical purposes, any date the user" "\n");
             P("             wishes to use as a yyyymmdd (from 01/01/0001"  "\n");
             P("             through 12/31/9999) is accepted.  The resultant \n");
             P("             date is returned via stdout in yyyymmdd form." "\n");
             P("             The program is especially useful for calculating\n");
             P("             yesterday's, tomorrow's, or any other desired" "\n");
             P("             date.  Additionally, by specifying an iteration \n");
             P("             value (the last argument) the program generates \n");
             P("             that number of dates, each adjusted on the"    "\n");
             P("             previous date (handy for calculating paydays and\n");
             P("             the like).  Because the program writes to stdout\n");
             P("             its output is easily redirected to a file where \n");
             P("             the results can be subsequently edited or munged\n");
             P("             as needed.  The program also comes with help"  "\n");
             P("             options (-h and -H for summary and detailed"   "\n");
             P("             outputs, respectively)."                       "\n");
             P(                                                             "\n");
             P(" Exit Codes: For all options except weekday (-w or -W)"     "\n");
             P("                Zero         = Normal   | Success"          "\n");
             P("                Nonzero (7+) = Abnormal | Failure"          "\n");
             P("             For weekday (-w or -W) option"                 "\n");
             P("                0-6 = Success (zero-based weekday: Sun = 0)""\n");
             P("                7+  = Failure"                              "\n");
             P(                                                             "\n");
             P("    History: The Gregorian correction to the Julian calendar \n");
             P("             made in October, 1582 dropped 10 days.  That"  "\n");
             P("             is, October 4, 1582 was followed immediately by \n");
             P("             October 15.  This Papal correction, although"  "\n");
             P("             scientifically correct, was not adopted by"    "\n");
             P("             non-Catholic countries until almost two"       "\n");
             P("             centuries later in 1752.  In September, 1752"  "\n");
             P("             the English calendar was adjusted to Pope"     "\n");
             P("             Gregory's method of correction and 11 days were \n");
             P("             dropped (September 14, followed September 2)." "\n");
             P(                                                             "\n");
             P("             While this routine easily calculates the date" "\n");
             P("             that far back, it does not drop October 5-14," "\n");
             P("             1582 or September 3-13, 1752.  If this routine""\n");
             P("             is used to calculate dates that far back, the" "\n");
             P("             previously adjusted and dropped dates will"    "\n");
             P("             appear as if no calendar corrections were ever""\n");
             P("             made.  All of this is only for technical"      "\n");
             P("             purists.  Most real-world applications will not \n");
             P("             go back that far.  This program's accuracy,"   "\n");
             P("             then, is sufficient for most purposes."        "\n");
             P(                                                             "\n");
             P("       Note: As with any program there are doubtless, many" "\n");
             P("             places where this code can be improved or"     "\n");
             P("             simplified.  Feel free, therefore, to forward" "\n");
             P("             comments/suggestions to Bob@OrlandoKuntao.com.""\n");
             P("             That said, my preference is for readable, easy""\n");
             P("             to follow code over highly efficient, but"     "\n");
             P("             difficult to follow (read obfuscated) code since\n");
             P("             readable code (even if less efficient) makes"  "\n");
             P("             maintenance much less a chore."                "\n");
             P(                                                             "\n");
             P(" +----------------------------------------------------------+\n");
             P(" |     For modifications, see 'Modified' section in the     |\n");
             P(" |     source code immediately following this statement.    |\n");
             P(" +----------------------------------------------------------+\n");
             P(                                                             "\n");
             /*-----------------------------------------------------------------*/
             /*                                                                 */
             /*    Modified: 2010-03-19 Bob Orlando                             */
             /*                 v2.3  * Bug fix: Added code to reject day '00'  */
             /*                         supplied by user.                       */
             /*                                                                 */
             /*              2004-07-14 Bob Orlando                             */
             /*                 v2.2  * Add -W option (same as -w, but returns  */
             /*                         long weekday name).  Thanks to Hans     */
             /*                         Looyschelder of the Netherlands for     */
             /*                         both the idea and the clean code for    */
             /*                         accomplishing it.                       */
             /*                                                                 */
             /*              2004-05-05 Bob Orlando                             */
             /*                 v2.1  * Add -S option (same as -s, but returns  */
             /*                         unsigned integer regardless of whether  */
             /*                         the target date is future or past).     */
             /*                                                                 */
             /*     Revised: 2003-05-30 Bob Orlando                             */
             /*                 v2.0  * Incorporate most of basedate.c          */
             /*                         functionality (options -b, -u, and -s). */
             /*                                                                 */
             /*-----------------------------------------------------------------*/
           #undef P
             return;
           }

           /*--------------------------------------------------------------------*/
           int this_years_days(int yyyy)
           /*--------------------------------------------------------------------*/
           {
             return ((leap_year(yyyy)) ? 366 : 365);
           }

           /*--------------------------------------------------------------------*/
           void usage(char *progname)
           /*--------------------------------------------------------------------*/
           {
           #define P printf
             P(" Program ID: %s (03-19-2010 / v2.3)\n",                 progname);
             P(                                                             "\n");
             P("      Usage: %s -bHhJjSstuWwy\n"
               "               [-|+]adj_days [yyyymmdd [iterations]]\n",progname);
             P(                                                             "\n");
             P("                -b Basedate of today (or date specified)"   "\n");
             P("                   since Jan. 1, 0001"                      "\n");
             P("                -H Detailed help (Documentation)"           "\n");
             P("                -h Summary help (Usage)"                    "\n");
             P("                -J Julian (yyyyJJJ) to Gregorian (yyyymmdd)""\n");
             P("                -j Julian day (ddd) for today or yyyymmdd"  "\n");
             P("                -S Days since (or until) yyyymmdd (unsigned) \n");
             P("                -s Days since (or until) yyyymmdd **"       "\n");
             P("                -t Tomorrow's date"                         "\n");
             P("                -u Basedate of today (or date specified)"   "\n");
             P("                   since Jan. 1, 1970--the Unix epoch date" "\n");
             P("                   (essentially 'dateplus -s 19700101')"    "\n");
             P("                -W Date's long weekday"                     "\n");
             P("                -w Date's weekday"                          "\n");
             P("                   (-w or -W: see 'Exit Codes' below)"      "\n");
             P("                -y Yesterday's date"                        "\n");
             P(                                                             "\n");
             P("      Notes: adj_days may be positive, negative, or unsigned.\n");
             P(                                                             "\n");
             P("             adj_days by itself (without a yyyymmdd option" "\n");
             P("             argument), yields an adjusted date that is"    "\n");
             P("             calculated from today's date.  For example,"   "\n");
             P("             '%s 1' yields tomorrow's date).\n",        progname);
             P(                                                             "\n");
             P("             yyyymmdd is an optional date from which an"    "\n");
             P("             adjusted date is calculated."                  "\n");
             P(                                                             "\n");
             P("             iterations generate multiple dates that are"   "\n");
             P("             adj_days apart (i.e. paydays).  This argument" "\n");
             P("             is not allowed with the julian (-j) option."   "\n");
             P(                                                             "\n");
             P("             yyyymmdd also may be a future date (useful for""\n");
             P("             determining the number of days until a certain""\n");
             P("             date).  Days future are reported negatively."  "\n");
             P("             For example, run on October 27, 1997), the"    "\n");
             P("          ** 'dateplus -s 20000101' yielded -731, meaning"  "\n");
             P("             731 days until Y2K.  (For unsigned results use""\n");
             P("             -S option instead.)"                         "\n\n");
           #undef P
             return;
           }

           /*--------------------------------------------------------------------*/
           void validate_mm_dd(int mm, int dd)
           /*--------------------------------------------------------------------*/
           {
             int  mm_days;
             /*-----------------------------------------------------*/
             /* Validate the month and day.  Start by determining   */
             /* the maximum possible days for the month.  Then, see */
             /* if the day for the month given exceeds its maximum. */
             /*-----------------------------------------------------*/
             switch (mm)
             {
               case  1:
               case  3:
               case  5:
               case  7:
               case  8:
               case 10:
               case 12:
                 mm_days=31;
                 break;
               case  4:
               case  6:
               case  9:
               case 11:
                 mm_days=30;
                 break;
               case  2:
                 mm_days = (leap_year(yyyy)) ? 29 : 28;
                 break;
               default:
                 fprintf(stderr,"Month %02d is invalid.\n", mm);
                 exit(21);
             }

             if (dd > mm_days)
             {
               fprintf(stderr,"%s, %d does not have %d days.\n",
                 months[mm-1], yyyy, dd);
               exit(22);
             }
             if (dd < 1)
             {
               fprintf(stderr,"%d is an invalid day for any month!\n", dd);
               exit(23);
             }
             return; /* Passed with flying colors. */
           }
              
            
 
Artificial intelligence is no match for natural stupidity.
 
©Copyright Bob Orlando, 1995-2014
All rights reserved.
http://www.OrlandoKuntao.com
E-mail: Bob@OrlandoKuntao.com
Last update:  Dec. 17, 2014
by Bob Orlando
Web Site of Bob Orlando: Instructor in Kuntao-Silat (Chinese kuntao and Dutch-Indonesian pukulan pentjak silat), author of two popular martial art books: "Indonesian Fighting Fundamentals" and "Martial Arts America: A Western Approach to Eastern Arts"; and producer of four martial art videos: Fighting Arts of Indonesia, Reflex Action, Fighting Footwork of Kuntao and Silat, Fighting Forms of Kuntao-Silat. Offering practical martial arts instruction to adults living in and throughout the Denver metropolitan area including, Lakewood, Littleton, Morrison, and Golden Colorado.