[前][次][番号順一覧][スレッド一覧]

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/

[前][次][番号順一覧][スレッド一覧]