15 #if defined(HAVE_SYS_TIME_H) 21 #define range(low, item, hi) (item) 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))) 31 upcase(
char *s,
size_t i)
40 downcase(
char *s,
size_t i)
51 date_strftime_with_tmx(
char *s,
const size_t maxsize,
const char *format,
54 char *endp = s + maxsize;
65 #define BIT_OF(n) (1U<<(n)) 68 static const char days_l[][10] = {
69 "Sunday",
"Monday",
"Tuesday",
"Wednesday",
70 "Thursday",
"Friday",
"Saturday",
72 static const char months_l[][10] = {
73 "January",
"February",
"March",
"April",
74 "May",
"June",
"July",
"August",
"September",
75 "October",
"November",
"December",
77 static const char ampm[][3] = {
"AM",
"PM", };
79 if (s ==
NULL || format ==
NULL || tmx ==
NULL || maxsize == 0)
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))) \ 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)) { \ 98 memset(s, padding ? padding : ' ', precision - (i)); \ 99 s += precision - (i); \ 105 #define FMT(def_pad, def_prec, fmt, val) \ 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), \ 114 if (l < 0) goto err; \ 117 #define STRFTIME(fmt) \ 119 i = date_strftime_with_tmx(s, endp - s, (fmt), tmx); \ 121 if (flags & BIT_OF(UPPER)) \ 123 if (!(flags & BIT_OF(LEFT)) && precision > i) { \ 124 if (start + maxsize < s + precision) { \ 128 memmove(s + precision - i, s, i); \ 129 memset(s, padding ? padding : ' ', precision - i); \ 134 #define FMTV(def_pad, def_prec, fmt, val) \ 137 if (FIXNUM_P(tmp)) { \ 138 FMT((def_pad), (def_prec), "l"fmt, FIX2LONG(tmp)); \ 141 VALUE args[2], result; \ 143 if (precision <= 0) precision = (def_prec); \ 144 if (flags & BIT_OF(LEFT)) precision = 1; \ 145 args[0] = INT2FIX(precision); \ 147 if (padding == '0' || (!padding && (def_pad) == '0')) \ 148 result = rb_str_format(2, args, rb_str_new2("%0*"fmt)); \ 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) \ 158 if (*format !=
'%') {
182 if (wday < 0 || wday > 6)
186 i =
strlen(tp = days_l[wday]);
188 i = 3, tp = days_l[wday];
202 if (mon < 1 || mon > 12)
206 i =
strlen(tp = months_l[mon - 1]);
208 i = 3, tp = months_l[mon - 1];
228 FMT((*format ==
'd') ?
'0' :
' ', 2,
"d", v);
241 FMT(
'0', 0 <= y ? 4 : 5,
"ld", y);
244 FMTV(
'0', 4,
"d", year);
258 FMT((*format ==
'H') ?
'0' :
' ', 2,
"d", v);
268 FMT((*format ==
'I') ?
'0' :
' ', 2,
"d", v);
304 (void)
snprintf(s, endp - s,
"%0*ld",
309 VALUE args[2], result;
437 if ((aoff / 3600) < 10)
447 precision = precision <= (3 + hw) ? hw : precision - 3;
448 NEEDS(precision + 3);
452 precision = precision <= (4 + hw) ? hw : precision - 4;
453 NEEDS(precision + 4);
457 precision = precision <= (7 + hw) ? hw : precision - 7;
458 NEEDS(precision + 7);
463 if (aoff % 3600 == 0) {
464 precision = precision <= (1 + hw) ?
466 NEEDS(precision + 3);
468 else if (aoff % 60 == 0) {
469 precision = precision <= (4 + hw) ?
471 NEEDS(precision + 4);
474 precision = precision <= (7 + hw) ?
476 NEEDS(precision + 7);
485 if (padding ==
' ' && precision > hl) {
486 i =
snprintf(s, endp - s,
"%*s", precision - hl,
"");
497 i =
snprintf(s, endp - s,
"%.*ld", precision, off / 3600);
501 if (colons == 3 && off == 0)
505 i =
snprintf(s, endp - s,
"%02d", (
int)(off / 60));
509 if (colons == 3 && off == 0)
513 i =
snprintf(s, endp - s,
"%02d", (
int)off);
521 STRFTIME(
"%a %b %e %H:%M:%S %Z %Y");
526 flags |=
BIT_OF(LOCALE_E);
527 if (*(format + 1) &&
strchr(
"cCxXyY", *(format + 1)))
532 flags |=
BIT_OF(LOCALE_O);
533 if (*(format + 1) &&
strchr(
"deHkIlmMSuUVwWy", *(format + 1)))
540 size_t l = strspn(format,
":");
542 if (*format ==
'z') {
574 case '1':
case '2':
case '3':
case '4':
575 case '5':
case '6':
case '7':
case '8':
case '9':
578 unsigned long prec = strtoul(format, &e, 10);
579 if (prec > INT_MAX || prec > maxsize) {
583 precision = (int)prec;
620 if (*format ==
'\0') {
629 const struct tmx *tmx)
631 return date_strftime_with_tmx(s, maxsize, format, tmx);
size_t strlen(const char *)
#define FMT(def_pad, def_prec, fmt, val)
size_t date_strftime(char *s, size_t maxsize, const char *format, const struct tmx *tmx)
#define range(low, item, hi)
VALUE rb_str_format(int, const VALUE *, VALUE)
#define FMTV(def_pad, def_prec, fmt, val)
char * strchr(char *, char)
RUBY_EXTERN size_t strlcpy(char *, const char *, size_t)
#define StringValueCStr(v)