Project

General

Profile

Bug #15988

Time#dst? vs "real" timezones

Added by zverok (Victor Shepelev) 14 days ago. Updated 13 days ago.

Status:
Assigned
Priority:
Normal
Target version:
-
[ruby-core:93557]

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

time-zone-dst.patch (1.68 KB) time-zone-dst.patch jeremyevans0 (Jeremy Evans), 07/05/2019 08:56 PM

History

Updated by zverok (Victor Shepelev) 14 days 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) 13 days ago

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) 13 days ago

I've noticed it and have a patch, but haven't committed it yet as not written the test using dummy timezone objects.

Also available in: Atom PDF