private static synchronized void initCache() {
      if (CACHE.size() <= 0) {
        for (FormatTokenEnum token : FormatTokenEnum.values()) {

          List<Character> tokenKeys = new ArrayList<Character>();

          if (token.name().contains("_")) {
            String[] tokens = token.name().split("_");
            for (String tokenLets : tokens) {
              tokenKeys.add(tokenLets.toUpperCase().charAt(0));
            }
          } else {
            tokenKeys.add(token.name().toUpperCase().charAt(0));
          }

          for (Character tokenKey : tokenKeys) {
            List<FormatTokenEnum> l = CACHE.get(tokenKey);
            if (l == null) {
              l = new ArrayList<FormatTokenEnum>(1);
              CACHE.put(tokenKey, l);
            }
            l.add(token);
          }
        }
      }
    }
  /** The format tokens. */
  static enum FormatTokenEnum {
    // 4-digit year
    YYYY(PARSLET_YEAR),
    // 4-digit year with sign (- = B.C.)
    SYYYY(PARSLET_YEAR),
    // 4-digit year based on the ISO standard (?)
    IYYY(PARSLET_YEAR),
    YYY(PARSLET_YEAR),
    IYY(PARSLET_YEAR),
    YY(PARSLET_YEAR),
    IY(PARSLET_YEAR),
    // Two-digit century with with sign (- = B.C.)
    SCC(PARSLET_YEAR),
    // Two-digit century.
    CC(PARSLET_YEAR),
    // 2-digit -> 4-digit year 0-49 -> 20xx , 50-99 -> 19xx
    RRRR(PARSLET_YEAR),
    // last 2-digit of the year using "current" century value.
    RR(PARSLET_YEAR),
    // Meridian indicator
    BC_AD(PARSLET_YEAR, PATTERN_BC_AD),
    // Full Name of month
    MONTH(PARSLET_MONTH),
    // Abbreviated name of month.
    MON(PARSLET_MONTH),
    // Month (01-12; JAN = 01).
    MM(PARSLET_MONTH),
    // Roman numeral month (I-XII; JAN = I).
    RM(PARSLET_MONTH),
    // Day of year (1-366).
    DDD(PARSLET_DAY),
    // Name of day.
    DAY(PARSLET_DAY),
    // Day of month (1-31).
    DD(PARSLET_DAY),
    // Abbreviated name of day.
    DY(PARSLET_DAY),
    HH24(PARSLET_TIME),
    HH12(PARSLET_TIME),
    // Hour of day (1-12).
    HH(PARSLET_TIME),
    // Min
    MI(PARSLET_TIME),
    // Seconds past midnight (0-86399)
    SSSSS(PARSLET_TIME),
    SS(PARSLET_TIME),
    // Fractional seconds
    FF(PARSLET_TIME, PATTERN_FF),
    // Time zone hour.
    TZH(PARSLET_TIME),
    // Time zone minute.
    TZM(PARSLET_TIME),
    // Time zone region ID
    TZR(PARSLET_TIME),
    // Daylight savings information. Example:
    // PST (for US/Pacific standard time);
    TZD(PARSLET_TIME),
    // Meridian indicator
    AM_PM(PARSLET_TIME, PATTERN_AM_PM),
    // NOT supported yet -
    // Full era name (Japanese Imperial, ROC Official,
    // and Thai Buddha calendars).
    EE(PARSLET_YEAR),
    // NOT supported yet -
    // Abbreviated era name (Japanese Imperial,
    // ROC Official, and Thai Buddha calendars).
    E(PARSLET_YEAR),
    Y(PARSLET_YEAR),
    I(PARSLET_YEAR),
    // Quarter of year (1, 2, 3, 4; JAN-MAR = 1).
    Q(PARSLET_MONTH),
    // Day of week (1-7).
    D(PARSLET_DAY),
    // NOT supported yet -
    // Julian day; the number of days since Jan 1, 4712 BC.
    J(PARSLET_DAY);

    private static final List<FormatTokenEnum> EMPTY_LIST = new ArrayList<FormatTokenEnum>(0);

    private static final Map<Character, List<FormatTokenEnum>> CACHE =
        new HashMap<Character, List<FormatTokenEnum>>(FormatTokenEnum.values().length);
    private final ToDateParslet toDateParslet;
    private final Pattern patternToUse;

    FormatTokenEnum(ToDateParslet toDateParslet, Pattern patternToUse) {
      this.toDateParslet = toDateParslet;
      this.patternToUse = patternToUse;
    }

    FormatTokenEnum(ToDateParslet toDateParslet) {
      this.toDateParslet = toDateParslet;
      patternToUse = Pattern.compile(format("^(%s)", name()), Pattern.CASE_INSENSITIVE);
    }

    /**
     * Optimization: Only return a list of {@link FormatTokenEnum} that share the same 1st char
     * using the 1st char of the 'to parse' formatStr. Or return empty list if no match.
     */
    static List<FormatTokenEnum> getTokensInQuestion(String formatStr) {
      List<FormatTokenEnum> result = EMPTY_LIST;
      if (CACHE.size() <= 0) {
        initCache();
      }
      if (formatStr != null && formatStr.length() > 0) {
        Character key = Character.toUpperCase(formatStr.charAt(0));
        result = CACHE.get(key);
      }
      if (result == null) {
        result = EMPTY_LIST;
      }
      return result;
    }

    private static synchronized void initCache() {
      if (CACHE.size() <= 0) {
        for (FormatTokenEnum token : FormatTokenEnum.values()) {

          List<Character> tokenKeys = new ArrayList<Character>();

          if (token.name().contains("_")) {
            String[] tokens = token.name().split("_");
            for (String tokenLets : tokens) {
              tokenKeys.add(tokenLets.toUpperCase().charAt(0));
            }
          } else {
            tokenKeys.add(token.name().toUpperCase().charAt(0));
          }

          for (Character tokenKey : tokenKeys) {
            List<FormatTokenEnum> l = CACHE.get(tokenKey);
            if (l == null) {
              l = new ArrayList<FormatTokenEnum>(1);
              CACHE.put(tokenKey, l);
            }
            l.add(token);
          }
        }
      }
    }

    /**
     * Parse the format-string with passed token of {@link FormatTokenEnum}. If token matches return
     * true, otherwise false.
     */
    boolean parseFormatStrWithToken(ToDateParser params) {
      Matcher matcher = patternToUse.matcher(params.getFormatStr());
      boolean foundToken = matcher.find();
      if (foundToken) {
        String formatTokenStr = matcher.group(1);
        toDateParslet.parse(params, this, formatTokenStr);
      }
      return foundToken;
    }
  }