Project

General

Profile

Bug #15988

Time#dst? vs "real" timezones

Added by zverok (Victor Shepelev) 5 months ago. Updated 4 months ago.

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

Associated revisions

Revision 149e414e
Added by nobu (Nobuyoshi Nakada) 4 months ago

Initialize DST flag

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

History

Updated by zverok (Victor Shepelev) 5 months 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) 5 months 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) 5 months ago

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

#4

Updated by nobu (Nobuyoshi Nakada) 4 months 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]

Also available in: Atom PDF