Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VC10.0

C++ .NET Command Line Calendar

5.00/5 (1 vote)
14 Oct 2010CPOL3 min read 21K   71  
How to use the .NET DateTime class in C++ to generate a basic calendar via a console program

Introduction


CustomCal is a .NET-based C++ project that shows how to use the DateTime class to build and output a calendar on the command line based on a year and month passed in as arguments.  This sample project is useful because there aren't a lot of examples that show how to use some of the basic methods of the DateTime class in C++.  


Background 


A friend of mine wanted to know how to build a command line calendar in C++, and I thought it was an interesting problem to solve. I decided to use the DateTime class from the .NET runtime because it did not seem to be limited to UTC (like the old-school ctime-based functions.) 


Using the code 


The CustomCal project is pretty simple and only includes three functions, and it does not leverage the object oriented nature of C++. The functions are:



  • main
  • buildCalendar(int year, int month) : The major logic of the program that does all the date calculations and outputs the calendar. 
  • showUsage()  : Outputs how the command line program should be used. 

The main function parses the command line arguments and validates that the year and month are within a logical range for the calendar and the DateTime class.  


C++
int main(array<System::String ^> ^args)
{
	int year;
	int month;
	if(args->Length == 2)
	{
		year = Convert::ToInt32(args[0]);
		month = Convert::ToInt32(args[1]);
		if((year < 1 || year > 9999) || (month < 1 || month > 12))
		{
			showUsage();
			return -2;
		}
	}
	else
	{
		showUsage();
		return -1;
	}

	buildCalendar(year, month);

	return 0;
}

The DateTime class, as far as I can tell, doesn't mind the extreme year situations of 1 or 9999. However, it will not magically resolve incorrect month designations by shifting to the next year (for instance, putting in 13 as the month in order to move to the 1st month of the next year.) 


Next, the program calls the buildCalendar function, which takes in the month and year, and writes out a calendar.


C++
// buildCalendar
//	int - year base for the calendar
//  int - month base for the calendar
int buildCalendar(int year, int month)
{
	int dayOfWeek;
	int weekCount = 6;
	int dayCount = 0;
	array<String^>^ months = gcnew array<String^>{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};

First thing that needs to happen in the function is the declaration of the variables necessary to facilitate the calendar building. The weekCount variable is used to control the main week loop for the outputting of the calendar, and the months variable is an array of short names for the month. The DateTime calendar doesn't have a method for retrieving the names for the months, so they have to be stored in the program itself.


Next, the dateTime variable is declared and set to the first day of the month and year passed into the function. 


DateTime dateTime = DateTime(year, month, 1);
Console::WriteLine(months[month-1] + " - " + year + "\n");
Console::WriteLine("Sun\tMon\tTue\tWed\tThu\tFri\tSat");

In order to start writing out the calendar at the beginning of the first week of the month, the program has to find out what day of the week the first of the month lands on. Then, startDate is declared and set to the first day of the week (which is not necessarily the first day of the month to be written out.)


dayOfWeek = Convert::ToInt32(dateTime.DayOfWeek)*-1;
//Move to the first day of the week
DateTime startDate = dateTime.AddDays(dayOfWeek);

Now that the first of the month and week has been set, its time to setup the outer loop to write out 6 weeks. 


The inner loop writes out the 7 days for each week. It does this by keeping an integer counter (dayCount) for the days that have been written to the console, and uses that counter to move to the next day in the month via the AddDays method. A day is not written out if the month is not the current month (which will probably happen in first or last weeks.)


	//Output at least 6 weeks
	for(; weekCount != 0; weekCount--)
	{
		//Output one week
		for(int j = 0; j < 7; j++)
		{
			if(startDate.AddDays(dayCount).Month == month)
			{
				Console::Write(startDate.AddDays(dayCount).Day + "\t");
			}
			else
			{
				//Don't show a day number if not for the current month
				Console::Write(" \t");
			}
			dayCount++;
		}
		
		System::Console::WriteLine("");
	}
	return 0;
}

The last function in the program is showUsage, which is called by main if the program is called with invalid arguments.  


void showUsage()
{
	Console::WriteLine("usage: CustomCal (4 digit year, > 1 and < 10,000) (month number, 1 - 12)");
	Console::WriteLine("example: CustomCal 1974 3  <-- March 1974");	
} 

If all goes well, the program will output one calendar month to the console. Here is the program in action:


customcal.png


Points of Interest


One thing to note about the DateTime class is that while you can convert the DayOfWeek output to Int32 in order to get 0 for Sunday, 1 for Monday, etc., you can't convert the integer of the Month output to a String in order to get the month name (hence the array of month names in the code above.)  

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)