Project

General

Profile

Actions

Bug #15988

closed

Time#dst? vs "real" timezones

Added by zverok (Victor Shepelev) over 5 years ago. Updated over 5 years ago.

Status:
Closed
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

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

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.

Actions #4

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]
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0