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

ruby-changes:56671

From: Nobuyoshi <ko1@a...>
Date: Sat, 27 Jul 2019 13:55:49 +0900 (JST)
Subject: [ruby-changes:56671] Nobuyoshi Nakada: 149e414ed5 (master): Initialize DST flag

https://git.ruby-lang.org/ruby.git/commit/?id=149e414ed5

From 149e414ed529d27aaeb0543bc133e08c782d8d41 Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Tue, 23 Apr 2019 13:09:34 +0900
Subject: Initialize DST flag

* time.c (zone_timelocal): initialize DST flag by asking the
  timezone object.  [Bug #15988]

diff --git a/spec/ruby/core/time/fixtures/classes.rb b/spec/ruby/core/time/fixtures/classes.rb
index ece7ed2..a648171 100644
--- a/spec/ruby/core/time/fixtures/classes.rb
+++ b/spec/ruby/core/time/fixtures/classes.rb
@@ -79,7 +79,7 @@ module TimeSpecs https://github.com/ruby/ruby/blob/trunk/spec/ruby/core/time/fixtures/classes.rb#L79
 
   class TimeWithFindTimezone < Time
     def self.find_timezone(name)
-      TimezoneWithName.new(name: name.to_s, offset: -10*60*60)
+      TimezoneWithName.new(name: name.to_s, offset: 5*3600+30*60)
     end
   end
 end
diff --git a/test/ruby/test_time_tz.rb b/test/ruby/test_time_tz.rb
index 68ce845..2a460aa 100644
--- a/test/ruby/test_time_tz.rb
+++ b/test/ruby/test_time_tz.rb
@@ -544,28 +544,47 @@ Europe/Lisbon  Sun Dec 31 23:59:59 1911 UT = Sun Dec 31 23:23:14 1911 LMT isdst= https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L544
 End
 
   class TZ
-    attr_reader :name, :offset
+    attr_reader :name, :offset, :offset2
 
-    def initialize(name, abbr, offset)
+    def initialize(name, abbr, offset, abbr2 = nil, offset2 = nil)
       @name = name
       @abbr = abbr
       @offset = offset
+      @abbr2 = abbr2
+      @offset2 = offset2
+    end
+
+    def dst?(t)
+      return false unless @offset2
+      case t when Integer
+        return nil
+      end
+      case t.mon
+      when 4..9
+        true
+      else
+        false
+      end
+    end
+
+    def offset(t)
+      (dst?(t) ? @offset2 : @offset)
     end
 
     def local_to_utc(t)
-      t - @offset
+      t - offset(t)
     end
 
     def utc_to_local(t)
-      t + @offset
+      t + offset(t)
     end
 
     def abbr(t)
-      @abbr
+      dst?(t) ? @abbr2 : @abbr
     end
 
     def ==(other)
-      @name == other.name and @abbr == other.abbr(0) and @offset == other.offset
+      @name == other.name and abbr(0) == other.abbr(0) and offset(0) == other.offset(0)
     end
 
     def inspect
@@ -576,33 +595,48 @@ end https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L595
 
 module TestTimeTZ::WithTZ
   def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
     t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
+    utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t)
     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_now(time_class, tz, tzarg, tzname, abbr, utc_offset)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
     t = time_class.now(in: tzarg)
     assert_equal(tz, t.zone)
   end
 
   def subtest_getlocal(time_class, tz, tzarg, tzname, abbr, utc_offset)
-    t = time_class.utc(2018, 9, 1, 12, 0, 0).getlocal(tzarg)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
+    utc = time_class.utc(2018, 9, 1, 12, 0, 0)
+    utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(utc)
+    t = utc.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, tzarg, tzname, abbr, utc_offset)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
     t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
+    utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t)
     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, tzarg, tzname, abbr, utc_offset)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
     t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg) + 4000
+    utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(t)
     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)
@@ -610,8 +644,11 @@ module TestTimeTZ::WithTZ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L644
   end
 
   def subtest_at(time_class, tz, tzarg, tzname, abbr, utc_offset)
-    h, m = (utc_offset / 60).divmod(60)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *utc_offset
     utc = time_class.utc(2018, 9, 1, 12, 0, 0)
+    utc_offset, abbr = utc_offset2, abbr2 if tz.dst?(utc)
+    h, m = (utc_offset / 60).divmod(60)
     t = time_class.at(utc, in: tzarg)
     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(utc.to_i, t.to_i)
@@ -622,12 +659,15 @@ module TestTimeTZ::WithTZ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L659
   end
 
   def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset)
