Compute Project Line Item Starting and Ending Dates

The Dates project provides the ability to compute the starting and ending times of a project line item while taking into account weekends, holidays and vacations.

You pass it a list of project line items, a list of holidays and vacations and a starting date and it will spin through the calendar assigning just the real working days to the project.


Dates.cpp

/******************************************************************************************
*                                                                                         *
*  Copyright (c) 2007 - 2011 Cass Tyler, PO Box 1026, Willard, NM 87063, (505) 384-5342   *
*                                                                                         *
*  This program takes the line item implementation time in days and computes the actual   *
*  dates associated with them, taking into account holidays, vacations, weekends, etc.    *
*                                                                                         *
******************************************************************************************/

#include "DateTime.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// Local Function Prototypes

bool IsNonWorkingDay ( long lnDay );
bool IsWeekend       ( long lnDay );
long NextWorkingDay  ( long lnDay );

// Enumerate the Days of the Week

enum eDayOfWeek {

   eSunday,
   eMonday,
   eTuesday,
   eWednesday,
   eThursday,
   eFriday,
   eSaturday,

};

// List the Non-Working Days (Holidays, Vacation Time, etc.)

long ulNonWorkingDays[] =  {

   // Vacation Week

   MDY2GD ( 10,  8, 2007 ),   // 732957
   MDY2GD ( 10,  9, 2007 ),   // 732958
   MDY2GD ( 10, 10, 2007 ),   // 732959
   MDY2GD ( 10, 11, 2007 ),   // 732960
   MDY2GD ( 10, 12, 2007 ),   // 732961

   // Thanksgiving

   MDY2GD ( 11, 22, 2007 ),   // 733003
   MDY2GD ( 11, 23, 2007 ),   // 733004

   // Winter Holiday

   MDY2GD ( 12, 24, 2007 ),   // 733034
   MDY2GD ( 12, 25, 2007 ),   // 733035
   MDY2GD ( 12, 26, 2007 ),   // 733036
   MDY2GD ( 12, 27, 2007 ),   // 733037
   MDY2GD ( 12, 28, 2007 ),   // 733038

   // New Years Eve

   MDY2GD ( 12, 31, 2007 ),   // 733041

   // New Years Day

   MDY2GD (  1,  1, 2008 ),   // 733042

   // Forth of July

   MDY2GD (  7,  4, 2008 ),   // 733227

};

// List the Line Items

struct tagItems {

   int      nDays;
   char *   szDesc;

} stItems[] = {

      10, "Stepper Motor Control",
      10, "Bring Up the Master Computer",
      15, "Finish the GUI",
      30, "Database",
      30, "Finish the Vacuum Controller",
      15, "Gold Disk Certification (Master Computer)",
      15, "Setup Configuration",
       5, "Current Measurement",
      10, "Named Configurations",
      10, "Ini File Configuration",
      15, "Testing",
      10, "Startup and Shutdown Checklists",
      10, "Documentation",
      10, "Training (Prepare, Present)",

};

bool IsNonWorkingDay ( long lnDay )

   {

      // Is this a Non-Working Day?

      for ( int i = 0; lnDay <= ulNonWorkingDays [ i ]; i++ )
         if ( lnDay == ulNonWorkingDays [ i ] )
            return true;

      return false;

   }  // bool IsNonWorkingDay ( long lnDay )

bool IsWeekend ( long lnDay )

   {
   long lnDayOfWeek = lnDay % 7L;

   return lnDayOfWeek == eSaturday || lnDayOfWeek == eSunday;

   }  // bool IsWeekend ( long lnDay )

long NextWorkingDay ( long lnDay )

   {

   lnDay++;

   while ( IsNonWorkingDay ( lnDay ) || IsWeekend ( lnDay ) )
      lnDay++;

   return lnDay;

   }  // long NextWorkingDay ( long lnDay )

int main ( int /* argc */, char * /* argv[] */, char * /* envp[] */ )

   {
   long  lnDay = MDY2GD ( 9, 12, 2007 );  // Initially the DAY BEFORE the First Working Day
   int   nMM = 0, nDD = 0, nYY = 0;

   // Print the Header Line

   fprintf ( stdout, "Begin,End,\"Work Days\",\"Calendar Days\",\"Line Item Description\"\n" );

   // Print the Line Item Line

   for ( int ixItem = 0; ixItem < sizeof stItems / sizeof stItems [ 0 ]; ixItem++ )
      {
      long lnBeg = NextWorkingDay ( lnDay );
      long lnEnd = lnBeg;

      // Find the Ending Date

      for ( int ixDay = 0; ixDay < stItems [ ixItem ].nDays; ixDay++ )
         lnEnd = ixDay ? NextWorkingDay ( lnEnd ) : lnBeg;

      // Print the Beginning Date

      GD2MDY ( lnBeg, &nMM, &nDD, &nYY );

      fprintf ( stdout, "%2.2d/%2.2d/%4.4d,", nMM, nDD, nYY );

      // Print the Ending Date

      GD2MDY ( lnEnd, &nMM, &nDD, &nYY );

      fprintf ( stdout, "%2.2d/%2.2d/%4.4d,", nMM, nDD, nYY );

      // Print the Number of Work Days, the Number of Calendar Days and the Line Item Description

      fprintf ( stdout, "%d,%d,\"%s\"\n", stItems [ ixItem ].nDays, lnEnd - lnBeg + 1, stItems [ ixItem ].szDesc );

      lnDay = lnEnd;

      }

   return 0;

   }  // int _tmain ( int argc, TCHAR * argv[], TCHAR * envp[] )