Feature #15527

Redesign of timezone object requirements

Added by zverok (Victor Shepelev) 10 days ago. Updated 7 days ago.

Target version:


In #14850, there was timezone support introduced, there were pretty specific requirements for the Timezone object:

A timezone argument must have local_to_utc and utc_to_local methods... The local_to_utc method should convert a Time-like object from the timezone to UTC, and utc_to_local is the opposite. ... The zone of the result is just ignored.

I understand this requirements were modelled after existing TZInfo gem, but the problem with them are:

  • they are too ad-hoc (in fact, return values of methods aren't used as a "Time object", but as a tuple of time components)
  • they belong to outdated tzinfo API (ignoring of offsets is due to support of Ruby 1.8, which didn't allowed constructing Time object with arbitrary offset, see discussion), recent release introduces also #to_local, which returns Time with proper offset.

The latter is a bit of time paradox: Ruby 2.6 new feature is designed after the library which works this way to support Ruby 1.8 :)
The bad thing is, this approach somehow "codifies" outdated API (so in future, any alternative timezone library should support pretty arbitrary API).

I believe, that in order to do everything that Time needs, timezone object should be able to answer exactly one question: "what offset from UTC is/was observed in this timezone at particular date". In fact, TZInfo has the API for this:

tz = TZInfo::Timezone.get('America/New_York')
# => #<TZInfo::DataTimezone: America/New_York> 
# => -18000 

If I understand correctly, this requirement ("A timezone argument must have #utc_offset(at_time)") will greatly simplify the implementation of Time, while also being compatible with TZInfo gem and much more explainable. With this requirement, alternative implementations could now be much simpler and focus only on "find the proper timezone/period/offset", omitting any (hard) details of deconstructing/constructing Time objects.


Updated by naruse (Yui NARUSE) 9 days ago

Sounds interesting, but zone.utc_offset(time) can only be a partial alternative of utc_to_local with using `gmtime(3).

Note that a timezone system requires two API.
One is an API which converts from [year, month, day, hour, minute, second] to epoch.
And another is an API which converts from epoch to [year, month, day, hour, minute, second, isdst, zonestr].

Updated by zverok (Victor Shepelev) 7 days ago

Note that a timezone system requires two API.

Sorry for my arrogance, but can you please explain this a bit?..
From what I can understand from code, local_to_utc is used only from, but I am not quite sure why exactly.
From "logical" point of view, we need just to understand what exact UTC offset it should have (so it covered with Zone#utc_offset), the only uncertainty here is what exact moment we want UTC offset for -- this can fire in the foot at DST change moment, but I am not sure how a pair of APIs could help here.

Also available in: Atom PDF