PostgreSQL Source Code: src/timezone/strftime.c Source File (original) (raw)
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
42
43#include <fcntl.h>
44
46
47
49{
60};
61
62#define Locale (&C_time_locale)
63
65 {
66 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
67 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
68 }, {
69 "January", "February", "March", "April", "May", "June",
70 "July", "August", "September", "October", "November", "December"
71 }, {
72 "Sun", "Mon", "Tue", "Wed",
73 "Thu", "Fri", "Sat"
74 }, {
75 "Sunday", "Monday", "Tuesday", "Wednesday",
76 "Thursday", "Friday", "Saturday"
77 },
78
79
80 "%H:%M:%S",
81
82
83
84
85
86
87
88 "%m/%d/%y",
89
90
91
92
93
94
95
96
97 "%a %b %e %T %Y",
98
99
100 "AM",
101
102
103 "PM",
104
105
106 "%a %b %e %H:%M:%S %Z %Y"
107};
108
110{
113
114static char *_add(const char *str, char *pt, const char *ptlim);
115static char *_conv(int n, const char *format, char *pt, const char *ptlim);
116static char *_fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim,
117 enum warn *warnp);
118static char *_yconv(int a, int b, bool convert_top, bool convert_yy, char *pt, char const *ptlim);
119
120
121
122
123
124
125
126
127size_t
129{
130 char *p;
131 int saved_errno = errno;
133
135 if (!p)
136 {
138 return 0;
139 }
140 if (p == s + maxsize)
141 {
142 errno = ERANGE;
143 return 0;
144 }
145 *p = '\0';
146 errno = saved_errno;
147 return p - s;
148}
149
150static char *
152 const char *ptlim, enum warn *warnp)
153{
155 {
157 {
160 {
161 case '\0':
163 break;
164 case 'A':
168 pt, ptlim);
169 continue;
170 case 'a':
174 pt, ptlim);
175 continue;
176 case 'B':
180 pt, ptlim);
181 continue;
182 case 'b':
183 case 'h':
187 pt, ptlim);
188 continue;
189 case 'C':
190
191
192
193
194
195
197 true, false, pt, ptlim);
198 continue;
199 case 'c':
200 {
202
203 pt = _fmt(Locale->c_fmt, t, pt, ptlim, &warn2);
206 if (warn2 > *warnp)
207 *warnp = warn2;
208 }
209 continue;
210 case 'D':
211 pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp);
212 continue;
213 case 'd':
215 continue;
216 case 'E':
217 case 'O':
218
219
220
221
222
223
224
226 case 'e':
228 continue;
229 case 'F':
230 pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp);
231 continue;
232 case 'H':
234 continue;
235 case 'I':
238 "%02d", pt, ptlim);
239 continue;
240 case 'j':
241 pt = _conv(t->tm_yday + 1, "%03d", pt, ptlim);
242 continue;
243 case 'k':
244
245
246
247
248
249
250
251
253 continue;
254#ifdef KITCHEN_SINK
255 case 'K':
256
257
258
259
260 pt = _add("kitchen sink", pt, ptlim);
261 continue;
262#endif
263 case 'l':
264
265
266
267
268
269
270
273 "%2d", pt, ptlim);
274 continue;
275 case 'M':
276 pt = _conv(t->tm_min, "%02d", pt, ptlim);
277 continue;
278 case 'm':
279 pt = _conv(t->tm_mon + 1, "%02d", pt, ptlim);
280 continue;
281 case 'n':
282 pt = _add("\n", pt, ptlim);
283 continue;
284 case 'p':
288 pt, ptlim);
289 continue;
290 case 'R':
291 pt = _fmt("%H:%M", t, pt, ptlim, warnp);
292 continue;
293 case 'r':
294 pt = _fmt("%I:%M:%S %p", t, pt, ptlim, warnp);
295 continue;
296 case 'S':
297 pt = _conv(t->tm_sec, "%02d", pt, ptlim);
298 continue;
299 case 'T':
300 pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp);
301 continue;
302 case 't':
303 pt = _add("\t", pt, ptlim);
304 continue;
305 case 'U':
308 "%02d", pt, ptlim);
309 continue;
310 case 'u':
311
312
313
314
315
316
319 "%d", pt, ptlim);
320 continue;
321 case 'V':
322 case 'G':
323 case 'g':
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 {
343 int year;
344 int base;
345 int yday;
347 int w;
348
353 for (;;)
354 {
356 int bot;
357 int top;
358
362
363
364
365
366
367 bot = ((yday + 11 - wday) %
369
370
371
372
373 top = bot -
375 if (top < -3)
377 top += len;
378 if (yday >= top)
379 {
380 ++base;
381 w = 1;
382 break;
383 }
384 if (yday >= bot)
385 {
386 w = 1 + ((yday - bot) /
388 break;
389 }
390 --base;
394 }
396 pt = _conv(w, "%02d",
397 pt, ptlim);
398 else if (*format == 'g')
399 {
401 pt = _yconv(year, base,
402 false, true,
403 pt, ptlim);
404 }
405 else
406 pt = _yconv(year, base,
407 true, true,
408 pt, ptlim);
409 }
410 continue;
411 case 'v':
412
413
414
415
416
417 pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp);
418 continue;
419 case 'W':
424 "%02d", pt, ptlim);
425 continue;
426 case 'w':
428 continue;
429 case 'X':
430 pt = _fmt(Locale->X_fmt, t, pt, ptlim, warnp);
431 continue;
432 case 'x':
433 {
435
436 pt = _fmt(Locale->x_fmt, t, pt, ptlim, &warn2);
439 if (warn2 > *warnp)
440 *warnp = warn2;
441 }
442 continue;
443 case 'y':
446 false, true,
447 pt, ptlim);
448 continue;
449 case 'Y':
451 true, true,
452 pt, ptlim);
453 continue;
454 case 'Z':
457
458
459
460
461
462
463 continue;
464 case 'z':
465 {
466 long diff;
467 char const *sign;
468 bool negative;
469
471 continue;
473 negative = diff < 0;
474 if (diff == 0)
475 {
477 negative = t->tm_zone[0] == '-';
478 }
479 if (negative)
480 {
482 diff = -diff;
483 }
484 else
490 pt = _conv(diff, "%04d", pt, ptlim);
491 }
492 continue;
493 case '+':
494 pt = _fmt(Locale->date_fmt, t, pt, ptlim,
495 warnp);
496 continue;
497 case '%':
498
499
500
501
502
503
504 default:
505 break;
506 }
507 }
508 if (pt == ptlim)
509 break;
511 }
512 return pt;
513}
514
515static char *
516_conv(int n, const char *format, char *pt, const char *ptlim)
517{
519
521 return _add(buf, pt, ptlim);
522}
523
524static char *
525_add(const char *str, char *pt, const char *ptlim)
526{
527 while (pt < ptlim && (*pt = *str++) != '\0')
528 ++pt;
529 return pt;
530}
531
532
533
534
535
536
537
538
539
540static char *
541_yconv(int a, int b, bool convert_top, bool convert_yy,
542 char *pt, const char *ptlim)
543{
544 int lead;
545 int trail;
546
547#define DIVISOR 100
551 if (trail < 0 && lead > 0)
552 {
554 --lead;
555 }
556 else if (lead < 0 && trail > 0)
557 {
559 ++lead;
560 }
561 if (convert_top)
562 {
563 if (lead == 0 && trail < 0)
564 pt = _add("-0", pt, ptlim);
565 else
566 pt = _conv(lead, "%02d", pt, ptlim);
567 }
568 if (convert_yy)
569 pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
570 return pt;
571}
#define INT_STRLEN_MAXIMUM(type)
static char * _add(const char *str, char *pt, const char *ptlim)
static char * _fmt(const char *format, const struct pg_tm *t, char *pt, const char *ptlim, enum warn *warnp)
static char * _yconv(int a, int b, bool convert_top, bool convert_yy, char *pt, char const *ptlim)
static char * _conv(int n, const char *format, char *pt, const char *ptlim)
size_t pg_strftime(char *s, size_t maxsize, const char *format, const struct pg_tm *t)
static const struct lc_time_T C_time_locale
const char * mon[MONSPERYEAR]
const char * weekday[DAYSPERWEEK]
const char * wday[DAYSPERWEEK]
const char * month[MONSPERYEAR]