Class: Timezone::Zone

Inherits:
Object
  • Object
show all
Includes:
Comparable
Defined in:
lib/timezone/zone.rb

Overview

This object represents a real-world timezone. Each instance provides methods for converting UTC times to the local timezone and local times to UTC for any historical, present or future times.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name) ⇒ Timezone::Zone

Create a new timezone object using the timezone name.

Parameters:

  • name (String)

    the timezone name



49
50
51
52
53
54
55
# File 'lib/timezone/zone.rb', line 49

def initialize(name)
  if name.is_a?(Hash)
    legacy_initialize(name)
  else
    @name = name
  end
end

Instance Attribute Details

#nameString (readonly) Also known as: to_s

Returns the timezone name.

Returns:

  • (String)

    the timezone name



20
21
22
# File 'lib/timezone/zone.rb', line 20

def name
  @name
end

Class Method Details

.list(*args) ⇒ Object

Deprecated.

This functionality will be removed in the next release.



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/timezone/zone.rb', line 247

def list(*args)
  Deprecate.call(
    self,
    :list,
    '[DEPRECATED] `Zone::list` will be deprecated in the ' \
      'next release of the `timezone` gem. There will be no ' \
      'replacement.'.freeze
  )

  args = nil if args.empty? # set to nil if no args are provided
  zones = args || Configure.default_for_list || names
  list = names.select { |name| zones.include? name }

  @zones = []
  now = Time.now
  list.each do |name|
    item = new(name)
    @zones << {
      zone: item.name,
      title: Configure.replacements[item.name] || item.name,
      offset: item.utc_offset,
      utc_offset: (item.utc_offset / (60 * 60)),
      dst: item.dst?(now)
    }
  end
  @zones.sort_by! { |zone| zone[Configure.order_list_by] }
end

.namesObject

Deprecated.

This method will be replaced with ‘Timezone.names` in future versions of this gem.



235
236
237
238
239
240
241
242
243
244
# File 'lib/timezone/zone.rb', line 235

def names
  Deprecate.call(
    self,
    :names,
    '[DEPRECATED] `::Timezone::Zone.names` will be removed in ' \
      'the next gem release. Use `::Timezone.names` instead.'.freeze
  )

  Loader.names
end

Instance Method Details

#<=>(other) ⇒ -1, ...

Compare one timezone with another based on current UTC offset.

Parameters:

Returns:

  • (-1, 0, 1, nil)

    comparison based on current ‘utc_offset`.



226
227
228
229
230
# File 'lib/timezone/zone.rb', line 226

def <=>(other)
  return nil unless other.respond_to?(:utc_offset)

  utc_offset <=> other.utc_offset
end

#active_support_time_zoneObject

Deprecated.

This functionality will be removed in the next release.



110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/timezone/zone.rb', line 110

def active_support_time_zone
  Deprecate.call(
    self.class,
    :active_support_time_zone,
    '[DEPRECATED] `Zone#active_support_time_zone` will be ' \
      'deprecated in the next release of the `timezone` gem. There ' \
      'will be no replacement.'.freeze
  )

  @active_support_time_zone ||=
    Timezone::ActiveSupport.format(name, :internal)
end

#dst?(time) ⇒ Boolean

If, at the given time, the timezone was observing Daylight Savings.

