diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | strftime.c | 43 | ||||
-rw-r--r-- | test/ruby/test_time.rb | 7 |
3 files changed, 38 insertions, 17 deletions
@@ -1,3 +1,8 @@ +Thu Mar 24 14:20:21 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * strftime.c (STRFTIME): deal with case conversion flags for + recursive formats. + Thu Mar 24 12:43:26 2016 Nobuyoshi Nakada <nobu@ruby-lang.org> * ext/date/date_core.c (dt_lite_iso8601): strftimev() always diff --git a/strftime.c b/strftime.c index f532bb0ac6..6502ec6f8f 100644 --- a/strftime.c +++ b/strftime.c @@ -157,6 +157,9 @@ max(int a, int b) /* strftime --- produce formatted time */ +enum {LEFT, CHCASE, LOWER, UPPER}; +#define BIT_OF(n) (1U<<(n)) + static char * resize_buffer(VALUE ftime, char *s, const char **start, const char **endp, ptrdiff_t n) @@ -171,6 +174,27 @@ resize_buffer(VALUE ftime, char *s, const char **start, const char **endp, return s += len; } +static char * +case_conv(char *s, ptrdiff_t i, int flags) +{ + switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) { + case BIT_OF(UPPER): + do { + if (ISLOWER(*s)) *s = TOUPPER(*s); + } while (s++, --i); + break; + case BIT_OF(LOWER): + do { + if (ISUPPER(*s)) *s = TOLOWER(*s); + } while (s++, --i); + break; + default: + s += i; + break; + } + return s; +} + /* * enc is the encoding of the format. It is used as the encoding of resulted * string, but the name of the month and weekday are always US-ASCII. So it @@ -195,8 +219,6 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, long y; int precision, flags, colons; char padding; - enum {LEFT, CHCASE, LOWER, UPPER}; -#define BIT_OF(n) (1U<<(n)) #ifdef MAILHEADER_EXT int sign; #endif @@ -269,6 +291,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, i = RSTRING_LEN(ftime) - len; \ endp = (start = s) + rb_str_capacity(ftime); \ s += len; \ + if (i > 0) case_conv(s, i, flags); \ if (precision > i) {\ NEEDS(precision); \ memmove(s + precision - i, s, i);\ @@ -834,21 +857,7 @@ rb_strftime_with_timespec(VALUE ftime, const char *format, size_t format_len, if (i) { FILL_PADDING(i); memcpy(s, tp, i); - switch (flags & (BIT_OF(UPPER)|BIT_OF(LOWER))) { - case BIT_OF(UPPER): - do { - if (ISLOWER(*s)) *s = TOUPPER(*s); - } while (s++, --i); - break; - case BIT_OF(LOWER): - do { - if (ISUPPER(*s)) *s = TOLOWER(*s); - } while (s++, --i); - break; - default: - s += i; - break; - } + s = case_conv(s, i, flags); } } if (format != format_end) { diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index 3e7d9613ed..24545b216c 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -730,6 +730,13 @@ class TestTime < Test::Unit::TestCase assert_equal(" 2", t.strftime("%l")) assert_equal("02", t.strftime("%0l")) assert_equal(" 2", t.strftime("%_l")) + assert_equal("MON", t.strftime("%^a")) + assert_equal("OCT", t.strftime("%^b")) + + t = get_t2000 + assert_equal("UTC", t.strftime("%^Z")) + assert_equal("utc", t.strftime("%#Z")) + assert_equal("SAT JAN 1 00:00:00 2000", t.strftime("%^c")) end def test_strftime_invalid_flags |