#if ! defined(_DATE_H_) #define _DATE_H_ class date { /* 日期型別 */ public: int year; /* 年 */ short month, day; /* 月, 日 */ int weekday() const; date operator +(int n) const; int operator -(date const & e) const; }; bool is_leap_year(int year); #endif /* 名稱: date.cc 作者: 洪朝貴 http://www.cyut.edu.tw/~ckhung/ 功能: 日期模組 技巧: 為避免在許多副程式中重複撰寫麻煩的閏年運算, 設計兩個 僅供內部使用的轉換程式 date_to_int() 及 int_to_date(). 欲作任何需要考慮閏年的運算時, 先將日期轉換為流水日期 (以 1753 年 1 月 1 日為基準), 作簡單的算術運算, 最後 再轉換為西歷. */ /* #include "date.h" */ #include static int days_in_month[] = { 0, /* 每個月有多少天 */ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static int days_upto_year(int year) /* 從基準日 1753 年一月一日起到 year 年一月一日止, 共經過了多少天? */ { return (year-1753) * 365 + (year-1753) / 4 - (year-1701) / 100 + (year-1601) / 400; } bool is_leap_year(int year) /* year 這一年是否為閏年? */ { if (year % 4) return 0; if (year % 100) return 1; return ! (year % 400); } static int date_to_int(date const & d) /* 以基準日 1753 年一月一日為第一天, 則 d 這一天是第幾天? */ { int n, i; n = days_upto_year(d.year); /* 今年之前的日數 */ for (i=1; i= n) { /* 過頭了, 估計到去年就好 */ --result.year; k = days_upto_year(result.year); } n -= k; /* 今年已過了多少天? */ assert(0 < n && 366 >= n); for (k=1; n>0; ++k) /* n 這麼多天究竟到幾月了? */ n -= days_in_month[k]; n += days_in_month[--k]; /* 現在 k 大約就是月份, n 大約就是日期了 */ /* 但是如果是閏年而且是二月以後 ... */ if (is_leap_year(result.year) && 2= n) { /* 如果正好是月初變月底 ... */ n = days_in_month[--k]; /* 改成上個月的最後一天 */ if (k==2) ++n; /* 當然要記得二月是廿九天 */ } } result.month = k; result.day = n; return result; } int date::weekday() const /* d 這一天是星期幾? (週日以 0 表示) */ { return date_to_int(*this) % 7; } date date::operator +(int n) const /* 從 d 這一天開始, 再過 n 天是那一天? */ { return int_to_date(date_to_int(*this) + n); } int date::operator -(date const & e) const /* d 這一天在 e 這一天之後多少天? */ { return date_to_int(*this) - date_to_int(e); } #if defined(TEST) /* 測試程式: 以 "g++ -Wall -DTEST date.cc" 編譯, 以 "a.out 1999 12 30" 測試 */ #include #include #include int main(int argc, char *argv[]) { date x; int n; char const * progname; if (4 != argc) { progname = strrchr(argv[0], '/'); if (NULL == progname) progname = argv[0]; cerr << "Usage: " << progname << " year month day\n"; exit(1); } x.year = atoi(argv[1]); x.month = atoi(argv[2]); x.day = atoi(argv[3]); n = date_to_int(x); cout << n << " (" << x.weekday() << ")\n"; x = int_to_date(n); cout << x.year << ' ' << x.month << ' ' << x.day << '\n'; x = x + 3; cout << "\n3 days later...\n"; cout << date_to_int(x) << " (" << x.weekday() << ")\n"; cout << x.year << ' ' << x.month << ' ' << x.day << '\n'; return 0; } #endif