Parameters:

  • time (#to_time)

    the source time

Returns:

  • (Boolean)

    whether the timezone, at the given time, was observing Daylight Savings Time



204
205
206
207
208
# File 'lib/timezone/zone.rb', line 204

def dst?(time)
  time = sanitize(time)

  rule_for_utc(time)[DST_BIT]
end

#inspectString

Returns a developer friendly representation of the object.

Returns:

  • (String)

    a developer friendly representation of the object



25
26
27
# File 'lib/timezone/zone.rb', line 25

def inspect
  "#<Timezone::Zone name: \"#{name}\">"
end

#legacy_initialize(options) ⇒ Object

Deprecated.

This functionality only exists for migration purposes.



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/timezone/zone.rb', line 84

def legacy_initialize(options)
  Deprecate.call(
    self.class,
    :initialize,
    '[DEPRECATED] Creating Zone objects using an options hash ' \
      'will be deprecated in the next release of the `timezone` ' \
      'gem. Use `Timezone::[]`, `Timezone::fetch` or ' \
      '`Timezone::lookup` instead.'.freeze
  )

  if options.key?(:lat) && options.key?(:lon)
    options[:zone] = timezone_id options[:lat], options[:lon]
  elsif options.key?(:latlon)
    options[:zone] = timezone_id(*options[:latlon])
  end

  if options[:zone].nil?
    raise Timezone::Error::NilZone,
      'No zone was found. Please specify a zone.'.freeze
  end

  @name = options[:zone]
  private_rules
end

#local_to_utc(time) ⇒ Time

Note:

The UTC equivalent is a “best guess”. There are cases where local times do not map to UTC at all (during a time skip forward). There are also cases where local times map to two distinct UTC times (during a fall back). All of these cases are approximated in this method and the first possible result is used instead.

Note:

A note about the handling of time arguments.

Because the UTC offset of a ‘Time` object in Ruby is not equivalent to a single timezone, the `time` argument in this method is first converted to a UTC equivalent before being used as a local time.

This prevents confusion between historical UTC offsets and the UTC offset that the ‘Time` object provides. For instance, if I pass a “local” time with offset `+8` but the timezone actually had an offset of `+9` at the given historical time, there is an inconsistency that must be resolved.

Did the user make a mistake; or is the offset intentional?

One approach to solving this problem would be to raise an error, but this means that the user then needs to calculate the appropriate local offset and append that to a UTC time to satisfy the function. This is impractical because the offset can already be calculated by this library. The user should only need to provide a time without an offset!

To resolve this inconsistency, the solution I chose was to scrub the offset. In the case where an offset is provided, the time is just converted to the UTC equivalent (without an offset). The resulting time is used as the local reference time.

For example, if the time ‘08:00 +2` is passed to this function, the local time is assumed to be `06:00`.

Converts the given local time to the UTC equivalent.

Parameters:

  • time (#to_time)

    the local time

Returns:

  • (Time)

    the time in UTC



180
181
182
183
184
# File 'lib/timezone/zone.rb', line 180

def local_to_utc(time)
  time = sanitize(time)

  time.utc - rule_for_local(time).rules.first[OFFSET_BIT]
end

#rulesObject

Deprecated.

This method will be removed in the next release.



72
73
74
75
76
77
78
79
80
81
# File 'lib/timezone/zone.rb', line 72

def rules
  Deprecate.call(
    self.class,
    :rules,
    '[DEPRECATED] `Zone#rules` will not be available in ' \
      'the next release of the `timezone` gem.'.freeze
  )

  private_rules
end

#time_with_offset(time) ⇒ Time

Converts the given time to the local timezone and includes the UTC offset in the result.

Parameters:

  • time (#to_time)

    the source time

Returns:

  • (Time)

    the time in the local timezone with the UTC offset



191
192
193
194
195
196
197
# File 'lib/timezone/zone.rb', line 191

def time_with_offset(time)
  time = sanitize(time)

  utc = utc_to_local(time)
  offset = utc_offset(time)
  Time.new(utc.year, utc.month, utc.day, utc.hour, utc.min, utc.sec, offset)
end

#utc_offset(time = nil) ⇒ Integer

Return the UTC offset (in seconds) for the given time.

Parameters:

  • time (#to_time) (defaults to: nil)

    (Time.now) the source time

Returns:

  • (Integer)

    the UTC offset (in seconds) in the local timezone



214
215
216
217
218
219
# File 'lib/timezone/zone.rb', line 214

def utc_offset(time = nil)
  time ||= Time.now
  time = sanitize(time)

  rule_for_utc(time)[OFFSET_BIT]
end

#utc_to_local(time) ⇒ Time Also known as: time

Note:

The resulting time is always a UTC time. If you would like a time with the appropriate offset, use ‘#time_with_offset` instead.

Converts the given time to the local timezone and does not include a UTC offset in the result.

Parameters:

  • time (#to_time)

    the source time

Returns:

  • (Time)

    the time in the local timezone



132
133
134
135
136
# File 'lib/timezone/zone.rb', line 132

def utc_to_local(time)
  time = sanitize(time)

  time.utc + utc_offset(time)
end

#valid?true

If this is a valid timezone.

Returns:

  • (true)

    if this is a valid timezone



32
33
34
# File 'lib/timezone/zone.rb', line 32

def valid?
  true
end

#zoneObject

Deprecated.

This method will be replaced with ‘Zone#name` in future versions of this gem.



59
60
61
62
63
64
65
66
67
68
69
# File 'lib/timezone/zone.rb', line 59

def zone
  Deprecate.call(
    self.class,
    :zone,
    '[DEPRECATED] `Zone#zone` will not be available in ' \
      'the next release of the `timezone` gem. Use `Zone#name` ' \
      'instead.'.freeze
  )

  name
end