From 214668fccbca2db14ce57797017b34acd86d4690 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 6 Sep 2024 15:53:46 +0900 Subject: [PATCH] [Feature #20707] Fix negative UTC offset conversion In short, get rid of division and modulo of negative integers. --- test/ruby/test_time.rb | 3 +++ time.c | 10 ++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/test/ruby/test_time.rb b/test/ruby/test_time.rb index cab14eb694..99ee84f247 100644 --- a/test/ruby/test_time.rb +++ b/test/ruby/test_time.rb @@ -1490,6 +1490,9 @@ class TestTime < Test::Unit::TestCase assert_equal("1960-12-31T23:00:00.123456Z", t.__send__(method, 6)) end + t = get_t2000.getlocal("-09:30") # Pacific/Marquesas + assert_equal("1999-12-31T14:30:00-09:30", t.__send__(method)) + assert_equal("10000-01-01T00:00:00Z", Time.utc(10000).__send__(method)) assert_equal("9999-01-01T00:00:00Z", Time.utc(9999).__send__(method)) assert_equal("0001-01-01T00:00:00Z", Time.utc(1).__send__(method)) # 1 AD diff --git a/time.c b/time.c index 801df3658e..51d39ff293 100644 --- a/time.c +++ b/time.c @@ -5285,13 +5285,15 @@ time_xmlschema(int argc, VALUE *argv, VALUE time) } else { long offset = NUM2LONG(rb_time_utc_offset(time)); + *ptr++ = offset < 0 ? '-' : '+'; + if (offset < 0) offset = -offset; int offset_hours = (int)(offset / 3600); - int offset_minutes = (int)((offset % 3600 / 60)); - written = snprintf(ptr, sizeof("+ZH:ZM"), "%+03d:%02d", offset_hours, offset_minutes); - RUBY_ASSERT(written == sizeof("+ZH:ZM") - 1); + int offset_minutes = (int)(offset % 3600 / 60); + written = snprintf(ptr, sizeof("ZH:ZM"), "%02d:%02d", offset_hours, offset_minutes); + RUBY_ASSERT(written == sizeof("ZH:ZM") - 1, "%d[%.*s]", written, written, ptr); ptr += written; } - rb_str_set_len(str, ptr -start); // We could skip coderange scanning as we know it's full ASCII. + rb_str_set_len(str, ptr - start); // We could skip coderange scanning as we know it's full ASCII. return str; }