class TwitterCldr::Timezones::GenericLocation

Constants

DEFAULT_CITY_EXCLUSION_PATTERN
DST_CHECK_RANGE
FORMATS
Territories
UNKNOWN_DEFAULT
Utils

Public Instance Methods

display_name_for(date, fmt = :generic_location) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 24
def display_name_for(date, fmt = :generic_location)
  case fmt
    when :generic_location
      generic_location_display_name
    when :generic_short
      generic_short_display_name(date) || generic_location_display_name
    when :generic_long
      generic_long_display_name(date) || generic_location_display_name
    when :specific_short
      specific_short_display_name(date)
    when :specific_long
      specific_long_display_name(date)
    when :exemplar_location
      exemplar_city
    else
      raise ArgumentError, "'#{fmt}' is not a valid generic timezone format, "\
        "must be one of #{FORMATS.join(', ')}"
  end
end

Private Instance Methods

default_exemplar_city() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 189
def default_exemplar_city
  @default_exemplar_city ||= begin
    return nil if tz_id =~ DEFAULT_CITY_EXCLUSION_PATTERN

    sep = tz_id.rindex('/')

    if sep && sep + 1 < tz_id.length
      return tz_id[(sep + 1)..-1].gsub('_', ' ')
    end

    nil
  end
end
exemplar_city() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 162
def exemplar_city
  @exemplar_city ||=
    timezone_data[:city] ||
    default_exemplar_city ||
    unknown_city ||
    UNKNOWN_DEFAULT
end
fallback_formats() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 219
def fallback_formats
  @fallback_formats ||= resource[:formats][:fallback_formats]
end
format_display_name(date, type, fmt) click to toggle source

From ICU source, TimeZoneGenericNames.java, formatGenericNonLocationName():

  1. If a generic non-location string is available for the zone, return it.

  2. If a generic non-location string is associated with a meta zone and the zone never use daylight time around the given date, use the standard string (if available).

  3. If a generic non-location string is associated with a meta zone and the offset at the given time is different from the preferred zone for the current locale, then return the generic partial location string (if available)

  4. If a generic non-location string is not available, use generic location string.

# File lib/twitter_cldr/timezones/generic_location.rb, line 89
def format_display_name(date, type, fmt)
  date_int = date.strftime('%s').to_i
  period = tz.period_for_local(date)

  flavor = if type == :generic
    :generic
  elsif type == :specific
    period.std_offset > 0 ? :daylight : :standard
  end

  if explicit = (timezone_data[fmt] || {})[flavor]
    return explicit
  end

  if tz_metazone = ZoneMeta.tz_metazone_for(tz_id, date)
    if use_standard?(date_int, period)
      std_name = tz_name_for(fmt, :standard) || mz_name_for(fmt, :standard, tz_metazone.mz_id)
      mz_generic_name = mz_name_for(fmt, :generic, tz_metazone.mz_id)

      # From ICU source, TimeZoneGenericNames.java, formatGenericNonLocationName():
      #
      # In CLDR, the same display name is used for both generic and standard
      # for some meta zones in some locales. This looks like data bugs. For
      # now, we check if the standard name is different from its generic name.
      return std_name if std_name && std_name != mz_generic_name
    end

    mz_name = mz_name_for(fmt, flavor, tz_metazone.mz_id)

    # don't go through all the golden zone logic if we're not computing the
    # generic format
    return mz_name if type == :specific

    golden_zone_id = tz_metazone.metazone.reference_tz_id

    if golden_zone_id != tz_id
      golden_zone = TZInfo::Timezone.get(golden_zone_id)
      golden_period = golden_zone.period_for_local(date)

      if period.utc_offset != golden_period.utc_offset || period.std_offset != golden_period.std_offset
        return nil unless mz_name
        return partial_location_name_for(tz_metazone.metazone, mz_name)
      else
        return mz_name
      end
    else
      return mz_name
    end
  end
end
generic_location_display_name() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 46
def generic_location_display_name
  if region_code = ZoneMeta.canonical_country_for(tz.identifier)
    if ZoneMeta.is_primary_region?(region_code, tz_id)
      region_name = Territories.from_territory_code_for_locale(region_code, tz.locale)
      return region_formats[:generic].sub('{0}', region_name || region_code)
    else
      # From ICU source, TimeZoneGenericNames.java, getGenericLocationName():
      #
      # exemplar location should return non-empty String
      # if the time zone is associated with a location
      return region_formats[:generic].sub('{0}', exemplar_city || region_code)
    end
  end
end
generic_long_display_name(date) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 65
def generic_long_display_name(date)
  format_display_name(date, :generic, :long)
end
generic_short_display_name(date) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 61
def generic_short_display_name(date)
  format_display_name(date, :generic, :short)
end
metazone_data() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 211
def metazone_data
  @metazone_data ||= resource[:metazones]
end
mz_name_for(fmt, flavor, mz_id) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 174
def mz_name_for(fmt, flavor, mz_id)
  Utils.traverse_hash(metazone_data, [mz_id.to_sym, fmt, flavor])
end
partial_location_name_for(metazone, mz_name) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 140
def partial_location_name_for(metazone, mz_name)
  region_code = ZoneMeta.canonical_country_for(tz_id)

  location = if region_code
    if region_code == metazone.reference_region_code
      Territories.from_territory_code_for_locale(region_code)
    else
      exemplar_city
    end
  else
    exemplar_city ? exemplar_city : tz_id
  end

  fallback_formats[:generic]
    .sub('{0}', location)
    .sub('{1}', mz_name || '')
end
region_formats() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 215
def region_formats
  @region_format ||= resource[:formats][:region_formats]
end
specific_long_display_name(date) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 73
def specific_long_display_name(date)
  format_display_name(date, :specific, :long)
end
specific_short_display_name(date) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 69
def specific_short_display_name(date)
  format_display_name(date, :specific, :short)
end
target_region_code() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 158
def target_region_code
  @target_region_code ||= tz.orig_locale.region || tz.max_locale.region
end
timezone_data() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 207
def timezone_data
  @timezone_data ||= (resource[:timezones][tz_id.to_sym] || {})
end
tz_name_for(fmt, flavor) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 170
def tz_name_for(fmt, flavor)
  Utils.traverse_hash(timezone_data[:timezones], [tz_id.to_sym, fmt, flavor])
end
unknown_city() click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 203
def unknown_city
  @unknown_city ||= resource[:timezones][:'Etc/Unknown'][:city]
end
use_standard?(date_int, transition_offset) click to toggle source
# File lib/twitter_cldr/timezones/generic_location.rb, line 178
def use_standard?(date_int, transition_offset)
  prev_trans = tz.transitions_up_to(Time.at(date_int - DST_CHECK_RANGE)).last
  next_trans = tz.transitions_up_to(Time.at(date_int + DST_CHECK_RANGE)).last

  return false if transition_offset.std_offset != 0
  return false if prev_trans && prev_trans.offset.std_offset != 0
  return false if next_trans && next_trans.offset.std_offset != 0

  true
end