The Month Program, Phase V

It’s all come to this: Gathering up the individual functions necessary to code a program that outputs the current month, formatted, with the proper number of days for February. Coincidentally, this post is published in February.

Here was my original request, from the January 4, 2014 lesson:

I want the monthly calendar output to highlight the current day of the month.

The process I’ve shown over the past five weeks illustrates how a programmer would tackle such a problem:

Phase I: Figure out today’s date. You need that information primarily to obtain the current year and month, but also to help calculate the first day of the month.

Phase II: Determine on which day of the week is the first of the month. This calculation requires knowing the current day (Phase I), and it’s necessary when you want to format a calendar’s output.

Phase III: Once you have the first day of the month, the process of creating a calendar involves creating formatted output. The big issue then is knowing on which day of the month you stop displaying the calendar.

Phase IV: Next you have to deal with the February problem. Twenty five percent of the time February could be 29 days long instead of 28. That step involves creating a special days-of-the-month function.

Phase V (this Lesson) brings it all together: The calendar output now contains a function to calculate the number of days in the month, including February. I also added one more element, which is to highlight the current day. That code is rather easy to implement: In the example below, an if statement at Line 47 determines whether day (the day being output for the calendar) is equal to mday (the current day of the month). If so, the printf() function displays the date with square brackets around the number (Line 48).

Here’s the final code:

#include <stdio.h>
#include <time.h>

int thefirst(int weekday, int monthday);
int daysInMonth(int month,int year);

int main()
{
    time_t tictoc;
    struct tm *rightnow;
    int wday,mday,month,year,firstdom,dim,day,d;
    char *months[12] = {
        "January", "February", "March", "April",
        "May", "June", "July", "August",
        "September", "October", "November", "December" };

    time(&tictoc);                  /* get Unix epoch time */
                                    /* fill tm struct rightnow */
    rightnow = localtime(&tictoc);
                                    /* Get info from struct */
    wday = rightnow->tm_wday;        /* 0=Sunday */
    mday = rightnow->tm_mday;        /* 1 to 31 */
    month = rightnow->tm_mon;        /* 0=January */
    year = rightnow->tm_year+1900;   /* current year - 1900 */

/* Display Calendar Header */
    printf("%s %d\n",months[month],year);
    printf("Sun Mon Tue Wed Thu Fri Sat\n");

/* Prep starting variables */
    firstdom = thefirst(wday,mday);
    dim = daysInMonth(month,year);
    day = 1;                            /* Day of the month */
/* Display the days of the month */
    while( day <= dim )
    {
        for( d = 0; d < 7; d++)
        {
            /* Test for the first week of the month */
            if( d < firstdom && day == 1 )
            {
                printf("    ");         /* blank date, 4 spaces */
            }
            else
            {
                                        /* highlight current day */
                if( day == mday )
                    printf("[%2d]",day);
                else
                    printf(" %2d ",day);
                                        /* check the next day */
                day++;
                if( day > dim )
                    break;
            }
        }
        putchar('\n');
    }

    return(0);
}

/* Calculate First Day of the Month. */
int thefirst(int weekday, int monthday)
{
    int first;

    first = weekday - (monthday % 7) + 1;
    first %= 7;
    if( first < 0 )
        first+=7;

    return(first);
}

/* Determine the number of days in the month */
int daysInMonth(int month,int year)
{
    int month_length[] = {
        31, 28, 31, 30, 31, 30,
        31, 31, 30, 31, 30, 31 };

    if(month != 1)
        return(month_length[month]);

    if( year % 4 )
        return(28);
    if( !(year % 100))
    {
        if( year % 400 )
            return(28);
        else
            return(29);
    }
    return(29);
}

Here’s the sample output (for today, February 1, 2014):

February 2014
Sun Mon Tue Wed Thu Fri Sat
                        [ 1]
  2   3   4   5   6   7   8 
  9  10  11  12  13  14  15 
 16  17  18  19  20  21  22 
 23  24  25  26  27  28 

One more addition you could make would be to center the month and year at the top of the calendar output. That involves a few tricks, but mostly pulling in your solution to January’s Exercise on centering text.

Leave a Reply