Esempio n. 1
0
 private static String[] getDisplayNameArray(int field, boolean isLong, Locale locale) {
   DateFormatSymbols dfs = new DateFormatSymbols(locale);
   switch (field) {
     case Calendar.AM_PM:
       return dfs.getAmPmStrings();
     case Calendar.DAY_OF_WEEK:
       return isLong ? dfs.getWeekdays() : dfs.getShortWeekdays();
     case Calendar.ERA:
       return dfs.getEras();
     case Calendar.MONTH:
       return isLong ? dfs.getMonths() : dfs.getShortMonths();
   }
   return null;
 }
  /**
   * This method parses the specified string into a date.
   *
   * @param dateStr The date string to parse.
   * @param pos The input and output parse position
   * @return The parsed date, or <code>null</code> if the string cannot be parsed.
   */
  public Date parse(String dateStr, ParsePosition pos) {
    int fmt_index = 0;
    int fmt_max = pattern.length();

    calendar.clear();
    boolean saw_timezone = false;
    int quote_start = -1;
    boolean is2DigitYear = false;
    try {
      for (; fmt_index < fmt_max; ++fmt_index) {
        char ch = pattern.charAt(fmt_index);
        if (ch == '\'') {
          int index = pos.getIndex();
          if (fmt_index < fmt_max - 1 && pattern.charAt(fmt_index + 1) == '\'') {
            if (!expect(dateStr, pos, ch)) return null;
            ++fmt_index;
          } else quote_start = quote_start < 0 ? fmt_index : -1;
          continue;
        }

        if (quote_start != -1 || ((ch < 'a' || ch > 'z') && (ch < 'A' || ch > 'Z'))) {
          if (!expect(dateStr, pos, ch)) return null;
          continue;
        }

        // We've arrived at a potential pattern character in the
        // pattern.
        int fmt_count = 1;
        while (++fmt_index < fmt_max && pattern.charAt(fmt_index) == ch) {
          ++fmt_count;
        }

        // We might need to limit the number of digits to parse in
        // some cases.  We look to the next pattern character to
        // decide.
        boolean limit_digits = false;
        if (fmt_index < fmt_max && standardChars.indexOf(pattern.charAt(fmt_index)) >= 0)
          limit_digits = true;
        --fmt_index;

        // We can handle most fields automatically: most either are
        // numeric or are looked up in a string vector.  In some cases
        // we need an offset.  When numeric, `offset' is added to the
        // resulting value.  When doing a string lookup, offset is the
        // initial index into the string array.
        int calendar_field;
        boolean is_numeric = true;
        int offset = 0;
        boolean maybe2DigitYear = false;
        boolean oneBasedHour = false;
        boolean oneBasedHourOfDay = false;
        Integer simpleOffset;
        String[] set1 = null;
        String[] set2 = null;
        switch (ch) {
          case 'd':
            calendar_field = Calendar.DATE;
            break;
          case 'D':
            calendar_field = Calendar.DAY_OF_YEAR;
            break;
          case 'F':
            calendar_field = Calendar.DAY_OF_WEEK_IN_MONTH;
            break;
          case 'E':
            is_numeric = false;
            offset = 1;
            calendar_field = Calendar.DAY_OF_WEEK;
            set1 = formatData.getWeekdays();
            set2 = formatData.getShortWeekdays();
            break;
          case 'w':
            calendar_field = Calendar.WEEK_OF_YEAR;
            break;
          case 'W':
            calendar_field = Calendar.WEEK_OF_MONTH;
            break;
          case 'M':
            calendar_field = Calendar.MONTH;
            if (fmt_count <= 2) offset = -1;
            else {
              is_numeric = false;
              set1 = formatData.getMonths();
              set2 = formatData.getShortMonths();
            }
            break;
          case 'y':
            calendar_field = Calendar.YEAR;
            if (fmt_count <= 2) maybe2DigitYear = true;
            break;
          case 'K':
            calendar_field = Calendar.HOUR;
            break;
          case 'h':
            calendar_field = Calendar.HOUR;
            oneBasedHour = true;
            break;
          case 'H':
            calendar_field = Calendar.HOUR_OF_DAY;
            break;
          case 'k':
            calendar_field = Calendar.HOUR_OF_DAY;
            oneBasedHourOfDay = true;
            break;
          case 'm':
            calendar_field = Calendar.MINUTE;
            break;
          case 's':
            calendar_field = Calendar.SECOND;
            break;
          case 'S':
            calendar_field = Calendar.MILLISECOND;
            break;
          case 'a':
            is_numeric = false;
            calendar_field = Calendar.AM_PM;
            set1 = formatData.getAmPmStrings();
            break;
          case 'z':
          case 'Z':
            // We need a special case for the timezone, because it
            // uses a different data structure than the other cases.
            is_numeric = false;
            calendar_field = Calendar.ZONE_OFFSET;
            String[][] zoneStrings = formatData.getZoneStrings();
            int zoneCount = zoneStrings.length;
            int index = pos.getIndex();
            boolean found_zone = false;
            simpleOffset = computeOffset(dateStr.substring(index));
            if (simpleOffset != null) {
              found_zone = true;
              saw_timezone = true;
              calendar.set(Calendar.DST_OFFSET, 0);
              offset = simpleOffset.intValue();
            } else {
              for (int j = 0; j < zoneCount; j++) {
                String[] strings = zoneStrings[j];
                int k;
                for (k = 0; k < strings.length; ++k) {
                  if (dateStr.startsWith(strings[k], index)) break;
                }
                if (k != strings.length) {
                  found_zone = true;
                  saw_timezone = true;
                  TimeZone tz = TimeZone.getTimeZone(strings[0]);
                  // Check if it's a DST zone or ordinary
                  if (k == 3 || k == 4) calendar.set(Calendar.DST_OFFSET, tz.getDSTSavings());
                  else calendar.set(Calendar.DST_OFFSET, 0);
                  offset = tz.getRawOffset();
                  pos.setIndex(index + strings[k].length());
                  break;
                }
              }
            }
            if (!found_zone) {
              pos.setErrorIndex(pos.getIndex());
              return null;
            }
            break;
          default:
            pos.setErrorIndex(pos.getIndex());
            return null;
        }

        // Compute the value we should assign to the field.
        int value;
        int index = -1;
        if (is_numeric) {
          numberFormat.setMinimumIntegerDigits(fmt_count);
          if (limit_digits) numberFormat.setMaximumIntegerDigits(fmt_count);
          if (maybe2DigitYear) index = pos.getIndex();
          Number n = numberFormat.parse(dateStr, pos);
          if (pos == null || !(n instanceof Long)) return null;
          value = n.intValue() + offset;
        } else if (set1 != null) {
          index = pos.getIndex();
          int i;
          boolean found = false;
          for (i = offset; i < set1.length; ++i) {
            if (set1[i] != null)
              if (dateStr.toUpperCase().startsWith(set1[i].toUpperCase(), index)) {
                found = true;
                pos.setIndex(index + set1[i].length());
                break;
              }
          }
          if (!found && set2 != null) {
            for (i = offset; i < set2.length; ++i) {
              if (set2[i] != null)
                if (dateStr.toUpperCase().startsWith(set2[i].toUpperCase(), index)) {
                  found = true;
                  pos.setIndex(index + set2[i].length());
                  break;
                }
            }
          }
          if (!found) {
            pos.setErrorIndex(index);
            return null;
          }
          value = i;
        } else value = offset;

        if (maybe2DigitYear) {
          // Parse into default century if the numeric year string has
          // exactly 2 digits.
          int digit_count = pos.getIndex() - index;
          if (digit_count == 2) {
            is2DigitYear = true;
            value += defaultCentury;
          }
        }

        // Calendar uses 0-based hours.
        // I.e. 00:00 AM is midnight, not 12 AM or 24:00
        if (oneBasedHour && value == 12) value = 0;

        if (oneBasedHourOfDay && value == 24) value = 0;

        // Assign the value and move on.
        calendar.set(calendar_field, value);
      }

      if (is2DigitYear) {
        // Apply the 80-20 heuristic to dermine the full year based on
        // defaultCenturyStart.
        int year = calendar.get(Calendar.YEAR);
        if (calendar.getTime().compareTo(defaultCenturyStart) < 0)
          calendar.set(Calendar.YEAR, year + 100);
      }
      if (!saw_timezone) {
        // Use the real rules to determine whether or not this
        // particular time is in daylight savings.
        calendar.clear(Calendar.DST_OFFSET);
        calendar.clear(Calendar.ZONE_OFFSET);
      }
      return calendar.getTime();
    } catch (IllegalArgumentException x) {
      pos.setErrorIndex(pos.getIndex());
      return null;
    }
  }
