Class: RiCal::Component::Timezone

Inherits:
RiCal::Component show all
Includes:
Properties::Timezone
Defined in:
lib/ri_cal/component/timezone.rb,
lib/ri_cal/component/timezone/daylight_period.rb,
lib/ri_cal/component/timezone/standard_period.rb,
lib/ri_cal/component/timezone/timezone_period.rb

Overview

An Timezone (VTIMEZONE) calendar component describes a timezone used within the calendar. A Timezone has two or more TimezonePeriod subcomponents which describe the transitions between standard and daylight saving time.

to see the property accessing methods for this class see the RiCal::Properties::Timezone module

Direct Known Subclasses

TZInfoTimezone

Defined Under Namespace

Classes: DaylightPeriod, StandardPeriod, TimezonePeriod

Instance Attribute Summary

Attributes inherited from RiCal::Component

#imported

Instance Method Summary collapse

Methods included from Properties::Timezone

#==, #add_date_times_to, #export_properties_to, included, #initialize_copy, #last_modified, #last_modified=, #last_modified_property, #last_modified_property=, #last_modified_property_from_string, #mutual_exclusion_violation, #tzid, #tzid=, #tzid_property, #tzid_property=, #tzid_property_from_string, #tzurl, #tzurl=, #tzurl_property, #tzurl_property=, #tzurl_property_from_string

Methods inherited from RiCal::Component

#add_property_date_times_to, #add_subcomponent, #add_x_property, #alarms, #daylight, #default_tzid, entity_name, #entity_name, #export, #export_prop_to, #export_subcomponent_to, #export_to, #export_x_properties_to, #find_timezone, from_parser, #imported?, #initialize, #initialize_copy, #last_before_local, #last_before_utc, #last_period, #method_missing, parse, parse_string, #parse_subcomponent, #process_line, #prop_string, #standard, #subcomponent_class, #subcomponents, #time_zone_for, #to_s, #tz_info_source?, #valid?, #x_properties

Constructor Details

This class inherits a constructor from RiCal::Component

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RiCal::Component

Instance Method Details

#identifierObject

The identifier of the timezone, e.g. “Europe/Paris”.



17
18
19
# File 'lib/ri_cal/component/timezone.rb', line 17

def identifier
  tzid
end

#local_to_utc(time) ⇒ Object

convert time from this time zone to utc time



144
145
146
147
148
149
150
# File 'lib/ri_cal/component/timezone.rb', line 144

def local_to_utc(time)
  time = time.to_ri_cal_date_time_value
  period = period_for_local(time)
  converted = time - period.tzoffsetto_property
  converted.tzid = "UTC"
  converted
end

#nameObject

An alias for identifier.



22
23
24
25
# File 'lib/ri_cal/component/timezone.rb', line 22

def name
  # Don't use alias, as identifier gets overridden.
  identifier
end

#period_for_local(local, dst = nil) ⇒ Object

Returns the TimezonePeriod for the given local time. local can either be a DateTime, Time or integer timestamp (Time.to_i). Any timezone information in local is ignored (it is treated as a time in the current timezone).

Warning: There are local times that have no equivalent UTC times (e.g. in the transition from standard time to daylight savings time). There are also local times that have more than one UTC equivalent (e.g. in the transition from daylight savings time to standard time).

In the first case (no equivalent UTC time), a PeriodNotFound exception will be raised.

In the second case (more than one equivalent UTC time), an AmbiguousTime exception will be raised unless the optional dst parameter or block handles the ambiguity.

If the ambiguity is due to a transition from daylight savings time to standard time, the dst parameter can be used to select whether the daylight savings time or local time is used. For example,

Timezone.get('America/New_York').period_for_local(DateTime.new(2004,10,31,1,30,0))

would raise an AmbiguousTime exception.

Specifying dst=true would the daylight savings period from April to October 2004. Specifying dst=false would return the standard period from October 2004 to April 2005.

If the dst parameter does not resolve the ambiguity, and a block is specified, it is called. The block must take a single parameter - an array of the periods that need to be resolved. The block can select and return a single period or return nil or an empty array to cause an AmbiguousTime exception to be raised.

TODO: need to check for ambiguity



100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/ri_cal/component/timezone.rb', line 100

def period_for_local(local, dst=nil)
  results = periods_for_local(local)

  if results.empty?
    raise TZInfo::PeriodNotFound
  elsif results.size < 2
    results.first
  else
    # ambiguous result try to resolve

    unless dst.nil?
      matches = results.find_all {|period| period.dst? == dst}
      results = matches unless matches.empty?
    end

    if results.size < 2
      results.first
    else
      # still ambiguous, try the block

      if block_given?
        results = yield results
      end

      if results.is_a?(TimezonePeriod)
        results
      elsif results && results.size == 1
        results.first
      else
        raise TZInfo::AmbiguousTime, "#{local} is an ambiguous local time."
      end
    end
  end
end

#period_for_utc(time) ⇒ Object

Returns the TimezonePeriod for the given UTC time. utc can either be a DateTime, Time or integer timestamp (Time.to_i). Any timezone information in utc is ignored (it is treated as a UTC time).



34
35
36
# File 'lib/ri_cal/component/timezone.rb', line 34

def period_for_utc(time)
  last_period(last_before_utc(standard, time), last_before_utc(daylight, time))
end

#periods_for_local(local) ⇒ Object

Returns the set of TimezonePeriod instances that are valid for the given local time as an array. If you just want a single period, use period_for_local instead and specify how ambiguities should be resolved. Returns an empty array if no periods are found for the given time.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/ri_cal/component/timezone.rb', line 42

def periods_for_local(local)
  local = local.to_ri_cal_date_time_value
  candidate_standard = last_before_local(standard, local)
  candidate_daylight = last_before_local(daylight, local)
  if candidate_daylight && candidate_daylight.swallows_local?(local, candidate_standard)
    []  # Invalid local time
  elsif candidate_standard
    if candidate_daylight
      if candidate_daylight.dtstart > candidate_standard.dtstart
        [candidate_daylight]
      elsif candidate_standard.ambiguous_local?(local)
        [candidate_daylight, candidate_standard]
      else
        [candidate_standard].compact
      end
    else
      [candidate_standard].compact
    end
  end
end

#rational_utc_offset(local) ⇒ Object

:nodoc:



27
28
29
30
# File 'lib/ri_cal/component/timezone.rb', line 27

def rational_utc_offset(local) #:nodoc:
  # 86400 is the number of seconds in a day
  RiCal.RationalOffset[period_for_local(local, true).utc_total_offset]
end

#utc_to_local(time) ⇒ Object

convert time from utc time to this time zone



136
137
138
139
140
141
# File 'lib/ri_cal/component/timezone.rb', line 136

def utc_to_local(time)
  time = time.to_ri_cal_date_time_value
  converted = time + period_for_utc(time).tzoffsetto_property
  converted.tzid = identifier
  converted
end