C++实现Date日期类
定义一个Date类,包含三个属性年、月、日
实现了如下功能:
- 年月日的增加、减少:2017年10月1日加上100个月30天是2025年5月31日
- 输出某天是星期几:2017年10月1日是星期日
- 判断某一年是否是闰年:2020年是闰年
- 下一个工作日(周末)日期:2010年10月2日下一个周末是10月8日
1 class Date 2 { 3 public: 4 Date(); 5 Date(int yy, Month mm, int dd); 6 int day() const { return m_day; } 7 int year() const { return m_year; } 8 Month month() const { return m_month; } 9 10 void add_day(int dd);//增加或减少天数 11 void add_month(int mm);//增加或减少月份 12 void add_year(int yy);//增加或减少年份 13 14 private: 15 int m_year; 16 Month m_month; 17 int m_day; 18 }; 19 //判断日期是否合法 20 bool is_date(int y, Month m, int d); 21 //判断是否为闰年 22 bool leapyear(int y); 23 //两个Date是否相等 24 bool operator==(const Date &a, const Date &b); 25 bool operator!=(const Date &a, const Date &b); 26 //Date输入输出 27 ostream &operator<<(ostream &os, const Date &d); 28 istream &operator>>(istream &is, Date &dd); 29 //今天是星期几 30 Day day_of_week(const Date &date); 31 ostream &operator<<(ostream &os, const Day &d); 32 //下一个周末 33 Date next_Sunday(const Date &d); 34 //下一个工作日 35 Date next_weekday(const Date &d);
具体的实现代码如下:
1 #include <iostream> 2 #include <vector> 3 #include <string> 4 5 using std::istream; 6 using std::ostream; 7 using std::vector; 8 using std::ios_base; 9 using std::string; 10 11 namespace Chrono 12 { 13 class InvalidDate 14 { 15 public: 16 std::string what() { return "InValid Date Occured"; }; 17 }; 18 19 enum class Month 20 { 21 jan = 1, //January 22 feb, //February 23 mar, //March 24 apr, //April 25 may, //May 26 jun, //June 27 jul, //July 28 aug, //August 29 sep, //September 30 oct, //October 31 nov, //November 32 dec //December 33 }; 34 35 enum class Day 36 { 37 sun, //sunday 38 mon, //monday 39 tue, //tuesday 40 wed, //wednesday 41 thu, // thursday 42 fri, //friday 43 sat //saturday 44 }; 45 46 class Date 47 { 48 public: 49 Date(); 50 Date(int yy, Month mm, int dd); 51 int day() const { return m_day; } 52 int year() const { return m_year; } 53 Month month() const { return m_month; } 54 55 void add_day(int dd); 56 void add_month(int mm); 57 void add_year(int yy); 58 59 private: 60 int m_year; 61 Month m_month; 62 int m_day; 63 }; 64 65 bool is_date(int y, Month m, int d); 66 bool leapyear(int y); 67 bool operator==(const Date &a, const Date &b); 68 bool operator!=(const Date &a, const Date &b); 69 ostream &operator<<(ostream &os, const Date &d); 70 istream &operator>>(istream &is, Date &dd); 71 Day day_of_week(const Date &date); 72 ostream &operator<<(ostream &os, const Day &d); 73 74 Date next_Sunday(const Date &d); 75 Date next_weekday(const Date &d); 76 77 //////////////////////////////////////////////////////////////////////////////// 78 //Implements ///// 79 //////////////////////////////////////////////////////////////////////////////// 80 Date::Date(int yy, Month mm, int dd) : m_year(yy), m_month(mm), m_day(dd) 81 { 82 if (!is_date(yy, mm, dd)) 83 throw InvalidDate{}; 84 } 85 86 const Date &default_date() 87 { 88 static const Date d{2001, Month::jan, 1}; 89 return d; 90 } 91 92 Date::Date() : m_year(default_date().year()), 93 m_month(default_date().month()), 94 m_day(default_date().day()) {} 95 96 void Date::add_day(int dd) 97 { 98 if (dd > 0) 99 { 100 for (; dd > 0; --dd) 101 { 102 int temp_d = m_day + 1; 103 switch (month()) 104 { 105 case Month::feb: 106 if ((leapyear(m_year) && temp_d > 29) || (!leapyear(m_year) && temp_d > 28)) 107 { 108 temp_d = 1; 109 m_month = Month::mar; 110 } 111 break; 112 case Month::apr: 113 case Month::jun: 114 case Month::sep: 115 case Month::nov: 116 if (temp_d > 30) 117 { 118 temp_d = 1; 119 m_month = Month((int)m_month + 1); 120 } 121 break; 122 case Month::dec: 123 if (temp_d > 31) 124 { 125 temp_d = 1; 126 m_month = Month::jan; 127 m_year += 1; 128 } 129 break; 130 default: 131 if (temp_d > 31) 132 { 133 temp_d = 1; 134 m_month = Month((int)m_month + 1); 135 } 136 break; 137 } 138 m_day = temp_d; 139 } 140 } 141 else if (dd < 0) 142 { 143 for (; dd < 0; ++dd) 144 { 145 int temp_d = day() - 1; 146 if (temp_d <= 0) 147 { 148 switch (month()) 149 { 150 case Month::jan: 151 m_month = Month::dec; 152 temp_d = 31; 153 m_year -= 1; 154 break; 155 case Month::mar: 156 m_month = Month::feb; 157 if (leapyear(m_year)) 158 temp_d = 29; 159 else 160 temp_d = 28; 161 break; 162 case Month::feb: 163 case Month::apr: 164 case Month::jun: 165 case Month::oct: 166 case Month::sep: 167 case Month::nov: 168 temp_d = 31; 169 m_month = Month((int)m_month - 1); 170 break; 171 default: 172 temp_d = 30; 173 m_month = Month((int)m_month - 1); 174 break; 175 } 176 } 177 m_day = temp_d; 178 } 179 } 180 } 181 182 void Date::add_month(int month) 183 { 184 int temp_y = month / 12 + m_year; 185 int temp_m = month % 12 + (int)m_day; 186 187 if (temp_y <= 0) 188 { 189 temp_y--; 190 temp_m = temp_m + 12; 191 } 192 else if (temp_m > 12) 193 { 194 temp_y++; 195 temp_m = temp_m - 12; 196 } 197 m_year = temp_y; 198 m_month = Month(temp_m); 199 switch (m_month) 200 { 201 case Month::feb: 202 if (leapyear(m_year) && m_day > 29) 203 m_day = 29; 204 else if (!leapyear(m_year) && m_day > 28) 205 m_day = 28; 206 break; 207 case Month::apr: 208 case Month::jun: 209 case Month::sep: 210 case Month::nov: 211 if (m_day > 30) 212 m_day = 30; 213 default: 214 break; 215 } 216 } 217 218 void Date::add_year(int n) 219 { 220 if (month() == Month::feb && day() == 29 && !leapyear(m_year + n)) 221 m_day = 28; 222 m_year += n; 223 } 224 225 bool is_date(int y, Month m, int d) 226 { 227 if (d <= 0) 228 return false; 229 if (m < Month::jan || m > Month::dec) 230 return false; 231 int days_in_month; 232 switch (m) 233 { 234 case Month::feb: 235 days_in_month = leapyear(y) ? 29 : 28; 236 break; 237 case Month::apr: 238 case Month::jun: 239 case Month::sep: 240 case Month::nov: 241 days_in_month = 30; 242 break; 243 default: 244 days_in_month = 31; 245 break; 246 } 247 if (days_in_month < d) 248 return false; 249 return true; 250 } 251 252 // https://en.wikipedia.org/wiki/Leap_year#Algorithm 253 bool leapyear(int y) 254 { 255 if (y % 4 != 0) 256 return false; 257 else if (y % 100 != 0) 258 return true; 259 else if (y % 400 != 0) 260 return false; 261 return true; 262 } 263 bool operator==(const Date &a, const Date &b) 264 { 265 return a.year() == b.year() && a.month() == b.month() && a.day() == b.day(); 266 } 267 268 bool operator!=(const Date &a, const Date &b) 269 { 270 return !(a == b); 271 } 272 273 ostream &operator<<(ostream &os, const Date &d) 274 { 275 return os << '(' << d.year() 276 << ',' << (int)d.month() 277 << ',' << d.day() << ')'; 278 } 279 280 ostream &operator<<(ostream &os, const Day &d) 281 { 282 vector<string> weekdays{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; 283 os << weekdays[(int)d]; 284 return os; 285 } 286 287 // format (2017,5,23) 288 istream &operator>>(istream &is, Date &d) 289 { 290 int yy, mm, dd; 291 char ch1, ch2, ch3, ch4; 292 is >> ch1 >> yy >> ch2 >> mm >> ch3 >> dd >> ch4; 293 if (!is) 294 return is; 295 if (ch1 != '(' || ch2 != ',' || ch3 != ',' || ch4 != ')') 296 is.clear(ios_base::failbit); 297 d = Date{yy, Month(mm), dd}; 298 return is; 299 } 300 301 // https://cs.uwaterloo.ca/~alopez-o/math-faq/node73.html 302 Day day_of_week(const Date &date) 303 { 304 int y = date.year(); 305 int m = (int)date.month(); 306 int d = date.day(); 307 y -= m < 3; 308 int day_of_week = (y + y / 4 - y / 100 + y / 400 + "-bed=pen+mad."[m] + d) % 7; 309 return Day(day_of_week); 310 } 311 Date next_Sunday(const Date &d) 312 { 313 Date d1 = d; 314 while (day_of_week(d1) != Day::sun) 315 { 316 d1.add_day(1); 317 } 318 return d1; 319 } 320 321 Date next_weekday(const Date &d) 322 { 323 Date d1 = d; 324 if (day_of_week(d1) == Day::sat) 325 d1.add_day(2); 326 else if (day_of_week(d1) == Day::fri) 327 d1.add_day(3); 328 else 329 d1.add_day(1); 330 return d1; 331 } 332 }