Calendar application in C Programming Language
Do not miss this exclusive book on Binary Tree Problems. Get it now for free.
In this article, we will explore how to design and implement a calendar generating command line tool in C Programming Language. Given a year, the tool will print the entire calendar in correct format. This is a good addition to SDE portfolio.
Table of contents:
- Features and requirements
- Code Design of calendar
- Hardcode the data we need
- Leap year
- Get current year
- Which day of the week?
- Design the calendar
- Complete C implementation
We will start with our C Calendar project.
Features and requirements
The features and requirements of our calendar tool will be as follows:
- By default, the tool will generate the calendar for current year. We should have the option to pass a custom year.
- Add color to the printed calendar such that current date has a distinct color, past dates are in red and future dates have another color.
- A calendar should be printed in order. For example, this is a sample month in our calendar:
February
-----------------------------------
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
Code Design of calendar
First, try to create a calendar manually for a given year say 2002. This will help you understand the information you need.
For every core part, we will create a function which will provide us all information we need. At the end, we will have a function which will use all the available information and print the calendar in a loop for every month.
Few of the information we need are:
- If the year is a leap year or not. This will help us figure out the number of days in that year.
- The day of the week a particular date is in.
- and so on
We will understand this better as we walk through the different sections.
Hardcode the data we need
To deal with calendar, we need 2 data beyond which we can generate everything. These are:
- The number of days in each month
- The name of each month
We will hardcode these two data as arrays in our C code.
We create an array to store the number of days in every month. This is needed as every month does not have the same number of days and neither does it follow a pattern.
int days_in_month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
Note the value at the i-th index is the number of days in the i-th month. For simplicity, we are skipping 0 index.
We create another array of char* (string) to store the name of each month. In this, we will skip the 0 index as well. There is a one-to-one mapping of this array to our previous array storing the number of days in each month.
char *months[]=
{
" ",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
Leap year
Note that in the previous section, we have set the number of days in February to be 28. This is true if the concerned year is a non-leap year.
If it is a leap year, then this value needs to be updated to 29.
Mathematically, a year is a leap if:
- The year is divisible by 400
- OR, year is divisible by 4 and not divisible by 100
Note, checking only if a year is divisible by 4 is not enough. Why?
The answer is in the fact that years like 2000 and 1600 are leap years but years like 1700, 1800, 1900, 2100, 2200 and 2300 are not leap years.
The actual length of a year (that is, Earth completing one complete circle around the Sun) is slightly less than 365.25 days (by nearly 11 minutes). To compensate, leap year is skipped 3 times every 400 years.
This function checks if the concerned year is a leap year or not and takes a corresponding action:
int determineleapyear(int year)
{
if(year% 4 == FALSE && year%100 != FALSE || year%400 == FALSE)
{
days_in_month[2] = 29;
return TRUE;
}
else
{
days_in_month[2] = 28;
return FALSE;
}
}
As days_in_month array is a global array, we can update it directly. Note, in the function, we can skip the else part.
Get current year
As we generate the calendar of a given year, we need to develop a function which will be able to get the current year on its own.
For this, we need to include the time.h header file which has a member function called localtime which gives the current time including the date, year, month, minutes, second and so on. For our case, we will extract only the year.
The process to get the time is as follows:
- Create a default timer variable
- Use the localtime member function to get the current local time using the timer value. This will return a struct which will have different parameters.
- We can get different information from different parameters such as tm_year for year, tm_mon for month and tm_mday for date.
We also, extract the current date and we will use this information later for a color coding within our calendar.
Following is the function implemented in C:
int inputyear(void)
{
int year;
time_t t = time(NULL);
struct tm tm = *localtime(&t);
today_year = tm.tm_year + 1900;
today_month = tm.tm_mon + 1;
today_day = tm.tm_mday;
year = today_year;
printf("Today DD/MM/YYYY: %d/%d/%d\n", today_day, today_month, today_year);
return year;
}
Which day of the week?
Every week has 7 days but we need to find which day of the week is the first day of the month. This is because while printing our calendar we need to print the first day accordingly by printing few spaces in the front.
Following is the function to calculate the day of the week for the 1st day of the year:
int determinedaycode(int year)
{
int daycode;
int d1, d2, d3;
d1 = (year - 1.)/ 4.0;
d2 = (year - 1.)/ 100.;
d3 = (year - 1.)/ 400.;
daycode = (year + d1 - d2 + d3) %7;
return daycode;
}
Beyond this, this variable will be constantly updated for every month which will be trivial.
Design the calendar
A single month in our calendar will look like this:
February
-----------------------------------
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
We can process and print each month in a loop. The days of the week are printed for each month as well.
The position of the first day of the month will be determined by daycode. For the first month that is January, daycode is calculated using the function determinedaycode() which should be called before starting to build our calendar. For the next month, daycode will be updated within the calendar code and will be easy and it is the next day in the week considering the last day of the previous month.
ou may create your own formatting for the calendar. In this case, we have assigned:
- 3 spaces for each day of the week. Print accordingly if date is single or double character.
- 2 spaces between two week days.
Complete C Implementation
Beyond the basic techniques as explained above, we have defined few macros in our code:
#define TRUE 1
#define FALSE 0
#define KGRN "\x1B[32m"
#define RED "\x1B[31m"
#define YEL "\x1B[33m"
#define RESET "\x1B[0m"
The macros for different colors are used for color coding. We color the current day in green, past days in red, upcoming days in green and so on. The color is assigned to a text using these ascii color codes.
If you want to print something in red, then place the macro RED before the word and place RESET after the word. If RESET is not placed after the word, all words after RED code will be in color red.
printf("%s%2d%s", RED, day, RESET );
Following is the complete C program for Calendar application:
#include<stdio.h>
#include <time.h>
#define TRUE 1
#define FALSE 0
#define KGRN "\x1B[32m"
#define RED "\x1B[31m"
#define YEL "\x1B[33m"
#define RESET "\x1B[0m"
int days_in_month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
int today_year = -1, today_month = -1, today_day = -1;
char *months[]=
{
" ",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
int inputyear(void)
{
int year;
time_t t = time(NULL);
struct tm tm = *localtime(&t);
today_year = tm.tm_year + 1900;
today_month = tm.tm_mon + 1;
today_day = tm.tm_mday;
year = today_year;
printf("Today DD/MM/YYYY: %d/%d/%d\n", today_day, today_month, today_year);
return year;
}
int determinedaycode(int year)
{
int daycode;
int d1, d2, d3;
d1 = (year - 1.)/ 4.0;
d2 = (year - 1.)/ 100.;
d3 = (year - 1.)/ 400.;
daycode = (year + d1 - d2 + d3) %7;
return daycode;
}
int determineleapyear(int year)
{
if(year% 4 == FALSE && year%100 != FALSE || year%400 == FALSE)
{
days_in_month[2] = 29;
return TRUE;
}
else
{
days_in_month[2] = 28;
return FALSE;
}
}
void calendar(int year, int daycode)
{
int month, day;
for ( month = 1; month <= 12; month++ )
{
printf("\n\n%s", months[month]);
printf("\n-----------------------------------");
printf("\nSun Mon Tue Wed Thu Fri Sat\n" );
// Correct the position for the first date
for ( day = 1; day <= 1 + daycode * 5; day++ )
{
printf(" ");
}
// Print all the dates for one month
for ( day = 1; day <= days_in_month[month]; day++ )
{
if(month < today_month)
printf("%s%2d%s", RED, day, RESET );
else if(month == today_month && day < today_day)
printf("%s%2d%s", RED, day, RESET );
else if(today_day == day && today_month == month)
printf("%s%2d%s", KGRN, day, RESET );
else
printf("%s%2d%s", YEL, day, RESET );
// Is day before Sat? Else start next line Sun.
if ( ( day + daycode ) % 7 > 0 )
printf(" " );
else
printf("\n " );
}
// Set position for next month
daycode = ( daycode + days_in_month[month] ) % 7;
}
}
int main(int argc, char** argv)
{
int year, daycode, leapyear;
if(argc > 1)
year = atoi(argv[1]);
else
year = inputyear();
printf("CALENDER OF YEAR %d", year);
daycode = determinedaycode(year);
determineleapyear(year);
calendar(year, daycode);
printf("\n");
}
Following is a sample output of our calendar:
Today DD/MM/YYYY: 17/1/2023
CALENDER OF YEAR 2023
January
-----------------------------------
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
29 30 31
February
-----------------------------------
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
March
-----------------------------------
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 29 30 31
April
-----------------------------------
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 29
30
May
-----------------------------------
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 29 30 31
June
-----------------------------------
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 29 30
July
-----------------------------------
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 29
30 31
August
-----------------------------------
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 29 30 31
September
-----------------------------------
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 29 30
October
-----------------------------------
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
29 30 31
November
-----------------------------------
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 29 30
December
-----------------------------------
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 29 30
31
With this article at OpenGenus, you must have the complete idea of how to create a custom calendar command line tool in C Programming Language.
Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.