Bug #15988
closedTime#dst? vs "real" timezones
Description
My current timezone is Europe/Kiev.
With default zone (how it was previously):
summer = Time.new(2019, 6, 1, 14, 30, 12) # => 2019-06-01 14:30:12 +0300
summer.zone # => "EEST"
summer.dst? # => true
winter = Time.new(2019, 12, 1, 14, 30, 12) # => 2019-12-01 14:30:12 +0200
winter.zone # => "EET"
winter.dst? # => false
(Note it is correctly true
in summer and false
in winter.)
With "real" timezone object
require 'tzinfo'
z = TZInfo::Timezone.get('Europe/Kiev')
# => #<TZInfo::DataTimezone: Europe/Kiev>
summer = Time.new(2019, 6, 1, 14, 30, 12, z) # => 2019-06-01 14:30:12 +0300
summer.zone # => #<TZInfo::DataTimezone: Europe/Kiev>
summer.dst? # => true
winter = Time.new(2019, 12, 1, 14, 30, 12, z) # => 2019-12-01 14:30:12 +0200 -- offset is correct
winter.zone # => #<TZInfo::DataTimezone: Europe/Kiev>
winter.dst? # => true -- this is wrong!
Note that offsets are calculated correctly (+3 in summer, +2 in winter), but dst?
is always true
.
TZInfo itself calculates DST properly:
z.dst?(summer) # => true
z.dst?(winter) # => false
Seems like a serious bug to me (or at least very hard to explain behavior).
PS: With arithmetics, everything works correctly:
six_months = 6 * 30 * 24 * 60 * 60
summer + six_months # => 2019-11-28 13:30:12 +0200
(summer + six_months).dst? # => false -- that is correct
Files
Updated by zverok (Victor Shepelev) over 5 years ago
Even funnier:
winter = Time.new(2019, 12, 1, 14, 30, 12, z) # => 2019-12-01 14:30:12 +0200 -- offset is correct
winter.dst? # => true -- this is wrong!
(winter + 1).dst? # => false -- fixed!
summer = Time.new(2019, 6, 1, 14, 30, 12, z) # => 2019-06-01 14:30:12 +0300
summer.dst? # => true
(summer + 1).dst? # => false -- what?..
Updated by jeremyevans0 (Jeremy Evans) over 5 years ago
- File time-zone-dst.patch time-zone-dst.patch added
- Status changed from Open to Assigned
- Assignee set to nobu (Nobuyoshi Nakada)
The behavior seems even worse in the master branch and 2.7.0-preview1, with a RuntimeError without a calculation, and always false after a calculation:
require 'tzinfo'
z = TZInfo::Timezone.get('Europe/Kiev')
t = Time.new(2019, 6, 1, 14, 30, 12, z)
t.dst?
# RuntimeError (isdst is not set yet)
(t + 1).dst?
# false
(t + 6 * 30 * 24 * 60 * 60).dst?
# false
Attached is a patch that calls dst?
on the timezone object to determine whether the time is in daylight savings time in the zone. This does add a method called on the timezone argument, though, so I'm not sure how acceptable it is. Both the tzinfo and timezone libraries appear to implement the method already.
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
I've noticed it and have a patch, but haven't committed it yet as not written the test using dummy timezone objects.
Updated by nobu (Nobuyoshi Nakada) over 5 years ago
- Status changed from Assigned to Closed
Applied in changeset git|149e414ed529d27aaeb0543bc133e08c782d8d41.
Initialize DST flag
- time.c (zone_timelocal): initialize DST flag by asking the
timezone object. [Bug #15988]