Esempio n. 3
0
  /**
   * Returns a list of Rules given a pattern.
   *
   * @return a {@code List} of Rule objects
   * @throws IllegalArgumentException if pattern is invalid
   */
  protected List<Rule> parsePattern() {
    DateFormatSymbols symbols = new DateFormatSymbols(mLocale);
    List<Rule> rules = new ArrayList<Rule>();

    String[] ERAs = symbols.getEras();
    String[] months = symbols.getMonths();
    String[] shortMonths = symbols.getShortMonths();
    String[] weekdays = symbols.getWeekdays();
    String[] shortWeekdays = symbols.getShortWeekdays();
    String[] AmPmStrings = symbols.getAmPmStrings();

    int length = mPattern.length();
    int[] indexRef = new int[1];

    for (int i = 0; i < length; i++) {
      indexRef[0] = i;
      String token = parseToken(mPattern, indexRef);
      i = indexRef[0];

      int tokenLen = token.length();
      if (tokenLen == 0) {
        break;
      }

      Rule rule;
      char c = token.charAt(0);

      switch (c) {
        case 'G': // era designator (text)
          rule = new TextField(Calendar.ERA, ERAs);
          break;
        case 'y': // year (number)
          if (tokenLen == 2) {
            rule = TwoDigitYearField.INSTANCE;
          } else {
            rule = selectNumberRule(Calendar.YEAR, tokenLen < 4 ? 4 : tokenLen);
          }
          break;
        case 'M': // month in year (text and number)
          if (tokenLen >= 4) {
            rule = new TextField(Calendar.MONTH, months);
          } else if (tokenLen == 3) {
            rule = new TextField(Calendar.MONTH, shortMonths);
          } else if (tokenLen == 2) {
            rule = TwoDigitMonthField.INSTANCE;
          } else {
            rule = UnpaddedMonthField.INSTANCE;
          }
          break;
        case 'd': // day in month (number)
          rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen);
          break;
        case 'h': // hour in am/pm (number, 1..12)
          rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen));
          break;
        case 'H': // hour in day (number, 0..23)
          rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen);
          break;
        case 'm': // minute in hour (number)
          rule = selectNumberRule(Calendar.MINUTE, tokenLen);
          break;
        case 's': // second in minute (number)
          rule = selectNumberRule(Calendar.SECOND, tokenLen);
          break;
        case 'S': // millisecond (number)
          rule = selectNumberRule(Calendar.MILLISECOND, tokenLen);
          break;
        case 'E': // day in week (text)
          rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays);
          break;
        case 'D': // day in year (number)
          rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen);
          break;
        case 'F': // day of week in month (number)
          rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen);
          break;
        case 'w': // week in year (number)
          rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen);
          break;
        case 'W': // week in month (number)
          rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen);
          break;
        case 'a': // am/pm marker (text)
          rule = new TextField(Calendar.AM_PM, AmPmStrings);
          break;
        case 'k': // hour in day (1..24)
          rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen));
          break;
        case 'K': // hour in am/pm (0..11)
          rule = selectNumberRule(Calendar.HOUR, tokenLen);
          break;
        case 'z': // time zone (text)
          if (tokenLen >= 4) {
            rule = new TimeZoneNameRule(mTimeZone, mLocale, TimeZone.LONG);
          } else {
            rule = new TimeZoneNameRule(mTimeZone, mLocale, TimeZone.SHORT);
          }
          break;
        case 'Z': // time zone (value)
          if (tokenLen == 1) {
            rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
          } else {
            rule = TimeZoneNumberRule.INSTANCE_COLON;
          }
          break;
        case '\'': // literal text
          String sub = token.substring(1);
          if (sub.length() == 1) {
            rule = new CharacterLiteral(sub.charAt(0));
          } else {
            rule = new StringLiteral(sub);
          }
          break;
        default:
          throw new IllegalArgumentException("Illegal pattern component: " + token);
      }

      rules.add(rule);
    }

    return rules;
  }
