Пример #1
0
    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);
          }
        }
      }
    }
Пример #2
0
 @Override
 public void parse(ToDateParser params, FormatTokenEnum formatTokenEnum, String formatTokenStr) {
   Calendar result = params.getResultCalendar();
   String s = params.getInputStr();
   String inputFragmentStr = null;
   int dateNr = 0;
   switch (formatTokenEnum) {
     case MONTH:
       inputFragmentStr = setByName(result, params, Calendar.MONTH, Calendar.LONG);
       break;
     case Q /*NOT supported yet*/:
       throwException(params, format("token '%s' not supported yet.", formatTokenEnum.name()));
       break;
     case MON:
       inputFragmentStr = setByName(result, params, Calendar.MONTH, Calendar.SHORT);
       break;
     case MM:
       // Note: In Calendar Month go from 0 - 11
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.MONTH, dateNr - 1);
       break;
     case RM:
       dateNr = 0;
       for (String monthName : ROMAN_MONTH) {
         dateNr++;
         int len = monthName.length();
         if (s.length() >= len && monthName.equalsIgnoreCase(s.substring(0, len))) {
           result.set(Calendar.MONTH, dateNr);
           inputFragmentStr = monthName;
           break;
         }
       }
       if (inputFragmentStr == null || inputFragmentStr.isEmpty()) {
         throwException(
             params,
             format(
                 "Issue happened when parsing token '%s'. " + "Expected one of: %s",
                 formatTokenEnum.name(), Arrays.toString(ROMAN_MONTH)));
       }
       break;
     default:
       throw new IllegalArgumentException(
           format(
               "%s: Internal Error. Unhandled case: %s",
               this.getClass().getSimpleName(), formatTokenEnum));
   }
   params.remove(inputFragmentStr, formatTokenStr);
 }
