1 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,102 @@ |
1 |
+/* |
|
2 |
+ * dayslib.c |
|
3 |
+ * |
|
4 |
+ * Small library to handle dates. The algorithms are mostly from Pascal's SWAG. |
|
5 |
+ * |
|
6 |
+ * History: |
|
7 |
+ * 1/11/03 Creation from the old sources of ohdatabank. |
|
8 |
+ * 8/01/04 Fix the yday2wday() function. Also generalize the formula |
|
9 |
+ * for a wider range of years (that is, pass the 2099 barrier). |
|
10 |
+ * 15/09/06 Fix some comments, protect the macro GetYearDays. |
|
11 |
+ * |
|
12 |
+ * Author: Dario Rodriguez dario@softhome.net |
|
13 |
+ * This code is dual licensed under the terms of the GNU LGPL/3-clause BSD. |
|
14 |
+ */ |
|
15 |
+ |
|
16 |
+/* Constants */ |
|
17 |
+const int __NAcDaysNoLeap[13]= |
|
18 |
+ {0,31,59,90,120,151,181,212,243,273,304,334,365}; |
|
19 |
+const int __NAcDaysLeap[13]= |
|
20 |
+ {0,31,60,91,121,152,182,213,244,274,305,335,366}; |
|
21 |
+ |
|
22 |
+int * |
|
23 |
+GetYearDays(int year) |
|
24 |
+{ |
|
25 |
+ return(((((year)%4)==0 && !(((year)%100)==0)) \ |
|
26 |
+ || ((year)%400)==0)?__NAcDaysLeap:__NAcDaysNoLeap); |
|
27 |
+} |
|
28 |
+ |
|
29 |
+/* Function prototypes */ |
|
30 |
+int yday2mday(int year, int yday, int *month, int *day); |
|
31 |
+int mday2yday(int year, int month, int day, int *yday); |
|
32 |
+int yday2wday(int year, int yday, int *wday); |
|
33 |
+ |
|
34 |
+/* Function bodies */ |
|
35 |
+/* yday2mday(): returns the day-in-month of the specified day-in-year */ |
|
36 |
+int |
|
37 |
+yday2mday(int year, int yday, int *month, int *day) |
|
38 |
+{ |
|
39 |
+ const int *NAcDays; |
|
40 |
+ NAcDays=GetYearDays(year); |
|
41 |
+ for(*month=1;yday>NAcDays[*month];(*month)++) |
|
42 |
+ ; |
|
43 |
+ *day=yday-NAcDays[(*month)-1]; |
|
44 |
+ return(year); |
|
45 |
+} |
|
46 |
+ |
|
47 |
+/* yday2mday(): returns the day-in-year of the specified day-in-month */ |
|
48 |
+int |
|
49 |
+mday2yday(int year, int month, int day, int *yday) |
|
50 |
+{ |
|
51 |
+ const int *NAcDays; |
|
52 |
+ NAcDays=GetYearDays(year); |
|
53 |
+ *yday=NAcDays[month-1]+day; |
|
54 |
+ return(year); |
|
55 |
+} |
|
56 |
+ |
|
57 |
+/* yday2mday(): returns the weekday (0:sunday) of the specified day-in-year */ |
|
58 |
+/* Warning: formula only valid for 1900- */ |
|
59 |
+int |
|
60 |
+yday2wday(int year, int yday, int *wday) |
|
61 |
+{ |
|
62 |
+#if 0 |
|
63 |
+ /* Simplified formula, valid only 1901-2099 */ |
|
64 |
+ *wday=(((year+3)/4)+year+4+yday)%7; |
|
65 |
+#else |
|
66 |
+ /* Full-blown formula, valid from 1900 onwards */ |
|
67 |
+ /* (ok, it works for years earlier to 1900, but I'm not sure when */ |
|
68 |
+ /* Also, it varies from country to country when they adopted the */ |
|
69 |
+ /* current calendary... see your encyclopaedia for more info on this).*/ |
|
70 |
+ *wday=(((year+3)/4)+year+4+yday-((year-1)/100-19)+((year-1)/400-4))%7; |
|
71 |
+#endif |
|
72 |
+ return(year); |
|
73 |
+} |
|
74 |
+ |
|
75 |
+#ifdef UNIT_TESTING |
|
76 |
+#include <stdio.h> |
|
77 |
+int |
|
78 |
+main(void) |
|
79 |
+{ |
|
80 |
+ struct { |
|
81 |
+ int day; |
|
82 |
+ int month; |
|
83 |
+ int year; |
|
84 |
+ int wday; |
|
85 |
+ } Tests[]={{1,1,2003,3},{31,12,2003,3},{1,1,2004,4},{1,2,2004,0},{1,3,2004,1}, |
|
86 |
+ {1,1,2000,6},{1,1,2001,1},{1,1,2002,2},{1,1,2003,3},{1,1,2004,4},{1,1,2005,6}, |
|
87 |
+ {1,1,2099,4},{1,1,2100,5},{1,1,2101,6},{1,1,2102,0},{1,7,2087,2}, |
|
88 |
+ {1,1,1897,5},{1,1,1898,6},{1,1,1899,0},{1,1,1900,1},{1,1,1901,2}, |
|
89 |
+ {12,10,2008,0},{0}}; |
|
90 |
+ long i; |
|
91 |
+ int day,month,year,wday; |
|
92 |
+ int resyday,reswday; |
|
93 |
+ for(i=0;Tests[i].day>=1;i++) { |
|
94 |
+ day=Tests[i].day,month=Tests[i].month; |
|
95 |
+ year=Tests[i].year,wday=Tests[i].wday; |
|
96 |
+ mday2yday(year,month,day,&resyday); |
|
97 |
+ yday2wday(year,resyday,&reswday); |
|
98 |
+ printf("%2i/%02i/%04i(%i) -> yday:%i,wday:%i... %s\n",day,month,year,wday,resyday,reswday,(wday!=reswday)?"ERROR":"Ok"); |
|
99 |
+ } |
|
100 |
+ return(0); |
|
101 |
+} |
|
102 |
+#endif |