+    abbr, abbr2 = *abbr
+    utc_offset, utc_offset2 = *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)
     assert_equal(t.utc_offset, (t2+1).utc_offset)
     assert_instance_of(t.zone.class, t2.zone)
+    assert_equal(t.dst?, t2.dst?)
   end
 
   def test_invalid_zone
@@ -652,22 +692,30 @@ module TestTimeTZ::WithTZ https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L692
 
   ZONES = {
     "Asia/Tokyo" => ["JST", +9*3600],
-    "America/Los_Angeles" => ["PDT", -7*3600],
+    "America/Los_Angeles" => ["PST", -8*3600, "PDT", -7*3600],
     "Africa/Ndjamena" => ["WAT", +1*3600],
   }
 
-  def make_timezone(tzname, abbr, utc_offset)
+  def make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil)
     self.class::TIME_CLASS.find_timezone(tzname)
   end
 
+  def subtest_dst?(time_class, tz, tzarg, tzname, abbr, utc_offset)
+    t = time_class.new(2018, 6, 22, 12, 0, 0, tzarg)
+    return unless tz.dst?(t)
+    assert_predicate t, :dst?
+    t = time_class.new(2018, 12, 22, 12, 0, 0, tzarg)
+    assert_not_predicate t, :dst?
+  end
+
   instance_methods(false).grep(/\Asub(?=test_)/) do |subtest|
     test = $'
-    ZONES.each_pair do |tzname, (abbr, utc_offset)|
+    ZONES.each_pair do |tzname, (abbr, utc_offset, abbr2, utc_offset2)|
       define_method("#{test}@#{tzname}") do
-        tz = make_timezone(tzname, abbr, utc_offset)
+        tz = make_timezone(tzname, abbr, utc_offset, abbr2, utc_offset2)
         time_class = self.class::TIME_CLASS
-        __send__(subtest, time_class, tz, tz, tzname, abbr, utc_offset)
-        __send__(subtest, time_class, tz, tzname, tzname, abbr, utc_offset)
+        __send__(subtest, time_class, tz, tz, tzname, [abbr, abbr2], [utc_offset, utc_offset2])
+        __send__(subtest, time_class, tz, tzname, tzname, [abbr, abbr2], [utc_offset, utc_offset2])
       end
     end
   end
@@ -694,8 +742,8 @@ class TestTimeTZ::DummyTZ < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_time_tz.rb#L742
     end
   end
 
-  def self.make_timezone(tzname, abbr, utc_offset)
-    TestTimeTZ::TZ.new(tzname, abbr, utc_offset)
+  def self.make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil)
+    TestTimeTZ::TZ.new(tzname, abbr, utc_offset, abbr2, utc_offset2)
   end
 end
 
diff --git a/time.c b/time.c
index 18f1b24..ed79288 100644
--- a/time.c
+++ b/time.c
@@ -2201,6 +2201,16 @@ extract_vtm(VALUE time, struct vtm *vtm, VALUE subsecx) https://github.com/ruby/ruby/blob/trunk/time.c#L2201
     return t;
 }
 
+static void
+zone_set_dst(VALUE zone, struct time_object *tobj, VALUE tm)
+{
+    ID id_dst_p;
+    VALUE dst;
+    CONST_ID(id_dst_p, "dst?");
+    dst = rb_check_funcall(zone, id_dst_p, 1, &tm);
+    tobj->vtm.isdst = (dst != Qundef && RTEST(dst));
+}
+
 static int
 zone_timelocal(VALUE zone, VALUE time)
 {
@@ -2220,6 +2230,7 @@ zone_timelocal(VALUE zone, VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L2230
         s = wadd(s, v2w(tobj->vtm.subsecx));
     }
     tobj->timew = s;
+    zone_set_dst(zone, tobj, tm);
     return 1;
 }
 
@@ -2239,6 +2250,7 @@ zone_localtime(VALUE zone, VALUE time) https://github.com/ruby/ruby/blob/trunk/time.c#L2250
     s = extract_vtm(local, &tobj->vtm, subsecx);
     tobj->tm_got = 1;
     zone_set_offset(zone, tobj, s, t);
+    zone_set_dst(zone, tobj, tm);
     return 1;
 }
 
@@ -5323,6 +5335,7 @@ end_submicro: ; https://github.com/ruby/ruby/blob/trunk/time.c#L5335
     if (!NIL_P(zone)) {
         zone = mload_zone(time, zone);
 	tobj->vtm.zone = zone;
+        zone_localtime(zone, time);
     }
 
     return time;
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

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