Пример #3
0
 @Override
 public void parse(ToDateParser params, FormatTokenEnum formatTokenEnum, String formatTokenStr) {
   Calendar result = params.getResultCalendar();
   String inputFragmentStr = null;
   int dateNr = 0;
   switch (formatTokenEnum) {
     case SYYYY:
     case YYYY:
     case IYYY:
       inputFragmentStr = matchStringOrThrow(PATTERN_FOUR_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       // Gregorian calendar does not have a year 0.
       // 0 = 0001 BC, -1 = 0002 BC, ... so we adjust
       result.set(Calendar.YEAR, dateNr >= 0 ? dateNr : dateNr + 1);
       break;
     case YYY:
     case IYY:
       inputFragmentStr = matchStringOrThrow(PATTERN_THREE_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       // Gregorian calendar does not have a year 0.
       // 0 = 0001 BC, -1 = 0002 BC, ... so we adjust
       result.set(Calendar.YEAR, dateNr >= 0 ? dateNr : dateNr + 1);
       break;
     case RRRR:
       inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       dateNr += dateNr < 50 ? 2000 : 1900;
       result.set(Calendar.YEAR, dateNr);
       break;
     case RR:
       Calendar calendar = Calendar.getInstance();
       int cc = calendar.get(Calendar.YEAR) / 100;
       inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr) + cc * 100;
       result.set(Calendar.YEAR, dateNr);
       break;
     case EE /*NOT supported yet*/:
       throwException(params, format("token '%s' not supported yet.", formatTokenEnum.name()));
       break;
     case E /*NOT supported yet*/:
       throwException(params, format("token '%s' not supported yet.", formatTokenEnum.name()));
       break;
     case YY:
     case IY:
       inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       // Gregorian calendar does not have a year 0.
       // 0 = 0001 BC, -1 = 0002 BC, ... so we adjust
       result.set(Calendar.YEAR, dateNr >= 0 ? dateNr : dateNr + 1);
       break;
     case SCC:
     case CC:
       inputFragmentStr = matchStringOrThrow(PATTERN_TWO_DIGITS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr) * 100;
       result.set(Calendar.YEAR, dateNr);
       break;
     case Y:
     case I:
       inputFragmentStr = matchStringOrThrow(PATTERN_ONE_DIGIT, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       // Gregorian calendar does not have a year 0.
       // 0 = 0001 BC, -1 = 0002 BC, ... so we adjust
       result.set(Calendar.YEAR, dateNr >= 0 ? dateNr : dateNr + 1);
       break;
     case BC_AD:
       inputFragmentStr = matchStringOrThrow(PATTERN_BC_AD, params, formatTokenEnum);
       if (inputFragmentStr.toUpperCase().startsWith("B")) {
         result.set(Calendar.ERA, GregorianCalendar.BC);
       } else {
         result.set(Calendar.ERA, GregorianCalendar.AD);
       }
       break;
     default:
       throw new IllegalArgumentException(
           format(
               "%s: Internal Error. Unhandled case: %s",
               this.getClass().getSimpleName(), formatTokenEnum));
   }
   params.remove(inputFragmentStr, formatTokenStr);
 }
Пример #4
0
  /** 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;
    }
  }
Пример #5
0
 @Override
 public void parse(ToDateParser params, FormatTokenEnum formatTokenEnum, String formatTokenStr) {
   Calendar result = params.getResultCalendar();
   String inputFragmentStr = null;
   int dateNr = 0;
   switch (formatTokenEnum) {
     case HH24:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.HOUR_OF_DAY, dateNr);
       break;
     case HH12:
     case HH:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.HOUR, dateNr);
       break;
     case MI:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.MINUTE, dateNr);
       break;
     case SS:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.SECOND, dateNr);
       break;
     case SSSSS:
       inputFragmentStr = matchStringOrThrow(PATTERN_NUMBER, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       result.set(Calendar.HOUR_OF_DAY, 0);
       result.set(Calendar.MINUTE, 0);
       result.set(Calendar.SECOND, dateNr);
       break;
     case FF:
       inputFragmentStr = matchStringOrThrow(PATTERN_NUMBER, params, formatTokenEnum);
       String paddedRightNrStr = format("%-9s", inputFragmentStr).replace(' ', '0');
       paddedRightNrStr = paddedRightNrStr.substring(0, 9);
       Double nineDigits = Double.parseDouble(paddedRightNrStr);
       params.setNanos(nineDigits.intValue());
       dateNr = (int) Math.round(nineDigits / 1000000.0);
       result.set(Calendar.MILLISECOND, dateNr);
       break;
     case AM_PM:
       inputFragmentStr = matchStringOrThrow(PATTERN_AM_PM, params, formatTokenEnum);
       if (inputFragmentStr.toUpperCase().startsWith("A")) {
         result.set(Calendar.AM_PM, Calendar.AM);
       } else {
         result.set(Calendar.AM_PM, Calendar.PM);
       }
       break;
     case TZH:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       TimeZone tz = result.getTimeZone();
       int offsetMillis = tz.getRawOffset();
       // purge min and sec
       offsetMillis = (offsetMillis / MILLIS_IN_HOUR) * MILLIS_IN_HOUR;
       tz.setRawOffset(offsetMillis + dateNr);
       result.setTimeZone(tz);
       break;
     case TZM:
       inputFragmentStr =
           matchStringOrThrow(PATTERN_TWO_DIGITS_OR_LESS, params, formatTokenEnum);
       dateNr = parseInt(inputFragmentStr);
       tz = result.getTimeZone();
       offsetMillis = tz.getRawOffset();
       // purge hour
       offsetMillis = offsetMillis % MILLIS_IN_HOUR;
       tz.setRawOffset(dateNr * MILLIS_IN_HOUR + offsetMillis);
       result.setTimeZone(tz);
       break;
     case TZR:
       // Example: US/Pacific
       String s = params.getInputStr();
       tz = result.getTimeZone();
       for (String tzName : TimeZone.getAvailableIDs()) {
         int length = tzName.length();
         if (s.length() >= length && tzName.equalsIgnoreCase(s.substring(0, length))) {
           tz.setID(tzName);
           result.setTimeZone(tz);
           inputFragmentStr = tzName;
           break;
         }
       }
       break;
     case TZD:
       // Must correspond with TZR region. Example: PST (for US/Pacific
       // standard time)
       throwException(params, format("token '%s' not supported yet.", formatTokenEnum.name()));
       break;
     default:
       throw new IllegalArgumentException(
           format(
               "%s: Internal Error. Unhandled case: %s",
               this.getClass().getSimpleName(), formatTokenEnum));
   }
   params.remove(inputFragmentStr, formatTokenStr);
 }