# CalInvite::IcalTimezone

Builds RFC 5545 VTIMEZONE components and converts UTC times to local wall-clock
time for a given IANA/Olson timezone identifier, using TZInfo (already pulled in
transitively via activesupport).

Only uses TZInfo APIs available in both tzinfo 1.2+ (pinned by Rails 6.0) and
2.x; the few period accessors renamed in 2.x go through {period_starts_at},
{period_ends_at} and {period_local_ends_at}.

Event validates `timezone` with {valid?}, so by the time a provider runs it's
either UTC or a TZInfo-recognized identifier. {local_time} and
{vtimezone_lines} still fail soft (return nil) for UTC or unrecognized input.

@api private

_module_ defined in `lib/cal_invite/ical_timezone.rb`

## Instance methods

### `fixed_observance_lines(period)`

@api private

### `format_offset(seconds)`

@api private

### `local_time(tzid, utc_time)`

Converts a UTC time to local wall-clock time for the given timezone.

@param tzid [String] An IANA timezone identifier, e.g. "America/New_York"
@param utc_time [Time] The time to convert (interpreted as UTC)
@return [Time, nil] The local wall-clock time, or nil if tzid is unrecognized

### `observance_lines(kind, from_period, to_period)`

@api private

### `period_after(tz, period)`

@api private

### `period_before(tz, period)`

@api private

### `period_ends_at(period)`

@api private

### `period_local_ends_at(period)`

@api private

### `period_starts_at(period)`

@api private

### `rrule_line(time)`

Derives a YEARLY RRULE (e.g. "2nd Sunday in March") from a transition date.

@api private

### `utc?(tzid)`

Whether `tzid` means UTC (case-insensitive 'UTC'), which needs no VTIMEZONE:
times are emitted as `Z`-suffixed UTC timestamps instead.

@param tzid [String, nil] The timezone identifier
@return [Boolean]

### `valid?(tzid)`

Whether `tzid` is usable as an event timezone: UTC or a TZInfo-recognized
IANA identifier (e.g. "America/New_York"). Raw offsets like "+01:00" aren't:
they have no VTIMEZONE definition.

@param tzid [String, nil] The timezone identifier
@return [Boolean]

### `vtimezone_lines(tzid)`

Builds a complete VTIMEZONE component (STANDARD/DAYLIGHT observances with
RRULEs derived from the timezone's actual transition rules) for the given
timezone identifier.

@param tzid [String] An IANA timezone identifier, e.g. "America/New_York"
@return [Array<String>, nil] iCalendar lines for the VTIMEZONE component, or
  nil if tzid is unrecognized, is UTC, or the component can't be built
