#
// created by ztwaker on 2006-8-24
// Used for: count days
// No guarantees offered. Constructive comments to waker615@gmail.com
// 需求:计算两个日期之间相距天数。
// 应用:倒计时等
#include <iostream>
#include <algorithm>
namespace date {
//#define min(a, b) (((a) > (b)) ? (b) : (a))
//#define max(a, b) (((a) > (b)) ? (a) : (b))
class Bad_date {}; // exception throw
class Bad_year : public Bad_date {};
class Bad_month : public Bad_date {};
class Bad_day : public Bad_date {};
static const int this_year = 2006;
inline bool leapyear(int year)
{
//if (year > this_year)
// throw Bad_year();
return ((year % 100==0) ? (year % 400==0) : (year % 4==0));
}
inline int yday(int year)
{
//if (year > this_year)
// throw Bad_year();
return (365 + leapyear(year));
}
inline int mday(int month, int year)
{
switch(month) {
case 1: case 3: case 5:
case 7: case 8: case 10:
case 12:
return 31;
case 4: case 6: case 9:
case 11:
return 30;
case 2:
return 28 + leapyear(year);
default:
throw Bad_month();
}
throw Bad_month();
}
class Date{
int y, m, d;
public:
Date(int year, int month, int day)
{
// check year/month/day available
if (0 == year)
throw Bad_year();
if (1 > month || 12 < month)
throw Bad_month();
if (1 > day || mday(month, year) < day)
throw Bad_day();
y = year; m = month; d = day;
}
Date(const Date& rhs)
{
this->y = rhs.year();
this->m = rhs.month();
this->d = rhs.day();
}
Date& operator=(const Date& rhs)
{
if (rhs == (*this))
return (*this);
this->y = rhs.year();
this->m = rhs.month();
this->d = rhs.day();
return (*this);
}
int year () const { return y; }
int month() const { return m; }
int day () const { return d; }
int passday() const
{
int dpass = 0;
for (int i = 1; i != m; ++i)
{
dpass += mday(i, y);
}
return (dpass + d);
}
friend std::ostream& operator<<(std::ostream& os, const Date& rhs);
friend bool operator==(const Date& lhs, const Date& rhs);
friend bool operator!=(const Date& lhs, const Date& rhs);
friend bool operator< (const Date& lhs, const Date& rhs);
friend bool operator> (const Date& lhs, const Date& rhs);
friend bool operator<=(const Date& lhs, const Date& rhs);
friend bool operator>=(const Date& lhs, const Date& rhs);
friend int distant(const Date& lhs, const Date& rhs);
};
inline std::ostream& operator<<(std::ostream& os, const Date& rhs)
{
return (os << rhs.y << "-" << rhs.m << "-" << rhs.d);
}
inline bool operator==(const Date& lhs, const Date& rhs)
{
return (lhs.y == rhs.y && lhs.m == rhs.m && lhs.d == rhs.d);
}
inline bool operator!=(const Date& lhs, const Date& rhs)
{
return (!(lhs==rhs));
}
inline bool operator<(const Date& lhs, const Date& rhs)
{
// compare year
if (lhs.y < rhs.y)
{
return true;
}
else if (lhs.y == rhs.y)
{
// compare month
if (lhs.m < rhs.m)
{
return true;
}
else if (lhs.m == rhs.m)
{
// compare day
if (lhs.d < rhs.d)
return true;
else
return false;
}
return false;
}
return false;
}
inline bool operator>(const Date& lhs, const Date& rhs)
{
// compare year
if (lhs.y > rhs.y)
{
return true;
}
else if (lhs.y == rhs.y)
{
// compare month
if (lhs.m > rhs.m)
{
return true;
}
else if (lhs.m == rhs.m)
{
// compare day
if (lhs.d > rhs.d)
return true;
else
return false;
}
return false;
}
return false;
}
inline bool operator<=(const Date& lhs, const Date& rhs)
{
return (!(lhs>rhs));
}
inline bool operator>=(const Date& lhs, const Date& rhs)
{
return (!(lhs<rhs));
}
int distant(const Date& lhs, const Date& rhs)
{
int distance = 0;
const int lowyear = std::min(lhs.y, rhs.y);
const int highyear = std::max(lhs.y, rhs.y);
for (int yn = lowyear; yn != highyear; ++yn)
{
distance += yday(yn);
}
return (
distance - std::min(lhs, rhs).passday()
+ std::max(lhs, rhs).passday()
);
}
} // end of namespace date
void test()
{
try {
date::Date today(2006, 1, 29); // 丙戌年春节
date::Date deadline(2007, 2, 18); // 丁亥年春节
std::cout << "From "<< today << " to " << deadline << " is ";
std::cout << date::distant(today, deadline) << " days left.\n";
}
catch (date::Bad_year) {
std::cout << "Bad year" << std::endl;
}
catch (date::Bad_month) {
std::cout << "Bad month" << std::endl;
}
catch (date::Bad_day) {
std::cout << "Bad day" << std::endl;
}
catch (date::Bad_date) {
std::cout << "Bad date" << std::endl;
}
}
int main()
{
test();
return 0;
}