C++实现Date日期类

定义一个Date类,包含三个属性年、月、日

实现了如下功能:

  1. 年月日的增加、减少:2017年10月1日加上100个月30天是2025年5月31日
  2. 输出某天是星期几:2017年10月1日是星期日
  3. 判断某一年是否是闰年:2020年是闰年
  4. 下一个工作日(周末)日期: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 }
代码实现

 

posted @ 2017-10-10 18:45  ,,,沙子,,,  阅读(4552)  评论(0编辑  收藏  举报