Esempio n. 4
0
  static String describeLocale(String name) {
    final StringBuilder result = new StringBuilder();
    result.append("<html>");

    final Locale locale = localeByName(name);

    result.append("<p>");
    append(result, "Display Name", locale.getDisplayName());
    append(result, "Localized Display Name", locale.getDisplayName(locale));

    if (locale.getLanguage().length() > 0) {
      String iso3Language = "(not available)";
      try {
        iso3Language = locale.getISO3Language();
      } catch (MissingResourceException ignored) {
      }

      result.append("<p>");
      append(result, "Display Language", locale.getDisplayLanguage());
      append(result, "Localized Display Language", locale.getDisplayLanguage(locale));
      append(result, "2-Letter Language Code", locale.getLanguage());
      append(result, "3-Letter Language Code", iso3Language);
    }
    if (locale.getCountry().length() > 0) {
      String iso3Country = "(not available)";
      try {
        iso3Country = locale.getISO3Country();
      } catch (MissingResourceException ignored) {
      }

      result.append("<p>");
      append(result, "Display Country", locale.getDisplayCountry());
      append(result, "Localized Display Country", locale.getDisplayCountry(locale));
      append(result, "2-Letter Country Code", locale.getCountry());
      append(result, "3-Letter Country Code", iso3Country);
    }
    if (locale.getVariant().length() > 0) {
      result.append("<p>");
      append(result, "Display Variant", locale.getDisplayVariant());
      append(result, "Localized Display Variant", locale.getDisplayVariant(locale));
      append(result, "Variant Code", locale.getVariant());
    }

    result.append("<p><b>Number Formatting</b>");
    describeNumberFormat(result, "Decimal", NumberFormat.getInstance(locale), 1234.5, -1234.5);
    describeNumberFormat(result, "Integer", NumberFormat.getIntegerInstance(locale), 1234, -1234);
    describeNumberFormat(
        result, "Currency", NumberFormat.getCurrencyInstance(locale), 1234.5, -1234.5);
    describeNumberFormat(result, "Percent", NumberFormat.getPercentInstance(locale), 12.3);

    boolean hasLocaleData = hasLocaleData();

    if (!hasLocaleData) {
      result.append("<p><b>Decimal Format Symbols</b>");
      NumberFormat nf = NumberFormat.getInstance(locale);
      if (nf instanceof DecimalFormat) {
        describeDecimalFormatSymbols(result, ((DecimalFormat) nf).getDecimalFormatSymbols());
      } else {
        result.append("(Didn't expect " + nf.getClass() + ".)");
      }
    }

    Date now =
        new Date(); // FIXME: it might be more useful to always show a time in the afternoon, to
    // make 24-hour patterns more obvious.
    result.append("<p><b>Date/Time Formatting</b>");
    describeDateFormat(
        result, "Full Date", DateFormat.getDateInstance(DateFormat.FULL, locale), now);
    describeDateFormat(
        result, "Long Date", DateFormat.getDateInstance(DateFormat.LONG, locale), now);
    describeDateFormat(
        result, "Medium Date", DateFormat.getDateInstance(DateFormat.MEDIUM, locale), now);
    describeDateFormat(
        result, "Short Date", DateFormat.getDateInstance(DateFormat.SHORT, locale), now);
    result.append("<p>");
    describeDateFormat(
        result, "Full Time", DateFormat.getTimeInstance(DateFormat.FULL, locale), now);
    describeDateFormat(
        result, "Long Time", DateFormat.getTimeInstance(DateFormat.LONG, locale), now);
    describeDateFormat(
        result, "Medium Time", DateFormat.getTimeInstance(DateFormat.MEDIUM, locale), now);
    describeDateFormat(
        result, "Short Time", DateFormat.getTimeInstance(DateFormat.SHORT, locale), now);
    result.append("<p>");
    describeDateFormat(
        result,
        "Full Date/Time",
        DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale),
        now);
    describeDateFormat(
        result,
        "Long Date/Time",
        DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, locale),
        now);
    describeDateFormat(
        result,
        "Medium Date/Time",
        DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale),
        now);
    describeDateFormat(
        result,
        "Short Date/Time",
        DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale),
        now);

    if (!hasLocaleData) {
      result.append("<p><b>Date Format Symbols</b><p>");
      DateFormat edf = DateFormat.getDateInstance(DateFormat.FULL, Locale.US);
      DateFormatSymbols edfs = ((SimpleDateFormat) edf).getDateFormatSymbols();
      DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, locale);
      DateFormatSymbols dfs = ((SimpleDateFormat) df).getDateFormatSymbols();
      append(result, "Local Pattern Chars", dfs.getLocalPatternChars());
      append(result, "Am/pm", Arrays.toString(dfs.getAmPmStrings()));
      append(result, "Eras", Arrays.toString(dfs.getEras()));
      append(result, "Months", Arrays.toString(dfs.getMonths()));
      append(result, "Short Months", Arrays.toString(dfs.getShortMonths()));
      append(result, "Weekdays", Arrays.toString(dfs.getWeekdays()));
      append(result, "Short Weekdays", Arrays.toString(dfs.getShortWeekdays()));
    }

    result.append("<p><b>Calendar</b><p>");
    Calendar c = Calendar.getInstance(locale);
    int firstDayOfWeek = c.getFirstDayOfWeek();
    String firstDayOfWeekString = new DateFormatSymbols(locale).getWeekdays()[firstDayOfWeek];
    String englishFirstDayOfWeekString =
        new DateFormatSymbols(Locale.US).getWeekdays()[firstDayOfWeek];
    String firstDayOfWeekDetails = firstDayOfWeek + " '" + firstDayOfWeekString + "'";
    if (!englishFirstDayOfWeekString.equals(firstDayOfWeekString)) {
      firstDayOfWeekDetails += " (" + englishFirstDayOfWeekString + ")";
    }
    append(result, "First Day of the Week", firstDayOfWeekDetails);
    append(result, "Minimal Days in First Week", c.getMinimalDaysInFirstWeek());

    // If this locale specifies a country, check out the currency.
    // Languages don't have currencies; countries do.
    if (!locale.getCountry().equals("")) {
      result.append("<p><b>Currency</b><p>");
      try {
        Currency currency = Currency.getInstance(locale);
        append(result, "ISO 4217 Currency Code", currency.getCurrencyCode());
        append(
            result,
            "Currency Symbol",
            unicodeString(currency.getSymbol(locale)) + " (" + currency.getSymbol(Locale.US) + ")");
        append(result, "Default Fraction Digits", currency.getDefaultFractionDigits());
      } catch (IllegalArgumentException ex) {
        result.append(
            "<p>(This version of Android is unable to return a Currency for this Locale.)");
      }
    }

    result.append("<p><b>Data Availability</b><p>");
    appendAvailability(result, locale, "BreakIterator", BreakIterator.class);
    appendAvailability(result, locale, "Calendar", NumberFormat.class);
    appendAvailability(result, locale, "Collator", Collator.class);
    appendAvailability(result, locale, "DateFormat", DateFormat.class);
    appendAvailability(result, locale, "DateFormatSymbols", DateFormatSymbols.class);
    appendAvailability(result, locale, "DecimalFormatSymbols", DecimalFormatSymbols.class);
    appendAvailability(result, locale, "NumberFormat", NumberFormat.class);

    if (hasLocaleData) {
      result.append("<p><b>libcore.icu.LocaleData</b>");
      try {
        Object enUsData = getLocaleDataInstance(Locale.US);
        Object localeData = getLocaleDataInstance(locale);
        String[] previous;

        result.append("<p>");
        describeStringArray(result, "amPm", enUsData, localeData, null);
        describeStringArray(result, "eras", enUsData, localeData, null);

        result.append("<p>");
        previous = describeStringArray(result, "longMonthNames", enUsData, localeData, null);
        describeStringArray(result, "longStandAloneMonthNames", enUsData, localeData, previous);
        previous = describeStringArray(result, "shortMonthNames", enUsData, localeData, null);
        describeStringArray(result, "shortStandAloneMonthNames", enUsData, localeData, previous);
        previous = describeStringArray(result, "tinyMonthNames", enUsData, localeData, null);
        describeStringArray(result, "tinyStandAloneMonthNames", enUsData, localeData, previous);

        result.append("<p>");
        previous = describeStringArray(result, "longWeekdayNames", enUsData, localeData, null);
        describeStringArray(result, "longStandAloneWeekdayNames", enUsData, localeData, previous);
        previous = describeStringArray(result, "shortWeekdayNames", enUsData, localeData, null);
        describeStringArray(result, "shortStandAloneWeekdayNames", enUsData, localeData, previous);
        previous = describeStringArray(result, "tinyWeekdayNames", enUsData, localeData, null);
        describeStringArray(result, "tinyStandAloneWeekdayNames", enUsData, localeData, previous);

        result.append("<p>");
        describeString(result, "yesterday", enUsData, localeData);
        describeString(result, "today", enUsData, localeData);
        describeString(result, "tomorrow", enUsData, localeData);

        result.append("<p>");
        describeString(result, "timeFormat12", enUsData, localeData);
        describeString(result, "timeFormat24", enUsData, localeData);

        result.append("<p>");
        describeChar(result, "zeroDigit", enUsData, localeData);
        describeChar(result, "decimalSeparator", enUsData, localeData);
        describeChar(result, "groupingSeparator", enUsData, localeData);
        describeChar(result, "patternSeparator", enUsData, localeData);
        describeChar(result, "percent", enUsData, localeData);
        describeChar(result, "perMill", enUsData, localeData);
        describeChar(result, "monetarySeparator", enUsData, localeData);
        describeChar(result, "minusSign", enUsData, localeData);
        describeString(result, "exponentSeparator", enUsData, localeData);
        describeString(result, "infinity", enUsData, localeData);
        describeString(result, "NaN", enUsData, localeData);

      } catch (Exception ex) {
        result.append("(" + ex.getClass().getSimpleName() + " thrown: " + ex.getMessage() + ")");
        System.err.println(ex);
      }
    }

    return result.toString();
  }