date 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of date might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/ext/date/date_core.c +9673 -0
- data/ext/date/date_parse.c +2998 -0
- data/ext/date/date_strftime.c +638 -0
- data/ext/date/date_strptime.c +703 -0
- data/ext/date/date_tmx.h +56 -0
- data/ext/date/extconf.rb +4 -0
- data/ext/date/prereq.mk +8 -0
- data/ext/date/zonetab.h +902 -0
- data/ext/date/zonetab.list +181 -0
- data/lib/date.rb +61 -0
- metadata +83 -0
@@ -0,0 +1,638 @@
|
|
1
|
+
/*
|
2
|
+
date_strftime.c: based on a public-domain implementation of ANSI C
|
3
|
+
library routine strftime, which is originally written by Arnold
|
4
|
+
Robbins.
|
5
|
+
*/
|
6
|
+
|
7
|
+
#include "ruby/ruby.h"
|
8
|
+
#include "date_tmx.h"
|
9
|
+
|
10
|
+
#include <stdlib.h>
|
11
|
+
#include <string.h>
|
12
|
+
#include <ctype.h>
|
13
|
+
#include <errno.h>
|
14
|
+
|
15
|
+
#if defined(HAVE_SYS_TIME_H)
|
16
|
+
#include <sys/time.h>
|
17
|
+
#endif
|
18
|
+
|
19
|
+
#undef strchr /* avoid AIX weirdness */
|
20
|
+
|
21
|
+
#define range(low, item, hi) (item)
|
22
|
+
|
23
|
+
#define add(x,y) (rb_funcall((x), '+', 1, (y)))
|
24
|
+
#define sub(x,y) (rb_funcall((x), '-', 1, (y)))
|
25
|
+
#define mul(x,y) (rb_funcall((x), '*', 1, (y)))
|
26
|
+
#define quo(x,y) (rb_funcall((x), rb_intern("quo"), 1, (y)))
|
27
|
+
#define div(x,y) (rb_funcall((x), rb_intern("div"), 1, (y)))
|
28
|
+
#define mod(x,y) (rb_funcall((x), '%', 1, (y)))
|
29
|
+
|
30
|
+
static void
|
31
|
+
upcase(char *s, size_t i)
|
32
|
+
{
|
33
|
+
do {
|
34
|
+
if (ISLOWER(*s))
|
35
|
+
*s = TOUPPER(*s);
|
36
|
+
} while (s++, --i);
|
37
|
+
}
|
38
|
+
|
39
|
+
static void
|
40
|
+
downcase(char *s, size_t i)
|
41
|
+
{
|
42
|
+
do {
|
43
|
+
if (ISUPPER(*s))
|
44
|
+
*s = TOLOWER(*s);
|
45
|
+
} while (s++, --i);
|
46
|
+
}
|
47
|
+
|
48
|
+
/* strftime --- produce formatted time */
|
49
|
+
|
50
|
+
static size_t
|
51
|
+
date_strftime_with_tmx(char *s, const size_t maxsize, const char *format,
|
52
|
+
const struct tmx *tmx)
|
53
|
+
{
|
54
|
+
char *endp = s + maxsize;
|
55
|
+
char *start = s;
|
56
|
+
const char *sp, *tp;
|
57
|
+
auto char tbuf[100];
|
58
|
+
ptrdiff_t i;
|
59
|
+
int v, w;
|
60
|
+
size_t colons;
|
61
|
+
int precision, flags;
|
62
|
+
char padding;
|
63
|
+
/* LOCALE_[OE] and COLONS are actually modifiers, not flags */
|
64
|
+
enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E, COLONS};
|
65
|
+
#define BIT_OF(n) (1U<<(n))
|
66
|
+
|
67
|
+
/* various tables for locale C */
|
68
|
+
static const char days_l[][10] = {
|
69
|
+
"Sunday", "Monday", "Tuesday", "Wednesday",
|
70
|
+
"Thursday", "Friday", "Saturday",
|
71
|
+
};
|
72
|
+
static const char months_l[][10] = {
|
73
|
+
"January", "February", "March", "April",
|
74
|
+
"May", "June", "July", "August", "September",
|
75
|
+
"October", "November", "December",
|
76
|
+
};
|
77
|
+
static const char ampm[][3] = { "AM", "PM", };
|
78
|
+
|
79
|
+
if (s == NULL || format == NULL || tmx == NULL || maxsize == 0)
|
80
|
+
return 0;
|
81
|
+
|
82
|
+
/* quick check if we even need to bother */
|
83
|
+
if (strchr(format, '%') == NULL && strlen(format) + 1 >= maxsize) {
|
84
|
+
err:
|
85
|
+
errno = ERANGE;
|
86
|
+
return 0;
|
87
|
+
}
|
88
|
+
|
89
|
+
for (; *format && s < endp - 1; format++) {
|
90
|
+
#define FLAG_FOUND() do { \
|
91
|
+
if (precision > 0 || flags & (BIT_OF(LOCALE_E) | BIT_OF(LOCALE_O) | BIT_OF(COLONS))) \
|
92
|
+
goto unknown; \
|
93
|
+
} while (0)
|
94
|
+
#define NEEDS(n) do if (s >= endp || (n) >= endp - s - 1) goto err; while (0)
|
95
|
+
#define FILL_PADDING(i) do { \
|
96
|
+
if (!(flags & BIT_OF(LEFT)) && precision > (i)) { \
|
97
|
+
NEEDS(precision); \
|
98
|
+
memset(s, padding ? padding : ' ', precision - (i)); \
|
99
|
+
s += precision - (i); \
|
100
|
+
} \
|
101
|
+
else { \
|
102
|
+
NEEDS(i); \
|
103
|
+
} \
|
104
|
+
} while (0);
|
105
|
+
#define FMT(def_pad, def_prec, fmt, val) \
|
106
|
+
do { \
|
107
|
+
int l; \
|
108
|
+
if (precision <= 0) precision = (def_prec); \
|
109
|
+
if (flags & BIT_OF(LEFT)) precision = 1; \
|
110
|
+
l = snprintf(s, endp - s, \
|
111
|
+
((padding == '0' || (!padding && (def_pad) == '0')) ? \
|
112
|
+
"%0*"fmt : "%*"fmt), \
|
113
|
+
precision, (val)); \
|
114
|
+
if (l < 0) goto err; \
|
115
|
+
s += l; \
|
116
|
+
} while (0)
|
117
|
+
#define STRFTIME(fmt) \
|
118
|
+
do { \
|
119
|
+
i = date_strftime_with_tmx(s, endp - s, (fmt), tmx); \
|
120
|
+
if (!i) return 0; \
|
121
|
+
if (flags & BIT_OF(UPPER)) \
|
122
|
+
upcase(s, i); \
|
123
|
+
if (!(flags & BIT_OF(LEFT)) && precision > i) { \
|
124
|
+
if (start + maxsize < s + precision) { \
|
125
|
+
errno = ERANGE; \
|
126
|
+
return 0; \
|
127
|
+
} \
|
128
|
+
memmove(s + precision - i, s, i); \
|
129
|
+
memset(s, padding ? padding : ' ', precision - i); \
|
130
|
+
s += precision; \
|
131
|
+
} \
|
132
|
+
else s += i; \
|
133
|
+
} while (0)
|
134
|
+
#define FMTV(def_pad, def_prec, fmt, val) \
|
135
|
+
do { \
|
136
|
+
VALUE tmp = (val); \
|
137
|
+
if (FIXNUM_P(tmp)) { \
|
138
|
+
FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \
|
139
|
+
} \
|
140
|
+
else { \
|
141
|
+
VALUE args[2], result; \
|
142
|
+
size_t l; \
|
143
|
+
if (precision <= 0) precision = (def_prec); \
|
144
|
+
if (flags & BIT_OF(LEFT)) precision = 1; \
|
145
|
+
args[0] = INT2FIX(precision); \
|
146
|
+
args[1] = (val); \
|
147
|
+
if (padding == '0' || (!padding && (def_pad) == '0')) \
|
148
|
+
result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \
|
149
|
+
else \
|
150
|
+
result = rb_str_format(2, args, rb_str_new2("%*"fmt)); \
|
151
|
+
l = strlcpy(s, StringValueCStr(result), endp - s); \
|
152
|
+
if ((size_t)(endp - s) <= l) \
|
153
|
+
goto err; \
|
154
|
+
s += l; \
|
155
|
+
} \
|
156
|
+
} while (0)
|
157
|
+
|
158
|
+
if (*format != '%') {
|
159
|
+
*s++ = *format;
|
160
|
+
continue;
|
161
|
+
}
|
162
|
+
tp = tbuf;
|
163
|
+
sp = format;
|
164
|
+
precision = -1;
|
165
|
+
flags = 0;
|
166
|
+
padding = 0;
|
167
|
+
colons = 0;
|
168
|
+
again:
|
169
|
+
switch (*++format) {
|
170
|
+
case '\0':
|
171
|
+
format--;
|
172
|
+
goto unknown;
|
173
|
+
|
174
|
+
case 'A': /* full weekday name */
|
175
|
+
case 'a': /* abbreviated weekday name */
|
176
|
+
if (flags & BIT_OF(CHCASE)) {
|
177
|
+
flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
|
178
|
+
flags |= BIT_OF(UPPER);
|
179
|
+
}
|
180
|
+
{
|
181
|
+
int wday = tmx_wday;
|
182
|
+
if (wday < 0 || wday > 6)
|
183
|
+
i = 1, tp = "?";
|
184
|
+
else {
|
185
|
+
if (*format == 'A')
|
186
|
+
i = strlen(tp = days_l[wday]);
|
187
|
+
else
|
188
|
+
i = 3, tp = days_l[wday];
|
189
|
+
}
|
190
|
+
}
|
191
|
+
break;
|
192
|
+
|
193
|
+
case 'B': /* full month name */
|
194
|
+
case 'b': /* abbreviated month name */
|
195
|
+
case 'h': /* same as %b */
|
196
|
+
if (flags & BIT_OF(CHCASE)) {
|
197
|
+
flags &= ~(BIT_OF(LOWER) | BIT_OF(CHCASE));
|
198
|
+
flags |= BIT_OF(UPPER);
|
199
|
+
}
|
200
|
+
{
|
201
|
+
int mon = tmx_mon;
|
202
|
+
if (mon < 1 || mon > 12)
|
203
|
+
i = 1, tp = "?";
|
204
|
+
else {
|
205
|
+
if (*format == 'B')
|
206
|
+
i = strlen(tp = months_l[mon - 1]);
|
207
|
+
else
|
208
|
+
i = 3, tp = months_l[mon - 1];
|
209
|
+
}
|
210
|
+
}
|
211
|
+
break;
|
212
|
+
|
213
|
+
case 'C': /* century (year/100) */
|
214
|
+
FMTV('0', 2, "d", div(tmx_year, INT2FIX(100)));
|
215
|
+
continue;
|
216
|
+
|
217
|
+
case 'c': /* appropriate date and time representation */
|
218
|
+
STRFTIME("%a %b %e %H:%M:%S %Y");
|
219
|
+
continue;
|
220
|
+
|
221
|
+
case 'D':
|
222
|
+
STRFTIME("%m/%d/%y");
|
223
|
+
continue;
|
224
|
+
|
225
|
+
case 'd': /* day of the month, 01 - 31 */
|
226
|
+
case 'e': /* day of month, blank padded */
|
227
|
+
v = range(1, tmx_mday, 31);
|
228
|
+
FMT((*format == 'd') ? '0' : ' ', 2, "d", v);
|
229
|
+
continue;
|
230
|
+
|
231
|
+
case 'F':
|
232
|
+
STRFTIME("%Y-%m-%d");
|
233
|
+
continue;
|
234
|
+
|
235
|
+
case 'G': /* year of ISO week with century */
|
236
|
+
case 'Y': /* year with century */
|
237
|
+
{
|
238
|
+
VALUE year = (*format == 'G') ? tmx_cwyear : tmx_year;
|
239
|
+
if (FIXNUM_P(year)) {
|
240
|
+
long y = FIX2LONG(year);
|
241
|
+
FMT('0', 0 <= y ? 4 : 5, "ld", y);
|
242
|
+
}
|
243
|
+
else {
|
244
|
+
FMTV('0', 4, "d", year);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
continue;
|
248
|
+
|
249
|
+
case 'g': /* year of ISO week without a century */
|
250
|
+
case 'y': /* year without a century */
|
251
|
+
v = NUM2INT(mod((*format == 'g') ? tmx_cwyear : tmx_year, INT2FIX(100)));
|
252
|
+
FMT('0', 2, "d", v);
|
253
|
+
continue;
|
254
|
+
|
255
|
+
case 'H': /* hour, 24-hour clock, 00 - 23 */
|
256
|
+
case 'k': /* hour, 24-hour clock, blank pad */
|
257
|
+
v = range(0, tmx_hour, 23);
|
258
|
+
FMT((*format == 'H') ? '0' : ' ', 2, "d", v);
|
259
|
+
continue;
|
260
|
+
|
261
|
+
case 'I': /* hour, 12-hour clock, 01 - 12 */
|
262
|
+
case 'l': /* hour, 12-hour clock, 1 - 12, blank pad */
|
263
|
+
v = range(0, tmx_hour, 23);
|
264
|
+
if (v == 0)
|
265
|
+
v = 12;
|
266
|
+
else if (v > 12)
|
267
|
+
v -= 12;
|
268
|
+
FMT((*format == 'I') ? '0' : ' ', 2, "d", v);
|
269
|
+
continue;
|
270
|
+
|
271
|
+
case 'j': /* day of the year, 001 - 366 */
|
272
|
+
v = range(1, tmx_yday, 366);
|
273
|
+
FMT('0', 3, "d", v);
|
274
|
+
continue;
|
275
|
+
|
276
|
+
case 'L': /* millisecond */
|
277
|
+
case 'N': /* nanosecond */
|
278
|
+
if (*format == 'L')
|
279
|
+
w = 3;
|
280
|
+
else
|
281
|
+
w = 9;
|
282
|
+
if (precision <= 0)
|
283
|
+
precision = w;
|
284
|
+
NEEDS(precision);
|
285
|
+
|
286
|
+
{
|
287
|
+
VALUE subsec = tmx_sec_fraction;
|
288
|
+
int ww;
|
289
|
+
long n;
|
290
|
+
|
291
|
+
ww = precision;
|
292
|
+
while (9 <= ww) {
|
293
|
+
subsec = mul(subsec, INT2FIX(1000000000));
|
294
|
+
ww -= 9;
|
295
|
+
}
|
296
|
+
n = 1;
|
297
|
+
for (; 0 < ww; ww--)
|
298
|
+
n *= 10;
|
299
|
+
if (n != 1)
|
300
|
+
subsec = mul(subsec, INT2FIX(n));
|
301
|
+
subsec = div(subsec, INT2FIX(1));
|
302
|
+
|
303
|
+
if (FIXNUM_P(subsec)) {
|
304
|
+
(void)snprintf(s, endp - s, "%0*ld",
|
305
|
+
precision, FIX2LONG(subsec));
|
306
|
+
s += precision;
|
307
|
+
}
|
308
|
+
else {
|
309
|
+
VALUE args[2], result;
|
310
|
+
args[0] = INT2FIX(precision);
|
311
|
+
args[1] = subsec;
|
312
|
+
result = rb_str_format(2, args, rb_str_new2("%0*d"));
|
313
|
+
(void)strlcpy(s, StringValueCStr(result), endp - s);
|
314
|
+
s += precision;
|
315
|
+
}
|
316
|
+
}
|
317
|
+
continue;
|
318
|
+
|
319
|
+
case 'M': /* minute, 00 - 59 */
|
320
|
+
v = range(0, tmx_min, 59);
|
321
|
+
FMT('0', 2, "d", v);
|
322
|
+
continue;
|
323
|
+
|
324
|
+
case 'm': /* month, 01 - 12 */
|
325
|
+
v = range(1, tmx_mon, 12);
|
326
|
+
FMT('0', 2, "d", v);
|
327
|
+
continue;
|
328
|
+
|
329
|
+
case 'n': /* same as \n */
|
330
|
+
FILL_PADDING(1);
|
331
|
+
*s++ = '\n';
|
332
|
+
continue;
|
333
|
+
|
334
|
+
case 't': /* same as \t */
|
335
|
+
FILL_PADDING(1);
|
336
|
+
*s++ = '\t';
|
337
|
+
continue;
|
338
|
+
|
339
|
+
case 'P': /* am or pm based on 12-hour clock */
|
340
|
+
case 'p': /* AM or PM based on 12-hour clock */
|
341
|
+
if ((*format == 'p' && (flags & BIT_OF(CHCASE))) ||
|
342
|
+
(*format == 'P' && !(flags & (BIT_OF(CHCASE) | BIT_OF(UPPER))))) {
|
343
|
+
flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
|
344
|
+
flags |= BIT_OF(LOWER);
|
345
|
+
}
|
346
|
+
v = range(0, tmx_hour, 23);
|
347
|
+
if (v < 12)
|
348
|
+
tp = ampm[0];
|
349
|
+
else
|
350
|
+
tp = ampm[1];
|
351
|
+
i = 2;
|
352
|
+
break;
|
353
|
+
|
354
|
+
case 'Q': /* milliseconds since Unix epoch */
|
355
|
+
FMTV('0', 1, "d", tmx_msecs);
|
356
|
+
continue;
|
357
|
+
|
358
|
+
case 'R':
|
359
|
+
STRFTIME("%H:%M");
|
360
|
+
continue;
|
361
|
+
|
362
|
+
case 'r':
|
363
|
+
STRFTIME("%I:%M:%S %p");
|
364
|
+
continue;
|
365
|
+
|
366
|
+
case 'S': /* second, 00 - 59 */
|
367
|
+
v = range(0, tmx_sec, 59);
|
368
|
+
FMT('0', 2, "d", v);
|
369
|
+
continue;
|
370
|
+
|
371
|
+
case 's': /* seconds since Unix epoch */
|
372
|
+
FMTV('0', 1, "d", tmx_secs);
|
373
|
+
continue;
|
374
|
+
|
375
|
+
case 'T':
|
376
|
+
STRFTIME("%H:%M:%S");
|
377
|
+
continue;
|
378
|
+
|
379
|
+
case 'U': /* week of year, Sunday is first day of week */
|
380
|
+
case 'W': /* week of year, Monday is first day of week */
|
381
|
+
v = range(0, (*format == 'U') ? tmx_wnum0 : tmx_wnum1, 53);
|
382
|
+
FMT('0', 2, "d", v);
|
383
|
+
continue;
|
384
|
+
|
385
|
+
case 'u': /* weekday, Monday == 1, 1 - 7 */
|
386
|
+
v = range(1, tmx_cwday, 7);
|
387
|
+
FMT('0', 1, "d", v);
|
388
|
+
continue;
|
389
|
+
|
390
|
+
case 'V': /* week of year according ISO 8601 */
|
391
|
+
v = range(1, tmx_cweek, 53);
|
392
|
+
FMT('0', 2, "d", v);
|
393
|
+
continue;
|
394
|
+
|
395
|
+
case 'v':
|
396
|
+
STRFTIME("%e-%b-%Y");
|
397
|
+
continue;
|
398
|
+
|
399
|
+
case 'w': /* weekday, Sunday == 0, 0 - 6 */
|
400
|
+
v = range(0, tmx_wday, 6);
|
401
|
+
FMT('0', 1, "d", v);
|
402
|
+
continue;
|
403
|
+
|
404
|
+
case 'X': /* appropriate time representation */
|
405
|
+
STRFTIME("%H:%M:%S");
|
406
|
+
continue;
|
407
|
+
|
408
|
+
case 'x': /* appropriate date representation */
|
409
|
+
STRFTIME("%m/%d/%y");
|
410
|
+
continue;
|
411
|
+
|
412
|
+
case 'Z': /* time zone name or abbreviation */
|
413
|
+
if (flags & BIT_OF(CHCASE)) {
|
414
|
+
flags &= ~(BIT_OF(UPPER) | BIT_OF(CHCASE));
|
415
|
+
flags |= BIT_OF(LOWER);
|
416
|
+
}
|
417
|
+
{
|
418
|
+
char *zone = tmx_zone;
|
419
|
+
if (zone == NULL)
|
420
|
+
tp = "";
|
421
|
+
else
|
422
|
+
tp = zone;
|
423
|
+
i = strlen(tp);
|
424
|
+
}
|
425
|
+
break;
|
426
|
+
|
427
|
+
case 'z': /* offset from UTC */
|
428
|
+
{
|
429
|
+
long off, aoff;
|
430
|
+
int hl, hw;
|
431
|
+
|
432
|
+
off = tmx_offset;
|
433
|
+
aoff = off;
|
434
|
+
if (aoff < 0)
|
435
|
+
aoff = -off;
|
436
|
+
|
437
|
+
if ((aoff / 3600) < 10)
|
438
|
+
hl = 1;
|
439
|
+
else
|
440
|
+
hl = 2;
|
441
|
+
hw = 2;
|
442
|
+
if (flags & BIT_OF(LEFT) && hl == 1)
|
443
|
+
hw = 1;
|
444
|
+
|
445
|
+
switch (colons) {
|
446
|
+
case 0: /* %z -> +hhmm */
|
447
|
+
precision = precision <= (3 + hw) ? hw : precision - 3;
|
448
|
+
NEEDS(precision + 3);
|
449
|
+
break;
|
450
|
+
|
451
|
+
case 1: /* %:z -> +hh:mm */
|
452
|
+
precision = precision <= (4 + hw) ? hw : precision - 4;
|
453
|
+
NEEDS(precision + 4);
|
454
|
+
break;
|
455
|
+
|
456
|
+
case 2: /* %::z -> +hh:mm:ss */
|
457
|
+
precision = precision <= (7 + hw) ? hw : precision - 7;
|
458
|
+
NEEDS(precision + 7);
|
459
|
+
break;
|
460
|
+
|
461
|
+
case 3: /* %:::z -> +hh[:mm[:ss]] */
|
462
|
+
{
|
463
|
+
if (aoff % 3600 == 0) {
|
464
|
+
precision = precision <= (1 + hw) ?
|
465
|
+
hw : precision - 1;
|
466
|
+
NEEDS(precision + 3);
|
467
|
+
}
|
468
|
+
else if (aoff % 60 == 0) {
|
469
|
+
precision = precision <= (4 + hw) ?
|
470
|
+
hw : precision - 4;
|
471
|
+
NEEDS(precision + 4);
|
472
|
+
}
|
473
|
+
else {
|
474
|
+
precision = precision <= (7 + hw) ?
|
475
|
+
hw : precision - 7;
|
476
|
+
NEEDS(precision + 7);
|
477
|
+
}
|
478
|
+
}
|
479
|
+
break;
|
480
|
+
|
481
|
+
default:
|
482
|
+
format--;
|
483
|
+
goto unknown;
|
484
|
+
}
|
485
|
+
if (padding == ' ' && precision > hl) {
|
486
|
+
i = snprintf(s, endp - s, "%*s", precision - hl, "");
|
487
|
+
precision = hl;
|
488
|
+
if (i < 0) goto err;
|
489
|
+
s += i;
|
490
|
+
}
|
491
|
+
if (off < 0) {
|
492
|
+
off = -off;
|
493
|
+
*s++ = '-';
|
494
|
+
} else {
|
495
|
+
*s++ = '+';
|
496
|
+
}
|
497
|
+
i = snprintf(s, endp - s, "%.*ld", precision, off / 3600);
|
498
|
+
if (i < 0) goto err;
|
499
|
+
s += i;
|
500
|
+
off = off % 3600;
|
501
|
+
if (colons == 3 && off == 0)
|
502
|
+
continue;
|
503
|
+
if (1 <= colons)
|
504
|
+
*s++ = ':';
|
505
|
+
i = snprintf(s, endp - s, "%02d", (int)(off / 60));
|
506
|
+
if (i < 0) goto err;
|
507
|
+
s += i;
|
508
|
+
off = off % 60;
|
509
|
+
if (colons == 3 && off == 0)
|
510
|
+
continue;
|
511
|
+
if (2 <= colons) {
|
512
|
+
*s++ = ':';
|
513
|
+
i = snprintf(s, endp - s, "%02d", (int)off);
|
514
|
+
if (i < 0) goto err;
|
515
|
+
s += i;
|
516
|
+
}
|
517
|
+
}
|
518
|
+
continue;
|
519
|
+
|
520
|
+
case '+':
|
521
|
+
STRFTIME("%a %b %e %H:%M:%S %Z %Y");
|
522
|
+
continue;
|
523
|
+
|
524
|
+
case 'E':
|
525
|
+
/* POSIX locale extensions, ignored for now */
|
526
|
+
flags |= BIT_OF(LOCALE_E);
|
527
|
+
if (*(format + 1) && strchr("cCxXyY", *(format + 1)))
|
528
|
+
goto again;
|
529
|
+
goto unknown;
|
530
|
+
case 'O':
|
531
|
+
/* POSIX locale extensions, ignored for now */
|
532
|
+
flags |= BIT_OF(LOCALE_O);
|
533
|
+
if (*(format + 1) && strchr("deHkIlmMSuUVwWy", *(format + 1)))
|
534
|
+
goto again;
|
535
|
+
goto unknown;
|
536
|
+
|
537
|
+
case ':':
|
538
|
+
flags |= BIT_OF(COLONS);
|
539
|
+
{
|
540
|
+
size_t l = strspn(format, ":");
|
541
|
+
format += l;
|
542
|
+
if (*format == 'z') {
|
543
|
+
colons = l;
|
544
|
+
format--;
|
545
|
+
goto again;
|
546
|
+
}
|
547
|
+
format -= l;
|
548
|
+
}
|
549
|
+
goto unknown;
|
550
|
+
|
551
|
+
case '_':
|
552
|
+
FLAG_FOUND();
|
553
|
+
padding = ' ';
|
554
|
+
goto again;
|
555
|
+
|
556
|
+
case '-':
|
557
|
+
FLAG_FOUND();
|
558
|
+
flags |= BIT_OF(LEFT);
|
559
|
+
goto again;
|
560
|
+
|
561
|
+
case '^':
|
562
|
+
FLAG_FOUND();
|
563
|
+
flags |= BIT_OF(UPPER);
|
564
|
+
goto again;
|
565
|
+
|
566
|
+
case '#':
|
567
|
+
FLAG_FOUND();
|
568
|
+
flags |= BIT_OF(CHCASE);
|
569
|
+
goto again;
|
570
|
+
|
571
|
+
case '0':
|
572
|
+
FLAG_FOUND();
|
573
|
+
padding = '0';
|
574
|
+
case '1': case '2': case '3': case '4':
|
575
|
+
case '5': case '6': case '7': case '8': case '9':
|
576
|
+
{
|
577
|
+
char *e;
|
578
|
+
unsigned long prec = strtoul(format, &e, 10);
|
579
|
+
if (prec > INT_MAX || prec > maxsize) {
|
580
|
+
errno = ERANGE;
|
581
|
+
return 0;
|
582
|
+
}
|
583
|
+
precision = (int)prec;
|
584
|
+
format = e - 1;
|
585
|
+
goto again;
|
586
|
+
}
|
587
|
+
|
588
|
+
case '%':
|
589
|
+
FILL_PADDING(1);
|
590
|
+
*s++ = '%';
|
591
|
+
continue;
|
592
|
+
|
593
|
+
default:
|
594
|
+
unknown:
|
595
|
+
i = format - sp + 1;
|
596
|
+
tp = sp;
|
597
|
+
precision = -1;
|
598
|
+
flags = 0;
|
599
|
+
padding = 0;
|
600
|
+
colons = 0;
|
601
|
+
break;
|
602
|
+
}
|
603
|
+
if (i) {
|
604
|
+
FILL_PADDING(i);
|
605
|
+
memcpy(s, tp, i);
|
606
|
+
switch (flags & (BIT_OF(UPPER) | BIT_OF(LOWER))) {
|
607
|
+
case BIT_OF(UPPER):
|
608
|
+
upcase(s, i);
|
609
|
+
break;
|
610
|
+
case BIT_OF(LOWER):
|
611
|
+
downcase(s, i);
|
612
|
+
break;
|
613
|
+
}
|
614
|
+
s += i;
|
615
|
+
}
|
616
|
+
}
|
617
|
+
if (s >= endp) {
|
618
|
+
goto err;
|
619
|
+
}
|
620
|
+
if (*format == '\0') {
|
621
|
+
*s = '\0';
|
622
|
+
return (s - start);
|
623
|
+
}
|
624
|
+
return 0;
|
625
|
+
}
|
626
|
+
|
627
|
+
size_t
|
628
|
+
date_strftime(char *s, size_t maxsize, const char *format,
|
629
|
+
const struct tmx *tmx)
|
630
|
+
{
|
631
|
+
return date_strftime_with_tmx(s, maxsize, format, tmx);
|
632
|
+
}
|
633
|
+
|
634
|
+
/*
|
635
|
+
Local variables:
|
636
|
+
c-file-style: "ruby"
|
637
|
+
End:
|
638
|
+
*/
|