Exemplo n.º 1
0
 /**
  * Append a representation of the time zone of 'calendar' to 'buffer'.
  *
  * @param count the number of z or Z characters in the format string; "zzz" would be 3, for
  *     example.
  * @param generalTimeZone true if we should use a display name ("PDT") if available; false implies
  *     that we should use RFC 822 format ("-0800") instead. This corresponds to 'z' versus 'Z' in
  *     the format string.
  */
 private void appendTimeZone(StringBuffer buffer, int count, boolean generalTimeZone) {
   if (generalTimeZone) {
     TimeZone tz = calendar.getTimeZone();
     boolean daylight = (calendar.get(Calendar.DST_OFFSET) != 0);
     int style = count < 4 ? TimeZone.SHORT : TimeZone.LONG;
     if (!formatData.customZoneStrings) {
       buffer.append(tz.getDisplayName(daylight, style, formatData.locale));
       return;
     }
     // We can't call TimeZone.getDisplayName() because it would not use
     // the custom DateFormatSymbols of this SimpleDateFormat.
     String custom =
         TimeZoneNames.getDisplayName(formatData.zoneStrings, tz.getID(), daylight, style);
     if (custom != null) {
       buffer.append(custom);
       return;
     }
   }
   // We didn't find what we were looking for, so default to a numeric time zone.
   appendNumericTimeZone(buffer, count, generalTimeZone);
 }
  public static List<Map<String, Object>> getZonesList(Context context) {
    final Locale locale = Locale.getDefault();
    final Date now = new Date();

    // The display name chosen for each zone entry depends on whether the zone is one associated
    // with the country of the user's chosen locale. For "local" zones we prefer the "long name"
    // (e.g. "Europe/London" -> "British Summer Time" for people in the UK). For "non-local"
    // zones we prefer the exemplar location (e.g. "Europe/London" -> "London" for English
    // speakers from outside the UK). This heuristic is based on the fact that people are
    // typically familiar with their local timezones and exemplar locations don't always match
    // modern-day expectations for people living in the country covered. Large countries like
    // China that mostly use a single timezone (olson id: "Asia/Shanghai") may not live near
    // "Shanghai" and prefer the long name over the exemplar location. The only time we don't
    // follow this policy for local zones is when Android supplies multiple olson IDs to choose
    // from and the use of a zone's long name leads to ambiguity. For example, at the time of
    // writing Android lists 5 olson ids for Australia which collapse to 2 different zone names
    // in winter but 4 different zone names in summer. The ambiguity leads to the users
    // selecting the wrong olson ids.

    // Get the list of olson ids to display to the user.
    List<String> olsonIdsToDisplay = readTimezonesToDisplay(context);

    // Create a lookup of local zone IDs.
    Set<String> localZoneIds = new TreeSet<String>();
    for (String olsonId : TimeZoneNames.forLocale(locale)) {
      localZoneIds.add(olsonId);
    }

    // Work out whether the long names for the local entries that we would show by default would
    // be ambiguous.
    Set<String> localZoneNames = new TreeSet<String>();
    boolean localLongNamesAreAmbiguous = false;
    for (String olsonId : olsonIdsToDisplay) {
      if (localZoneIds.contains(olsonId)) {
        TimeZone tz = TimeZone.getTimeZone(olsonId);
        String zoneLongName = getZoneLongName(locale, tz, now);
        boolean longNameIsUnique = localZoneNames.add(zoneLongName);
        if (!longNameIsUnique) {
          localLongNamesAreAmbiguous = true;
          break;
        }
      }
    }

    // Generate the list of zone entries to return.
    List<Map<String, Object>> zones = new ArrayList<Map<String, Object>>();
    for (String olsonId : olsonIdsToDisplay) {
      final TimeZone tz = TimeZone.getTimeZone(olsonId);
      // Exemplar location display is the default. The only time we intend to display the long
      // name is when the olsonId is local AND long names are not ambiguous.
      boolean isLocalZoneId = localZoneIds.contains(olsonId);
      boolean preferLongName = isLocalZoneId && !localLongNamesAreAmbiguous;
      String displayName = getZoneDisplayName(locale, tz, now, preferLongName);

      String gmtOffsetString = getGmtOffsetString(locale, tz, now);
      int offsetMillis = tz.getOffset(now.getTime());
      Map<String, Object> displayEntry =
          createDisplayEntry(tz, gmtOffsetString, displayName, offsetMillis);
      zones.add(displayEntry);
    }
    return zones;
  }
 private static String getZoneExemplarLocation(Locale locale, TimeZone tz) {
   return TimeZoneNames.getExemplarLocation(locale.toString(), tz.getID());
 }