#if ! defined(_DATE_H_) /* 避免重複 include */ #define _DATE_H_ typedef struct { /* 日期型別 */ int year; /* 年 */ short month, day; /* 月, 日 */ } date; int weekday(date d); date date_add(date d, int n); int date_sub(date d, date e); int is_leap_year(int year); #endif /* 名稱: date.c 作者: 洪朝貴 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; } int 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 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; 0= n) { /* 如果正好是月初變月底 ... */ n = days_in_month[--k]; /* 改成上個月的最後一天 */ if (2==k) ++n; /* 當然要記得二月是廿九天 */ } } result.month = k; result.day = n; return result; } int weekday(date d) /* d 這一天是星期幾? (週日以 0 表示) */ { return date_to_int(d) % 7; } date date_add(date d, int n) /* 從 d 這一天開始, 再過 n 天是那一天? */ { return int_to_date(date_to_int(d) + n); } int date_sub(date d, date e) /* d 這一天在 e 這一天之後多少天? */ { return date_to_int(d) - date_to_int(e); } #if defined(TEST) /* 測試程式: 以 "gcc -Wall -DTEST date.c" 編譯, 以 "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 (progname == NULL) progname = argv[0]; fprintf(stderr, "Usage: %s year month day\n", progname); exit(1); } x.year = atoi(argv[1]); x.month = atoi(argv[2]); x.day = atoi(argv[3]); n = date_to_int(x); printf("%d (%d)\n", n, weekday(x)); x = int_to_date(n); printf("%d %d %d\n", x.year, x.month, x.day); x = date_add(x, 3); printf("\n3 days later...\n"); n = date_to_int(x); printf("%d (%d)\n", n, weekday(x)); printf("%d %d %d\n", x.year, x.month, x.day); return 0; } #endif