1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45:
46: 47: 48: 49:
50:
51: #include <basic.h>
52: #include <errno.h>
53: #include <time.h>
54: #include <t2ex/datetime.h>
55:
56: #define TM_YEAR_BASE 1900
57: #define EPOCH_JD 2440588
58:
59: #define TZOFS(tz) (-(tz).offset)
60:
61: #define TZDST(tz) ((tz).daylight)
62:
63: LOCAL int gc2jd(int y, int m, int d)
64: {
65: int q, j;
66: m -= 3; if (m < 0) { m += 12; y--; }
67: j = 1721120;
68: if (y < 0) {
69: q = ((400 - 1) - y) / 400;
70: j -= q * (365 * 400 + 97); y += q * 400;
71: }
72: j += (y * 365) + (y / 4) - (y / 100) + (y / 400);
73: q = m / 5; j += q * (30 * 5 + 3); m -= q * 5;
74: q = m / 2; j += q * (30 * 2 + 1); m -= q * 2;
75: j += (m * 31) + d - 1;
76: return j;
77: }
78:
79: LOCAL void jd2gc(int j, int *yp, int *mp, int *dp)
80: {
81: int q, y, m;
82: j -= 1721120;
83: if (j < 0) {
84: q = (((365 * 400 + 97) - 1) - j) / (365 * 400 + 97);
85: j += q * (365 * 400 + 97); y = -q * 400;
86: } else {
87: q = j / (365 * 400 + 97);
88: j -= q * (365 * 400 + 97); y = q * 400;
89: }
90: q = j / (365 * 100 + 24); if (q == 4) q--; j -= q * (365 * 100 + 24); y += q * 100;
91: q = j / (365 * 4 + 1); j -= q * (365 * 4 + 1); y += q * 4;
92: q = j / 365; if (q == 4) q--; j -= q * 365; y += q;
93: q = j / (30 * 5 + 3); j -= q * (30 * 5 + 3); m = q * 5;
94: q = j / (30 * 2 + 1); j -= q * (30 * 2 + 1); m += q * 2;
95: q = j / 31; j -= q * 31; m += q + 3;
96: if (m > 12) { y++; m -= 12; }
97: *yp = y; *mp = m; *dp = j + 1;
98: }
99:
100: LOCAL ER get_tz(struct tzinfo *tz, errno_t *eno)
101: {
102: ER er;
103:
104: er = dt_getsystz( tz );
105: if (er < 0) goto e1;
106: return 0;
107:
108: e1: if (eno) *eno = EINVAL;
109: return er;
110: }
111:
112: EXPORT struct tm *gmtime_r_eno(const time_t *clock, struct tm *result, errno_t *eno)
113: {
114: int jd, y, m, d;
115: time_t jdt;
116:
117: result->tm_usec = 0;
118: result->tm_sec = *clock % 60;
119: result->tm_min = (*clock / 60) % 60;
120: result->tm_hour = (*clock / (60 * 60)) % 24;
121:
122: jd = jdt = (*clock / (24 * 60 * 60)) + EPOCH_JD;
123: if (jd != jdt) goto e1;
124: jd2gc( jd, &y, &m, &d );
125: result->tm_mday = d;
126: result->tm_mon = m - 1;
127: result->tm_year = y - TM_YEAR_BASE;
128:
129: result->tm_wday = (jd + 1) % 7;
130: result->tm_yday = jd - gc2jd( y, 1, 1 );
131: result->tm_isdst = 0;
132:
133: return result;
134:
135: e1: if (eno) *eno = EOVERFLOW;
136: return NULL;
137: }
138:
139: EXPORT struct tm *gmtime_r(const time_t *clock, struct tm *result)
140: {
141: return gmtime_r_eno(clock, result, NULL);
142: }
143:
144: EXPORT struct tm *localtime_r_eno(const time_t *clock, struct tm *result, errno_t *eno)
145: {
146: time_t t;
147: int d;
148: struct tzinfo tz;
149:
150: if (get_tz( &tz, eno ) != 0) goto e2;
151: d = TZOFS(tz);
152: t = *clock + d;
153: if (d >= 0) {
154: if (t < *clock) goto e1;
155: } else {
156: if (t >= *clock) goto e1;
157: }
158: if (gmtime_r_eno( &t, result, eno ) == NULL) goto e2;
159: result->tm_isdst = TZDST(tz);
160: return result;
161:
162: e1: if (eno) *eno = EOVERFLOW;
163: e2: return NULL;
164: }
165:
166: EXPORT struct tm *localtime_r(const time_t *clock, struct tm *result)
167: {
168: return localtime_r_eno(clock, result, NULL);
169: }
170:
171: EXPORT time_t mktime_eno(struct tm *tm, errno_t *eno)
172: {
173: int y;
174: time_t t;
175: struct tzinfo tz;
176:
177: y = tm->tm_year + TM_YEAR_BASE;
178: if (y <= -5000000 || y >= 5000000
179: || tm->tm_mon < 0 || tm->tm_mon >= 12) goto e1;
180: t = tm->tm_sec + (tm->tm_min * 60) + (tm->tm_hour * (60 * 60))
181: + ((time_t)(gc2jd(y, tm->tm_mon + 1, tm->tm_mday) - EPOCH_JD)
182: * (24 * 60 * 60));
183: if (gmtime_r_eno( &t, tm, eno ) == NULL) goto e2;
184: if (get_tz( &tz, eno ) != 0) goto e2;
185: tm->tm_isdst = TZDST(tz);
186: return t - TZOFS(tz);
187:
188: e1: if (eno) *eno = EOVERFLOW;
189: e2: return -1;
190: }
191:
192: EXPORT time_t mktime(struct tm *tm)
193: {
194: return mktime_eno(tm, NULL);
195: }