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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
| /* Implementation for Date Class (Date.cpp) */
#include <iostream>
#include <stdexcept>
#include "Date.h"
using namespace std;
// Initialize static non-integer variable (must be done outside the class declaration)
const string Date::STR_MONTHS[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
const int Date::DAYS_IN_MONTHS[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
const string Date::STR_DAYS[] = {"Sunday", "Monday", "Tuesday", "Wednesday",
"Thursday", "Friday", "Saturday"};
// A static function that returns true if the given year is a leap year
bool Date::isLeapYear(int year) {
return ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0));
}
// A static function that returns true if the given y, m, d constitutes a valid date
bool Date::isValidDate(int y, int m, int d) {
if (y >= YEAR_MIN && y <= YEAR_MAX && m >= 1 && m <= 12) {
int lastDayOfMonth = DAYS_IN_MONTHS[m-1];
if (m == 2 && isLeapYear(y)) {
lastDayOfMonth = 29;
}
return (d >= 1 && d <= lastDayOfMonth);
} else {
return false;
}
}
// A static function that returns the day of the week (0:Sun, 6:Sat) for the given date
// Wiki "Determination of the day of the week" for the algorithm
int Date::getDayOfWeek(int y, int m, int d) {
int centuryTable[] = {4, 2, 0, 6, 4, 2, 0, 6}; // 17xx, 18xx, ...
int MonthTable[] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
int MonthLeapYearTable[] = {6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
int century = y / 100;
int twoDigitYear = y % 100;
int centuryTableIndex = (century - 17) % 8;
// Date before 17xx are not valid, but needed to prevent negative index
if (centuryTableIndex < 0) {
centuryTableIndex += 8;
}
int sum = centuryTable[centuryTableIndex] + twoDigitYear + twoDigitYear / 4;
if (isLeapYear(y)) {
sum += MonthLeapYearTable[m-1];
} else {
sum += MonthTable[m-1];
}
sum += d;
return sum % 7;
}
// Constructor
Date::Date(int y, int m, int d) {
setDate(y, m, d);
}
// With Input validation
void Date::setDate(int y, int m, int d) {
setYear(y);
setMonth(m);
setDay(d); // need to set the day after year and month
}
int Date::getYear() const {
return year;
}
void Date::setYear(int y) {
if (y >= YEAR_MIN && y <= YEAR_MAX) {
year = y;
} else {
throw invalid_argument("Error: Invalid year (1753-9999)!");
}
}
int Date::getMonth() const {
return month;
}
void Date::setMonth(int m) {
if (m >= 1 && m <= 12) {
month = m;
} else {
throw invalid_argument("Error: Invalid month (1-12)!");
}
}
int Date::getDay() const {
return day;
}
// Assuming that the year and month are already set
void Date::setDay(int d) {
int lastDayOfMonth = DAYS_IN_MONTHS[month-1];
if (month == 2 && isLeapYear(year)) {
lastDayOfMonth = 29;
}
if (d >= 1 && d <= lastDayOfMonth) {
day = d;
} else {
throw invalid_argument("Error: Invalid day (1-28|29|30|31)!");
}
}
// Print this instance in the format "xxxday, d mmm yyyy".
void Date::print() const {
cout << STR_DAYS[getDayOfWeek(year, month, day)] << ", "
<< day << " " << STR_MONTHS[month-1] << " " << year << endl;
}
// Increment this instance to the next day and return this instance by reference
Date& Date::nextDay() {
int lastDayOfMonth = DAYS_IN_MONTHS[month-1];
if (month == 2 && isLeapYear(year)) {
lastDayOfMonth = 29;
}
// check day against the end of month
if (++day > lastDayOfMonth) {
day = 1;
if (++month > 12) {
month = 1;
if (++year > YEAR_MAX) {
throw out_of_range("Error: Next day is out of range!");
}
}
}
return *this;
}
// Decrement this instance to the previous day and return this instance by reference
Date& Date::previousDay() {
int lastDayOfMonth = DAYS_IN_MONTHS[month-1];
if (month == 2 && isLeapYear(year)) {
lastDayOfMonth = 29;
}
// check day against the end of month
if (--day < 1) {
day = lastDayOfMonth;
if (--month < 1) {
month = 12;
if (--year < YEAR_MIN) {
throw out_of_range("Error: Previous day is out of range!");
}
}
}
return *this;
}
// Increment this instance to the next month and return this instance by reference
Date& Date::nextMonth() {
if (++month > 12) {
month = 1;
if (++year > YEAR_MAX) {
throw out_of_range("Error: Next month is out of range!");
}
}
// may need to adjust the last day of the month
int lastDayOfMonth = DAYS_IN_MONTHS[month-1];
if (month == 2 && isLeapYear(year)) {
lastDayOfMonth = 29;
}
if (day > lastDayOfMonth) {
day = lastDayOfMonth;
}
return *this;
}
// Decrement this instance to the previous month and return this instance by reference
Date& Date::previousMonth() {
if (--month < 1) {
month = 12;
if (--year < YEAR_MIN) {
throw out_of_range("Error: Previous month is out of range!");
}
}
// may need to adjust the last day of the month
int lastDayOfMonth = DAYS_IN_MONTHS[month-1];
if (month == 2 && isLeapYear(year)) {
lastDayOfMonth = 29;
}
if (day > lastDayOfMonth) {
day = lastDayOfMonth;
}
return *this;
}
// Increment this instance to the next year and return this instance by reference
Date& Date::nextYear() {
if (++year > YEAR_MAX) {
throw out_of_range("Error: Next year is out of range!");
}
// may need to adjust the last day of the month for leap year (29 Feb)
// to non-leap year (28 Feb)
if (month == 2 && day == 29 && !isLeapYear(year)) {
day = 28;
}
return *this;
}
// Decrement this instance to the previous year and return this instance by reference
Date& Date::previousYear() {
if (--year < YEAR_MIN) {
throw out_of_range("Error: Previous year is out of range!");
}
// may need to adjust the last day of the month for leap year (29 Feb)
// to non-leap year (28 Feb)
if (month == 2 && day == 29 && !isLeapYear(year)) {
day = 28;
}
return *this;
}
|