Initialize DST flag
* time.c (zone_timelocal): initialize DST flag by asking the timezone object. [Bug #15988]
This commit is contained in:
parent
8bccbf3cfe
commit
149e414ed5
@ -79,7 +79,7 @@ module TimeSpecs
|
|||||||
|
|
||||||
class TimeWithFindTimezone < Time
|
class TimeWithFindTimezone < Time
|
||||||
def self.find_timezone(name)
|
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
|
end
|
||||||
end
|
end
|
||||||
|
@ -544,28 +544,47 @@ Europe/Lisbon Sun Dec 31 23:59:59 1911 UT = Sun Dec 31 23:23:14 1911 LMT isdst=
|
|||||||
End
|
End
|
||||||
|
|
||||||
class TZ
|
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
|
@name = name
|
||||||
@abbr = abbr
|
@abbr = abbr
|
||||||
@offset = offset
|
@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
|
end
|
||||||
|
|
||||||
def local_to_utc(t)
|
def local_to_utc(t)
|
||||||
t - @offset
|
t - offset(t)
|
||||||
end
|
end
|
||||||
|
|
||||||
def utc_to_local(t)
|
def utc_to_local(t)
|
||||||
t + @offset
|
t + offset(t)
|
||||||
end
|
end
|
||||||
|
|
||||||
def abbr(t)
|
def abbr(t)
|
||||||
@abbr
|
dst?(t) ? @abbr2 : @abbr
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other)
|
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
|
end
|
||||||
|
|
||||||
def inspect
|
def inspect
|
||||||
@ -576,33 +595,48 @@ end
|
|||||||
|
|
||||||
module TestTimeTZ::WithTZ
|
module TestTimeTZ::WithTZ
|
||||||
def subtest_new(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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)
|
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])
|
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)
|
h, m = (-utc_offset / 60).divmod(60)
|
||||||
assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i)
|
assert_equal(time_class.utc(2018, 9, 1, 12+h, m, 0).to_i, t.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
def subtest_now(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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)
|
t = time_class.now(in: tzarg)
|
||||||
assert_equal(tz, t.zone)
|
assert_equal(tz, t.zone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def subtest_getlocal(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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)
|
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([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)
|
assert_equal(time_class.utc(2018, 9, 1, 12, 0, 0), t)
|
||||||
end
|
end
|
||||||
|
|
||||||
def subtest_strftime(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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)
|
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, m = (utc_offset.abs / 60).divmod(60)
|
||||||
h = -h if utc_offset < 0
|
h = -h if utc_offset < 0
|
||||||
assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z"))
|
assert_equal("%+.2d%.2d %s" % [h, m, abbr], t.strftime("%z %Z"))
|
||||||
end
|
end
|
||||||
|
|
||||||
def subtest_plus(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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
|
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])
|
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)
|
m, s = (4000-utc_offset).divmod(60)
|
||||||
h, m = m.divmod(60)
|
h, m = m.divmod(60)
|
||||||
@ -610,8 +644,11 @@ module TestTimeTZ::WithTZ
|
|||||||
end
|
end
|
||||||
|
|
||||||
def subtest_at(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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 = 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)
|
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([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)
|
assert_equal(utc.to_i, t.to_i)
|
||||||
@ -622,12 +659,15 @@ module TestTimeTZ::WithTZ
|
|||||||
end
|
end
|
||||||
|
|
||||||
def subtest_marshal(time_class, tz, tzarg, tzname, abbr, utc_offset)
|
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)
|
t = time_class.new(2018, 9, 1, 12, 0, 0, tzarg)
|
||||||
t2 = Marshal.load(Marshal.dump(t))
|
t2 = Marshal.load(Marshal.dump(t))
|
||||||
assert_equal(t, t2)
|
assert_equal(t, t2)
|
||||||
assert_equal(t.utc_offset, t2.utc_offset)
|
assert_equal(t.utc_offset, t2.utc_offset)
|
||||||
assert_equal(t.utc_offset, (t2+1).utc_offset)
|
assert_equal(t.utc_offset, (t2+1).utc_offset)
|
||||||
assert_instance_of(t.zone.class, t2.zone)
|
assert_instance_of(t.zone.class, t2.zone)
|
||||||
|
assert_equal(t.dst?, t2.dst?)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_invalid_zone
|
def test_invalid_zone
|
||||||
@ -652,22 +692,30 @@ module TestTimeTZ::WithTZ
|
|||||||
|
|
||||||
ZONES = {
|
ZONES = {
|
||||||
"Asia/Tokyo" => ["JST", +9*3600],
|
"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],
|
"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)
|
self.class::TIME_CLASS.find_timezone(tzname)
|
||||||
end
|
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|
|
instance_methods(false).grep(/\Asub(?=test_)/) do |subtest|
|
||||||
test = $'
|
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
|
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
|
time_class = self.class::TIME_CLASS
|
||||||
__send__(subtest, time_class, tz, tz, 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, utc_offset)
|
__send__(subtest, time_class, tz, tzname, tzname, [abbr, abbr2], [utc_offset, utc_offset2])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -694,8 +742,8 @@ class TestTimeTZ::DummyTZ < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.make_timezone(tzname, abbr, utc_offset)
|
def self.make_timezone(tzname, abbr, utc_offset, abbr2 = nil, utc_offset2 = nil)
|
||||||
TestTimeTZ::TZ.new(tzname, abbr, utc_offset)
|
TestTimeTZ::TZ.new(tzname, abbr, utc_offset, abbr2, utc_offset2)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
13
time.c
13
time.c
@ -2201,6 +2201,16 @@ extract_vtm(VALUE time, struct vtm *vtm, VALUE subsecx)
|
|||||||
return t;
|
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
|
static int
|
||||||
zone_timelocal(VALUE zone, VALUE time)
|
zone_timelocal(VALUE zone, VALUE time)
|
||||||
{
|
{
|
||||||
@ -2220,6 +2230,7 @@ zone_timelocal(VALUE zone, VALUE time)
|
|||||||
s = wadd(s, v2w(tobj->vtm.subsecx));
|
s = wadd(s, v2w(tobj->vtm.subsecx));
|
||||||
}
|
}
|
||||||
tobj->timew = s;
|
tobj->timew = s;
|
||||||
|
zone_set_dst(zone, tobj, tm);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2239,6 +2250,7 @@ zone_localtime(VALUE zone, VALUE time)
|
|||||||
s = extract_vtm(local, &tobj->vtm, subsecx);
|
s = extract_vtm(local, &tobj->vtm, subsecx);
|
||||||
tobj->tm_got = 1;
|
tobj->tm_got = 1;
|
||||||
zone_set_offset(zone, tobj, s, t);
|
zone_set_offset(zone, tobj, s, t);
|
||||||
|
zone_set_dst(zone, tobj, tm);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5323,6 +5335,7 @@ end_submicro: ;
|
|||||||
if (!NIL_P(zone)) {
|
if (!NIL_P(zone)) {
|
||||||
zone = mload_zone(time, zone);
|
zone = mload_zone(time, zone);
|
||||||
tobj->vtm.zone = zone;
|
tobj->vtm.zone = zone;
|
||||||
|
zone_localtime(zone, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return time;
|
return time;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user