To create a calendar, you start with the first day of the month. Knowing which weekday is the first of the month is vital to your success.
Last week’s Lesson discussed how to create a program that displays the current day of the month and day of the week. Those are the two critical pieces of information you need to start building a monthly calendar.
Well, you also need to know which month it is, so that you can properly display 30 or 31 days, with February being a hassel. For now, however, your task is generating code that tells you whether the first of the month is a Sunday, Monday, Tuesday, etc.
So how do you get from Saturday January 11 to Wednesday January 1?
The key is to reconstruct the first week of the month. To do that when you know the current day of the month and day of the week, you whip out the modulus operator. With 7 possible days of the week, you can pretty much figure that % 7
somehow works into the equation.
Breaking down the problem specifically, if you know today is Saturday January 11 then on what day of the month was the first Saturday?
That’s where the % 7
formula works. In this case, 11
(today’s date) %
(mod) 7
(days in a week) equals 4. So the first Saturday of the month was the 4th.
In your head, you can count backwards: 4th Saturday, 3rd Friday, 2nd Thursday, and then the 1st was a Wednesday. The computer can’t access information in your head, so you’ll need to do more coding. Specifically, you’ll use the tm_wday
member of the tm
structure generated by the localtime() function.
Saturday is the tm_wday
value 6. Subtract 4 and you get 2, which is Tuesday. That isn’t the first day of the week, so you need to add one: tm_wday - (tm_mday % 7) + 1
If the first falls on a Sunday, you need to perform another % 7
to keep within the range of 0 and 6. Further, you need to deal with negative values, which can happen for various reasons. Rather than slog through additional explanations, here is the algorithm I devised:
/* Calculate First Day of the Month */
first = wday - (mday % 7) + 1;
first %= 7;
if( first < 0 )
first+=7;
The variable first
is the weekday upon which the 1st falls, 0 through 6 for Sunday through Saturday. Those values correspond to the values stored in the tm
structure's tm_wday
member.
Here's the sample code:
#include <stdio.h> #include <time.h> int main() { time_t tictoc; struct tm *rightnow; int first,wday,mday,month; char *months[12] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; char *weekdays[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; 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 */ /* Calculate First Day of the Month */ first = wday - (mday % 7) + 1; first %= 7; if( first < 0 ) first+=7; printf("The 1st of %s is on a %s\n", months[month], weekdays[first]); return(0); }
The code's output reflects the current day of the month:
The 1st of January is on a Wednesday
The next step is to build the calendar. Once you create that first week, the rest of the weeks fall into place. That is, until you get to the end of the month. That's a topic for another week's Lesson.