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:
52:
53: #include <basic.h>
54: #include <ctype.h>
55: #include <errno.h>
56: #include <t2ex/datetime.h>
57: #include "internal.h"
58:
59:
60: Inline ER update_tz( struct tzinfo* tz )
61: {
62: if (tz->tzname[0][0] == '\0') {
63: ER er = dt_getsystz(tz);
64: if (er < E_OK) {
65: return er;
66: }
67: }
68: return (tz->tzname[0][0] != '\0') ? E_OK : EX_INVAL;
69: }
70:
71:
72: LOCAL void update_gv(int gv[2], const struct tm *t)
73: {
74: int k, v, d;
75:
76:
77: if (gv[1] >= 0) return;
78:
79: k = (t -> tm_wday - t -> tm_yday + (53 * 7) + 6) % 7;
80: v = ((k > 3) ? 1 : 0) + (t -> tm_yday + k + 1) / 7;
81:
82: if (v > 0) {
83:
84: gv[0] = t->tm_year;
85: gv[1] = v;
86: }
87: else {
88:
89: d = 365 + (isleap(1900 + t -> tm_yday - 1) ? 1 : 0);
90: k = ( k + (53 * 7) - d) % 7;
91: v = ((k > 3) ? 1 : 0) + (d + t -> tm_yday + k + 1) / 7;
92:
93: gv[0] = t->tm_year - 1;
94: gv[1] = v;
95: }
96: }
97:
98:
99: LOCAL int put( const char c, const struct tm *t, char **p, int *siz, struct tzinfo* tz, int gv[2] )
100: {
101: ER er;
102: int k; const char *q;
103:
104: switch (c) {
105: case 'd' :
106: case 'm' :
107: case 'y' :
108: case 'H' :
109: case 'I' :
110: case 'M' :
111: case 'S' :
112: case 'C' :
113: case 'U' :
114: case 'W' :
115: case 'V' :
116: case 'g' :
117: if (c == 'd') {
118: k = t -> tm_mday;
119: }
120: else if (c == 'm') {
121: k = t -> tm_mon + 1;
122: }
123: else if (c == 'y') {
124: k = t -> tm_year % 100;
125: }
126: else if (c == 'H') {
127: k = t -> tm_hour;
128: }
129: else if (c == 'I') {
130: k = ((t -> tm_hour + 11) % 12) + 1;
131: }
132: else if (c == 'M') {
133: k = t -> tm_min;
134: }
135: else if (c == 'S') {
136: k = t -> tm_sec;
137: }
138: else if (c == 'C') {
139: k = (t -> tm_year + 1900) / 100;
140: }
141: else if (c == 'U') {
142: k = (t -> tm_wday - t -> tm_yday + (53 * 7) + 6) % 7;
143: k = (t -> tm_yday + k + 1) / 7;
144: }
145: else if (c == 'W') {
146: k = (t -> tm_wday - t -> tm_yday + (53 * 7) + 5) % 7;
147: k = (t -> tm_yday + k + 1) / 7;
148: }
149: else if (c == 'V') {
150: update_gv(gv, t);
151: k = gv[1];
152: }
153: else {
154: update_gv(gv, t);
155: k = (gv[0] + 1900) % 100;
156: }
157: *siz -= 2; if (*siz < 0) return -1;
158: *(*p)++ = ((k / 10) % 10) + '0';
159: *(*p)++ = ((k) % 10) + '0';
160: break;
161: case 'u' :
162: case 'w' :
163:
164: k = (t -> tm_wday) + ((c == 'u') ? 1 : 0);
165: if (--*siz < 0) return -1;
166: *(*p)++ = ((k) % 10) + '0';
167: break;
168: case 'j' :
169:
170: k = t -> tm_yday + 1;
171: *siz -= 3; if (*siz < 0) return -1;
172: *(*p)++ = ((k / 100) % 10) + '0';
173: *(*p)++ = ((k / 10) % 10) + '0';
174: *(*p)++ = ((k) % 10) + '0';
175: break;
176: case 'Y' :
177: case 'G' :
178: if (c == 'Y') {
179: k = t -> tm_year + 1900;
180: }
181: else {
182: update_gv(gv, t);
183: k = gv[0] + 1900;
184: }
185: *siz -= 4; if (*siz < 0) return -1;
186: *(*p)++ = ((k / 1000) % 10) + '0';
187: *(*p)++ = ((k / 100) % 10) + '0';
188: *(*p)++ = ((k / 10) % 10) + '0';
189: *(*p)++ = ((k) % 10) + '0';
190: break;
191: case 'e' :
192:
193: k = t -> tm_mday;
194: *siz -= 2; if (*siz < 0) return -1;
195: *(*p)++ = ((k >= 10) ? ((k / 10) % 10) + '0' : ' ');
196: *(*p)++ = ((k) % 10) + '0';
197: break;
198: case 'a' :
199: case 'A' :
200: case 'b' :
201: case 'h' :
202: case 'B' :
203: case 'p' :
204: if (c == 'a') {
205: k = 3;
206: q = _dt_weeknm + ((sizeof(_dt_weeknm) / 7) * t -> tm_wday);
207: }
208: else if (c == 'A') {
209: k = sizeof(_dt_weeknm) / 7;
210: q = _dt_weeknm + (k * t -> tm_wday);
211: }
212: else if (c == 'b' || c == 'h') {
213: k = 3;
214: q = _dt_monthnm + ((sizeof(_dt_monthnm) / 12) * t -> tm_mon);
215: }
216: else if (c == 'B') {
217: k = sizeof(_dt_monthnm) / 12;
218: q = _dt_monthnm + (k * t -> tm_mon);
219: }
220: else {
221: k = sizeof(_dt_ampm) / 2;
222: q = _dt_ampm + (k * (t -> tm_hour >= 12));
223: }
224: while (k-- > 0) {
225: if (*q <= ' ') break;
226: if (--*siz < 0) return -1;
227: *(*p)++ = *q++;
228: }
229: break;
230: case 'x':
231: case 'D':
232:
233: put( 'm', t, p, siz, tz, gv );
234: if (--*siz < 0) return -1;
235: *(*p)++ = '/';
236: put( 'd', t, p, siz, tz, gv );
237: if (--*siz < 0) return -1;
238: *(*p)++ = '/';
239: put( 'y', t, p, siz, tz, gv );
240: break;
241: case 'F':
242:
243: put( 'Y', t, p, siz, tz, gv );
244: if (--*siz < 0) return -1;
245: *(*p)++ = '-';
246: put( 'm', t, p, siz, tz, gv );
247: if (--*siz < 0) return -1;
248: *(*p)++ = '-';
249: put( 'd', t, p, siz, tz, gv );
250: break;
251: case 'X':
252: case 'T':
253: case 'R':
254:
255: put( 'H', t, p, siz, tz, gv );
256: if (--*siz < 0) return -1;
257: *(*p)++ = ':';
258: put( 'M', t, p, siz, tz, gv );
259: if (c == 'R') break;
260: if (--*siz < 0) return -1;
261: *(*p)++ = ':';
262: put( 'S', t, p, siz, tz, gv );
263: break;
264: case 'r':
265:
266: put( 'I', t, p, siz, tz, gv );
267: if (--*siz < 0) return -1;
268: *(*p)++ = ':';
269: put( 'M', t, p, siz, tz, gv );
270: if (--*siz < 0) return -1;
271: *(*p)++ = ':';
272: put( 'S', t, p, siz, tz, gv );
273: if (--*siz < 0) return -1;
274: *(*p)++ = ' ';
275: put( 'p', t, p, siz, tz, gv );
276: break;
277: case 'c':
278:
279: put( 'a', t, p, siz, tz, gv );
280: if (--*siz < 0) return -1;
281: *(*p)++ = ' ';
282: put( 'b', t, p, siz, tz, gv );
283: if (--*siz < 0) return -1;
284: *(*p)++ = ' ';
285: put( 'd', t, p, siz, tz, gv );
286: if (--*siz < 0) return -1;
287: *(*p)++ = ' ';
288: put( 'X', t, p, siz, tz, gv );
289: if (--*siz < 0) return -1;
290: *(*p)++ = ' ';
291: put( 'Y', t, p, siz, tz, gv );
292: break;
293: case 'z':
294:
295: er = update_tz(tz);
296: if (er < E_OK) return -1;
297: k = tz->daylight ? tz->dst_offset : tz->offset;
298: if (k >= 0) {
299: *(*p)++ = '-';
300: }
301: else {
302: *(*p)++ = '+';
303: k = -k;
304: }
305: if (--*siz < 0) return -1;
306: *(*p)++ = ((k / (60 * 60) / 10) % 10) + '0';
307: if (--*siz < 0) return -1;
308: *(*p)++ = ((k / (60 * 60)) % 10) + '0';
309: if (--*siz < 0) return -1;
310: k %= (60 * 60);
311: *(*p)++ = ((k / 60 / 10) % 10) + '0';
312: if (--*siz < 0) return -1;
313: *(*p)++ = ((k / 60) % 10) + '0';
314: break;
315: case 'Z':
316:
317: er = update_tz(tz);
318: if (er < E_OK) return -1;
319: q = tz->tzname[tz->daylight ? 1 : 0];
320: for (k = 0; q[k] != '\0' && k < TZNAME_MAX; ) {
321: if (--*siz < 0) return -1;
322: *(*p)++ = q[k++];
323: }
324: break;
325: case 't':
326:
327: if (--*siz < 0) return -1;
328: *(*p)++ = '\t';
329: break;
330: }
331: return 0;
332: }
333:
334: 335: 336:
337: EXPORT int dt_strftime( char *s, size_t max, const char *format, const struct tm *tm, const struct tzinfo* tz )
338: {
339: struct tzinfo systz;
340: int c, n; const char *p; char d;
341: int gv[2] = {-1, -1};
342:
343: if (tz == NULL) {
344: systz.tzname[0][0] = '\0';
345: tz = &systz;
346: }
347: else if (tz->tzname[0][0] == '\0') {
348: return EX_INVAL;
349: }
350:
351: n = max;
352: for( p = format; (c = _dt_spec( &p, &d )); ) {
353: if (c == 1) {
354: if (--n < 0) goto err_ret;
355: *s++ = d;
356: }
357: else {
358: if (put( c, tm, &s, &n, (struct tzinfo*)tz, gv ) < 0) goto err_ret;
359: }
360: }
361:
362: *s = '\0';
363: return max - n;
364:
365: err_ret:
366:
367: return EX_RANGE;
368: }