diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | strftime.c | 49 | ||||
-rw-r--r-- | test/ruby/test_time_tz.rb | 21 | ||||
-rw-r--r-- | time.c | 4 |
4 files changed, 69 insertions, 10 deletions
@@ -1,3 +1,8 @@ +Thu Jul 8 06:05:58 2010 Tanaka Akira <akr@fsij.org> + + * strftime.c (rb_strftime_with_timespec): support %:z and %::z. + [ruby-dev:41841] + Thu Jul 8 00:15:50 2010 Yusuke Endoh <mame@tsg.ne.jp> * gem_prelude.rb: provide workaround for gem activation. Currently, diff --git a/strftime.c b/strftime.c index 2b98e29148..ac83f5d0e2 100644 --- a/strftime.c +++ b/strftime.c @@ -215,7 +215,7 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str #endif #endif /* HAVE_TM_NAME */ #endif /* HAVE_TM_ZONE */ - int precision, flags; + int precision, flags, colons; char padding; enum {LEFT, CHCASE, LOWER, UPPER, LOCALE_O, LOCALE_E}; #define BIT_OF(n) (1U<<(n)) @@ -348,6 +348,7 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str precision = -1; flags = 0; padding = 0; + colons = 0; again: switch (*++format) { case '\0': @@ -530,13 +531,31 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str * us that muck around with various message processors. */ case 'z': /* time zone offset east of GMT e.g. -0600 */ - if (precision < 4) precision = 4; - NEEDS(precision + 1); + switch (colons) { + case 0: /* %z -> +hhmm */ + precision = precision <= 5 ? 2 : precision-3; + NEEDS(precision + 3); + break; + + case 1: /* %:z -> +hh:mm */ + precision = precision <= 5 ? 2 : precision-3; + NEEDS(precision + 4); + break; + + case 2: /* %::z -> +hh:mm:ss */ + precision = precision <= 5 ? 2 : precision-3; + NEEDS(precision + 7); + break; + + default: + format--; + goto unknown; + } if (gmt) { off = 0; } else { - off = NUM2LONG(rb_funcall(quo(vtm->utc_offset, INT2FIX(60)), rb_intern("round"), 0)); + off = NUM2LONG(rb_funcall(vtm->utc_offset, rb_intern("round"), 0)); #if 0 #ifdef HAVE_TM_NAME /* @@ -583,11 +602,22 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str } else { *s++ = '+'; } - off = off/60*100 + off%60; - i = snprintf(s, endp - s, (padding == ' ' ? "%*ld" : "%.*ld"), - precision - (precision > 4), off); + i = snprintf(s, endp - s, (padding == ' ' ? "%*ld" : "%.*ld"), precision, off / 3600); + if (i < 0) goto err; + s += i; + off = off % 3600; + if (1 <= colons) + *s++ = ':'; + i = snprintf(s, endp - s, "%02d", off / 60); if (i < 0) goto err; s += i; + off = off % 60; + if (2 <= colons) { + *s++ = ':'; + i = snprintf(s, endp - s, "%02d", off); + if (i < 0) goto err; + s += i; + } continue; #endif /* MAILHEADER_EXT */ @@ -839,6 +869,11 @@ rb_strftime_with_timespec(char *s, size_t maxsize, const char *format, const str padding = ' '; goto again; + case ':': + FLAG_FOUND(); + colons++; + goto again; + case '0': padding = '0'; case '1': case '2': case '3': case '4': diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb index 1041e31d2b..4942d32028 100644 --- a/test/ruby/test_time_tz.rb +++ b/test/ruby/test_time_tz.rb @@ -18,7 +18,7 @@ class TestTimeTZ < Test::Unit::TestCase end module Util - def format_gmtoff(gmtoff) + def format_gmtoff(gmtoff, colon=false) if gmtoff < 0 expected = "-" gmtoff = -gmtoff @@ -26,7 +26,20 @@ class TestTimeTZ < Test::Unit::TestCase expected = "+" end gmtoff /= 60 - expected << "%02d%02d" % [gmtoff / 60, gmtoff % 60] + expected << "%02d" % [gmtoff / 60] + expected << ":" if colon + expected << "%02d" % [gmtoff % 60] + expected + end + + def format_gmtoff2(gmtoff) + if gmtoff < 0 + expected = "-" + gmtoff = -gmtoff + else + expected = "+" + end + expected << "%02d:%02d:%02d" % [gmtoff / 3600, gmtoff % 3600 / 60, gmtoff % 60] expected end @@ -189,6 +202,9 @@ class TestTimeTZ < Test::Unit::TestCase assert_nothing_raised(mesg) { t.localtime } assert_equal(expected, time_to_s(t), mesg) assert_equal(gmtoff, t.gmtoff) + assert_equal(format_gmtoff(gmtoff), t.strftime("%z")) + assert_equal(format_gmtoff(gmtoff, true), t.strftime("%:z")) + assert_equal(format_gmtoff2(gmtoff), t.strftime("%::z")) } } } @@ -289,6 +305,7 @@ right/America/Los_Angeles Wed Dec 31 23:59:60 2008 UTC = Wed Dec 31 15:59:60 20 #right/Asia/Tokyo Sat Dec 31 23:59:60 2005 UTC = Sun Jan 1 08:59:60 2006 JST isdst=0 gmtoff=32400 right/Europe/Paris Fri Jun 30 23:59:60 1972 UTC = Sat Jul 1 00:59:60 1972 CET isdst=0 gmtoff=3600 right/Europe/Paris Wed Dec 31 23:59:60 2008 UTC = Thu Jan 1 00:59:60 2009 CET isdst=0 gmtoff=3600 +Europe/Lisbon Mon Jan 1 00:36:31 1912 UTC = Sun Dec 31 23:59:59 1911 LMT isdst=0 gmtoff=-2192 End gen_zdump_test end @@ -4346,7 +4346,9 @@ strftimev(const char *fmt, VALUE time) * %X - Preferred representation for the time alone, no date * %y - Year without a century (00..99) * %Y - Year with century - * %z - Time zone as hour offset from UTC (e.g. +0900) + * %z - Time zone as hour and minute offset from UTC (e.g. +0900) + * %:z - hour and minute offset from UTC with a colon (e.g. +09:00) + * %::z - hour, minute and second offset from UTC (e.g. +09:00:00) * %Z - Time zone name * %% - Literal ``%'' character * |