Here's a fully functional console calendar I wrote using pdcurses/ncurses, it was based off a Windows version calendar, but I ported what I could to Linux, still missing some functionality from the Windows version by stoned coder, but I hope to get that sorted.
CODE
// calendar.cpp by mastercomputers
// includes
#include <curses.h> // contains our console objects
#include <cstdlib> // contains our string manipulation objects
// classes
class calendar
{
public:
calendar(int d = 1, int m = 1, int y = 2004); // defaults to 1/1/2004 (nz format dd/mm/yy)
virtual ~calendar() {} // does nothing, destructor virtual incase of inheritance
void printcalendar();
private:
bool isleapyear(); // returns true if leap year
int checkday(int); // checks validity of the day
int whatdayisfirstofmonth(); // returns 0 to 6 (Sunday - Saturday)
int howmanydays(); // returns number of days in the month
int day;
int month;
int year;
};
// constructors
calendar::calendar(int d, int m, int y) //checks validity of date and sets the variables
{
if(y < 1582) // Gregorian calendar was accepted 1582
{
printw("\nThe year %d is before Gregorian Calendar was accepted.\nWill fix to Julian Calendar eventually.\nSetting Year to 1582\nPress ANY key to continue\n", y);
refresh();
getch(); // waits for key press
year = 1582; // invalid year so set to 1582
}
else if(y >= 4904) // Every 3,322 years the calendar is out by a full day
{
printw("\nEvery 3,322 years would be out by a full day for the Gregorian Calendar.\nI will never live to see if they ever fix it.\nSo I am not correcting this calendar, but do be warned.\nSetting Year to %d\nPress ANY key to continue\n", y, y);
refresh();
getch();
year = y;
}
else
year = y; // y is valid so use it to set year
if((m >= 1) && (m <= 12)) // check month between 1 and 12
month = m; // if it is, sets month
else
{
printw("\nThe month %d is invalid. Setting Month to January\nPress ANY key to continue\n", m);
refresh();
getch();
month = 1;
}
day = checkday(d); // validate the day
}
bool calendar::isleapyear() // checks whether year is a leap year
{
if((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
return true; // it's a leap year
else
return false; // it's not a leap year
}
int calendar::checkday(int testday) // checks day is legal for month
{
if((testday > 0) && (testday <= howmanydays()))
return testday; // day is legal
printw("\nInvalid day entered. Setting to First of the Month.\nPress ANY key to continue\n");
refresh();
getch();
return 1; // day is not legal so setting to first day
}
int calendar::howmanydays()
{
if((month == 2) && isleapyear())
return 29; // if leap year February has 29 days
static const int daysinmonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // sets our month days
return daysinmonth[month - 1];
}
int calendar::whatdayisfirstofmonth() // calculates the day that is first for our month
{
int d = 1; // day is first
int m = month; // the month we selected
int y = year; // the year we selected
int f = (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7; // the impressive algorithm to do it
return f; // returns 0-6 (Sunday - Saturday)
}
void calendar::printcalendar() // prints calendar for entered date
{
clear(); // clears the screen
printw("Date entered was >> %d/%d/%d.\n",day, month, year);
printw("\n SUN MON TUE WED THU FRI SAT\n");
int startday = whatdayisfirstofmonth();
int endday = howmanydays();
for(int i = 0; i < startday; i++)
{
if(i == 0)
mvprintw(4, 4, "-");
if(i == 1)
mvprintw(4, 11, "-");
if(i == 2)
mvprintw(4, 18, "-");
if(i == 3)
mvprintw(4, 25, "-");
if(i == 4)
mvprintw(4, 32, "-");
if(i == 5)
mvprintw(4, 39, "-");
} // end of for loop
int rows = 4;
int count = 1;
for(int j = startday; j < (startday + endday); j++)
{
if(j % 7 == 0)
{
rows += 2;
move(rows, 4);
}
if(j % 7 == 1)
move(rows, 11);
if(j % 7 == 2)
move(rows, 18);
if(j % 7 == 3)
move(rows, 25);
if(j % 7 == 4)
move(rows, 32);
if(j % 7 == 5)
move(rows, 39);
if(j % 7 == 6)
move(rows, 46);
if(count == day) // set text to red if count is the day entered
{
start_color();
init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
attron(COLOR_PAIR(COLOR_RED));
}
printw("%d",count);
if(count == day) // turns off red text after day has been performed
attroff(COLOR_PAIR(COLOR_RED));
count++;
} // end of for loop
printw(" \n\n\n");
refresh();
}
int main(void)
{
initscr(); // starts our console screen buffer
echo(); // allows user input to be seen on screen
raw(); // enables break keys to escape program
if(has_colors() == FALSE) // checks whether console supports color
{
endwin();
fprintf(stderr, "Your terminal does not support color\nPress ANY key to exit\n");
getch();
return 1;
}
while(true) // indefinite loop
{
clear(); // clears screen
printw("Gregorian Calendar.\n\nUse NZ date format: day/month/year.\nUse the ENTER key after each entry.\n\n");
refresh();
char input_day[3];
char input_month[3];
char input_year[5];
printw("DAY: ");
refresh();
getnstr(input_day, 2); // gets the input as string
printw("MONTH: ");
refresh();
getnstr(input_month, 2);
printw("YEAR: ");
refresh();
getnstr(input_year, 4);
int d = atoi(input_day); // converts string to integers(numbers)
int m = atoi(input_month);
int y = atoi(input_year);
calendar date(d, m, y); // instantiates the calendar objects
date.printcalendar();
printw("Another calendar (Y/N) ? ");
refresh();
char input[2];
getnstr(input, 1);
if((input[0] == 'N' || input[0] == 'n'))
break; // escapes while loop
}
endwin(); // ends out console buffer
return 0;
}
// includes
#include <curses.h> // contains our console objects
#include <cstdlib> // contains our string manipulation objects
// classes
class calendar
{
public:
calendar(int d = 1, int m = 1, int y = 2004); // defaults to 1/1/2004 (nz format dd/mm/yy)
virtual ~calendar() {} // does nothing, destructor virtual incase of inheritance
void printcalendar();
private:
bool isleapyear(); // returns true if leap year
int checkday(int); // checks validity of the day
int whatdayisfirstofmonth(); // returns 0 to 6 (Sunday - Saturday)
int howmanydays(); // returns number of days in the month
int day;
int month;
int year;
};
// constructors
calendar::calendar(int d, int m, int y) //checks validity of date and sets the variables
{
if(y < 1582) // Gregorian calendar was accepted 1582
{
printw("\nThe year %d is before Gregorian Calendar was accepted.\nWill fix to Julian Calendar eventually.\nSetting Year to 1582\nPress ANY key to continue\n", y);
refresh();
getch(); // waits for key press
year = 1582; // invalid year so set to 1582
}
else if(y >= 4904) // Every 3,322 years the calendar is out by a full day
{
printw("\nEvery 3,322 years would be out by a full day for the Gregorian Calendar.\nI will never live to see if they ever fix it.\nSo I am not correcting this calendar, but do be warned.\nSetting Year to %d\nPress ANY key to continue\n", y, y);
refresh();
getch();
year = y;
}
else
year = y; // y is valid so use it to set year
if((m >= 1) && (m <= 12)) // check month between 1 and 12
month = m; // if it is, sets month
else
{
printw("\nThe month %d is invalid. Setting Month to January\nPress ANY key to continue\n", m);
refresh();
getch();
month = 1;
}
day = checkday(d); // validate the day
}
bool calendar::isleapyear() // checks whether year is a leap year
{
if((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)))
return true; // it's a leap year
else
return false; // it's not a leap year
}
int calendar::checkday(int testday) // checks day is legal for month
{
if((testday > 0) && (testday <= howmanydays()))
return testday; // day is legal
printw("\nInvalid day entered. Setting to First of the Month.\nPress ANY key to continue\n");
refresh();
getch();
return 1; // day is not legal so setting to first day
}
int calendar::howmanydays()
{
if((month == 2) && isleapyear())
return 29; // if leap year February has 29 days
static const int daysinmonth[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // sets our month days
return daysinmonth[month - 1];
}
int calendar::whatdayisfirstofmonth() // calculates the day that is first for our month
{
int d = 1; // day is first
int m = month; // the month we selected
int y = year; // the year we selected
int f = (d += m < 3 ? y-- : y - 2, 23 * m / 9 + d + 4 + y / 4 - y / 100 + y / 400) % 7; // the impressive algorithm to do it
return f; // returns 0-6 (Sunday - Saturday)
}
void calendar::printcalendar() // prints calendar for entered date
{
clear(); // clears the screen
printw("Date entered was >> %d/%d/%d.\n",day, month, year);
printw("\n SUN MON TUE WED THU FRI SAT\n");
int startday = whatdayisfirstofmonth();
int endday = howmanydays();
for(int i = 0; i < startday; i++)
{
if(i == 0)
mvprintw(4, 4, "-");
if(i == 1)
mvprintw(4, 11, "-");
if(i == 2)
mvprintw(4, 18, "-");
if(i == 3)
mvprintw(4, 25, "-");
if(i == 4)
mvprintw(4, 32, "-");
if(i == 5)
mvprintw(4, 39, "-");
} // end of for loop
int rows = 4;
int count = 1;
for(int j = startday; j < (startday + endday); j++)
{
if(j % 7 == 0)
{
rows += 2;
move(rows, 4);
}
if(j % 7 == 1)
move(rows, 11);
if(j % 7 == 2)
move(rows, 18);
if(j % 7 == 3)
move(rows, 25);
if(j % 7 == 4)
move(rows, 32);
if(j % 7 == 5)
move(rows, 39);
if(j % 7 == 6)
move(rows, 46);
if(count == day) // set text to red if count is the day entered
{
start_color();
init_pair(COLOR_RED, COLOR_RED, COLOR_BLACK);
attron(COLOR_PAIR(COLOR_RED));
}
printw("%d",count);
if(count == day) // turns off red text after day has been performed
attroff(COLOR_PAIR(COLOR_RED));
count++;
} // end of for loop
printw(" \n\n\n");
refresh();
}
int main(void)
{
initscr(); // starts our console screen buffer
echo(); // allows user input to be seen on screen
raw(); // enables break keys to escape program
if(has_colors() == FALSE) // checks whether console supports color
{
endwin();
fprintf(stderr, "Your terminal does not support color\nPress ANY key to exit\n");
getch();
return 1;
}
while(true) // indefinite loop
{
clear(); // clears screen
printw("Gregorian Calendar.\n\nUse NZ date format: day/month/year.\nUse the ENTER key after each entry.\n\n");
refresh();
char input_day[3];
char input_month[3];
char input_year[5];
printw("DAY: ");
refresh();
getnstr(input_day, 2); // gets the input as string
printw("MONTH: ");
refresh();
getnstr(input_month, 2);
printw("YEAR: ");
refresh();
getnstr(input_year, 4);
int d = atoi(input_day); // converts string to integers(numbers)
int m = atoi(input_month);
int y = atoi(input_year);
calendar date(d, m, y); // instantiates the calendar objects
date.printcalendar();
printw("Another calendar (Y/N) ? ");
refresh();
char input[2];
getnstr(input, 1);
if((input[0] == 'N' || input[0] == 'n'))
break; // escapes while loop
}
endwin(); // ends out console buffer
return 0;
}
To compile under Cygwin: g++ calendar.cpp -o calendar -lncurses -s -Os
To compile under MinGW for DOS: g++ calendar.cpp -o calendar -lpdcurses -s -Os
To compile under Linux: g++ calendar.cpp -o calendar -lncurses -s -Os
Get Cygwin here
Get MinGW here
Get PDCurses here
Get nCurses here
PDCurses should work with VC++ so this program should compile under it, you however need the PDCurses library.
Well, what this console program does is ask you for a DAY you like to see, MONTH you like to see and YEAR you like to see. It will then display a calendar with the day names and the days within that month. It changes the color of your DAY to red so it stands out more.
Updated: Another Calendar request added, a bit of code cleanup, works in Windows under DOS, Every 3,322 year fix (I thought about it but it would not be official and after 3,322 years I wouldn't exists to see a fix, I have a solution but will not include it in the program.
For those of you who are lazy and run DOS, here's the zipped up source and binary. PM me and I'll compile it and make it available for you.
Things that need working on: Build a Menu to run program, Ability to have specific date choice e.g. day/month/year or month/day/year, make compatible for early years using Julian's Calendar, different color displays and better layout, show the full year calendar and whatever else I can come up with.
Apart from that, it's a fully functional Gregorian Calendar.
If anyone would like to make alterations, please feel free. I know there's a lot that could be improved as it was quickly done.
Cheers, MC

