diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-28 14:08:31 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-11-28 14:08:31 +0000 |
commit | 337b4b634495f247711cb25636364cc7f967e457 (patch) | |
tree | e05a5a70a05aae8e7eeb543eee93bd44e9a70f09 | |
parent | fe08f99e9388c9f4f2eccc66a260330252c62a81 (diff) |
Try Time.find_timezone to convert name to timezone
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@66076 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | test/ruby/test_time_tz.rb | 31 | ||||
-rw-r--r-- | time.c | 71 |
2 files changed, 74 insertions, 28 deletions
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb index f6635f6ce1..5360666d3c 100644 --- a/test/ruby/test_time_tz.rb +++ b/test/ruby/test_time_tz.rb @@ -503,41 +503,49 @@ End 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 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 @@ -642,6 +642,7 @@ static uint32_t obj2subsecx(VALUE obj, VALUE *subsecx); 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) 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) 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 time) 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 time) 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) 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) 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, VALUE time) 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, VALUE time) 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, VALUE time) * * 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 |