ruby-changes:53858
From: nobu <ko1@a...>
Date: Wed, 28 Nov 2018 23:08:46 +0900 (JST)
Subject: [ruby-changes:53858] nobu:r66076 (trunk): Try Time.find_timezone to convert name to timezone
nobu 2018-11-28 23:08:31 +0900 (Wed, 28 Nov 2018) New Revision: 66076 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=66076 Log: Try Time.find_timezone to convert name to timezone Modified files: trunk/test/ruby/test_time_tz.rb trunk/time.c Index: time.c =================================================================== --- time.c (revision 66075) +++ time.c (revision 66076) @@ -642,6 +642,7 @@ static uint32_t obj2subsecx(VALUE obj, V https://github.com/ruby/ruby/blob/trunk/time.c#L642 static VALUE time_gmtime(VALUE); static VALUE time_localtime(VALUE); static VALUE time_fixoff(VALUE); +static VALUE time_zonelocal(VALUE time, VALUE off); static time_t timegm_noleapsecond(struct tm *tm); static int tmcmp(struct tm *a, struct tm *b); @@ -2040,6 +2041,13 @@ maybe_tzobj_p(VALUE obj) https://github.com/ruby/ruby/blob/trunk/time.c#L2041 return TRUE; } +NORETURN(static void invalid_utc_offset(void)); +static void +invalid_utc_offset(void) +{ + rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected for utc_offset"); +} + static VALUE utc_offset_arg(VALUE arg) { @@ -2049,7 +2057,7 @@ utc_offset_arg(VALUE arg) https://github.com/ruby/ruby/blob/trunk/time.c#L2057 char *s = RSTRING_PTR(tmp); if (!rb_enc_str_asciicompat_p(tmp)) { invalid_utc_offset: - rb_raise(rb_eArgError, "\"+HH:MM\" or \"-HH:MM\" expected for utc_offset"); + return Qnil; } switch (RSTRING_LEN(tmp)) { case 9: @@ -2263,8 +2271,9 @@ time_init_1(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/time.c#L2271 vtm.isdst = 0; else if (maybe_tzobj_p(arg)) zone = arg; - else - vtm.utc_offset = utc_offset_arg(arg); + else if (NIL_P(vtm.utc_offset = utc_offset_arg(arg))) + if (NIL_P(zone = find_timezone(time, arg))) + invalid_utc_offset(); } validate_vtm(&vtm); @@ -2280,8 +2289,9 @@ time_init_1(int argc, VALUE *argv, VALUE https://github.com/ruby/ruby/blob/trunk/time.c#L2289 if (zone_timelocal(zone, time)) { return time; } - else { - vtm.utc_offset = utc_offset_arg(zone); + else if (NIL_P(vtm.utc_offset = utc_offset_arg(zone))) { + if (NIL_P(zone = find_timezone(time, zone)) || !zone_timelocal(zone, time)) + invalid_utc_offset(); } } @@ -2480,11 +2490,18 @@ rb_time_num_new(VALUE timev, VALUE off) https://github.com/ruby/ruby/blob/trunk/time.c#L2490 VALUE time = time_new_timew(rb_cTime, rb_time_magnify(v2w(timev))); if (!NIL_P(off)) { - if (maybe_tzobj_p(off)) { + VALUE zone = off; + + if (maybe_tzobj_p(zone)) { time_gmtime(time); - if (zone_timelocal(off, time)) return time; + if (zone_timelocal(zone, time)) return time; + } + if (NIL_P(off = utc_offset_arg(off))) { + if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); + time_gmtime(time); + if (!zone_timelocal(zone, time)) invalid_utc_offset(); + return time; } - off = utc_offset_arg(off); validate_utc_offset(off); time_set_utc_offset(time, off); return time; @@ -3682,6 +3699,23 @@ time_localtime(VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L3699 return time; } +static VALUE +time_zonelocal(VALUE time, VALUE off) +{ + VALUE zone = off; + if (zone_localtime(zone, time)) return time; + + if (NIL_P(off = utc_offset_arg(off))) { + if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); + if (!zone_localtime(zone, time)) invalid_utc_offset(); + return time; + } + validate_utc_offset(off); + + time_set_utc_offset(time, off); + return time_fixoff(time); +} + /* * call-seq: * time.localtime -> time @@ -3712,13 +3746,7 @@ time_localtime_m(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/time.c#L3746 rb_scan_args(argc, argv, "01", &off); if (!NIL_P(off)) { - if (zone_localtime(off, time)) return time; - - off = utc_offset_arg(off); - validate_utc_offset(off); - - time_set_utc_offset(time, off); - return time_fixoff(time); + return time_zonelocal(time, off); } return time_localtime(time); @@ -3835,12 +3863,18 @@ time_getlocaltime(int argc, VALUE *argv, https://github.com/ruby/ruby/blob/trunk/time.c#L3863 rb_scan_args(argc, argv, "01", &off); if (!NIL_P(off)) { - if (maybe_tzobj_p(off)) { + VALUE zone = off; + if (maybe_tzobj_p(zone)) { VALUE t = time_dup(time); if (zone_localtime(off, t)) return t; } - off = utc_offset_arg(off); + if (NIL_P(off = utc_offset_arg(off))) { + if (NIL_P(zone = find_timezone(time, zone))) invalid_utc_offset(); + time = time_dup(time); + if (!zone_localtime(zone, time)) invalid_utc_offset(); + return time; + } validate_utc_offset(off); time = time_dup(time); @@ -5417,6 +5451,9 @@ rb_time_zone_abbreviation(VALUE zone, VA https://github.com/ruby/ruby/blob/trunk/time.c#L5451 * * At loading marshaled data, a timezone name will be converted to a timezone * object by +find_timezone+ class method, if the method is defined. + * + * Similary, that class method will be called when a timezone argument does + * not have the necessary methods mentioned above. */ void Index: test/ruby/test_time_tz.rb =================================================================== --- test/ruby/test_time_tz.rb (revision 66075) +++ test/ruby/test_time_tz.rb (revision 66076) @@ -503,41 +503,49 @@ End https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L503 def abbr(t) @abbr end + + def ==(other) + @name == other.name and @abbr == other.abbr(0) and @offset == other.offset + end + + def inspect + "#<TZ: #@name #@abbr #@offset>" + end end end module TestTimeTZ::WithTZ - def subtest_new(time_class, tz, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tz) + def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) assert_equal([2018, 9, 1, 12, 0, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) h, m = (-utc_offset / 60).divmod(60) assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i) end - def subtest_getlocal(time_class, tz, tzname, abbr, utc_offset) - t = time_class.utc(2018, 9, 1, 12, 0, 0).getlocal(tz) + def subtest_getlocal(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.utc(2018, 9, 1, 12, 0, 0).getlocal(tzarg) h, m = (utc_offset / 60).divmod(60) assert_equal([2018, 9, 1, 12+h, m, 0, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) assert_equal(time_class.utc(2018, 9, 1, 12, 0, 0), t) end - def subtest_strftime(time_class, tz, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tz) + def subtest_strftime(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) h, m = (utc_offset.abs / 60).divmod(60) h = -h if utc_offset < 0 assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z")) end - def subtest_plus(time_class, tz, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tz) + 4000 + def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) + 4000 assert_equal([2018, 9, 1, 13, 6, 40, tz], [t.year, t.mon, t.mday, t.hour, t.min, t.sec, t.zone]) m, s = (4000-utc_offset).divmod(60) h, m = m.divmod(60) assert_equal(time_class.utc(2018, 9, 1, 12+h, m, s), t) end - def subtest_marshal(time_class, tz, tzname, abbr, utc_offset) - t = time_class.new(2018, 9, 1, 12, 0, 0, tz) + def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset) + t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) t2 = Marshal.load(Marshal.dump(t)) assert_equal(t, t2) assert_equal(t.utc_offset, t2.utc_offset) @@ -561,7 +569,8 @@ module TestTimeTZ::WithTZ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L569 define_method("#{test}@#{tzname}") do tz = make_timezone(tzname, abbr, utc_offset) time_class = self.class::TIME_CLASS - __send__(subtest, time_class, tz, tzname, abbr, utc_offset) + __send__(subtest, time_class, tz, tz, tzname, abbr, utc_offset) + __send__(subtest, time_class, tz, tzname, tzname, abbr, utc_offset) end end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/