Example #1
0
 public boolean readDigitAndAdvance(RefInt i, int scale, int maxdigit) {
   if (!isValid()) return false;
   char c = source.charAt(index);
   if (c < '0' || c > '9') return false;
   int val = (int) c - (int) '0';
   if (val > maxdigit) return false;
   i.value += (val * scale);
   advance();
   return true;
 }
Example #2
0
  public boolean parseDateTime(String s, int part) {
    ParseContext context = new ParseContext(s);

    boolean bDatePart = (part & DateTimePart_Date) != 0;
    boolean bTimePart = (part & DateTimePart_Time) != 0;

    RefInt year = new RefInt(0);
    RefInt month = new RefInt(0);
    RefInt day = new RefInt(0);
    RefInt hour = new RefInt(0);
    RefInt minute = new RefInt(0);
    double second = 0;

    hasTZ = TZ_MISSING;
    offsetTZ = 0;

    if (bDatePart) {
      // parse date
      boolean bNegative = context.checkAndAdvance('-');

      if ((part & DateTimePart_Year) != 0) {
        int digits = 0;
        RefInt temp = new RefInt(0);
        ;
        while (context.readDigitAndAdvance(temp, 1, 9)) {
          year.value = year.value * 10 + temp.value;
          digits += 1;
          temp.value = 0;
          if (digits >= 8) // overflow
          return false;
        }
        if (digits < 4) // inalid
        return false;
        if (digits > 4 && year.value < 10000) return false;
        if (bNegative) year.value = -year.value;
      }

      if ((part & (DateTimePart_Month | DateTimePart_Day)) != 0) {
        if (!context.checkAndAdvance('-')) return false;

        if ((part & DateTimePart_Month) != 0) {
          if (!context.readDigitAndAdvance(month, 10, 1)) return false;
          if (!context.readDigitAndAdvance(month, 1, month.value < 10 ? 9 : 2)) return false;
          if (month.value == 0) return false;
        }

        if ((part & DateTimePart_Day) != 0) {
          if (!context.checkAndAdvance('-')) return false;

          int maxFirstDigit = month.value != 2 ? 3 : 2;

          // complicate things by making them complicated.
          if (!context.readDigitAndAdvance(day, 10, maxFirstDigit)) return false;
          if (!context.readDigitAndAdvance(day, 1, 9)) return false;
          if (day.value == 0 || day.value > 31) return false;

          if ((part & DateTimePart_Month) != 0) {
            boolean b1 = month.value <= 7;
            boolean b2 = (month.value & 1) == 0;

            // month 1, 3, 5, 7, 8, 10, 12
            if (b1 == b2 && day.value > 30) return false;

            // february.
            if (month.value == 2 && day.value > 29) return false;

            // leap years.
            if (month.value == 2
                && (part & DateTimePart_Year) != 0
                && (year.value % 4 != 0 || year.value % 100 == 0)
                && year.value % 400 != 0
                && day.value > 28) return false;
          }
        }
      }

      if (bTimePart) {
        // a 'T' must follow
        if (!context.checkAndAdvance('T')) return false;
      }
    }

    if (bTimePart) {
      // check format here

      // hour from 0 to 2
      if (!context.readDigitAndAdvance(hour, 10, 2)) return false;
      if (!context.readDigitAndAdvance(hour, 1, hour.value < 20 ? 9 : 4)) return false;
      if (!context.checkAndAdvance(':')) return false;
      int maxFirstDigit = hour.value == 24 ? 0 : 5;
      int maxSecondDigit = hour.value == 24 ? 0 : 9;
      if (!context.readDigitAndAdvance(minute, 10, maxFirstDigit)) return false;
      if (!context.readDigitAndAdvance(minute, 1, maxSecondDigit)) return false;
      if (!context.checkAndAdvance(':')) return false;
      RefInt secondInt = new RefInt(0);
      if (!context.readDigitAndAdvance(secondInt, 10, maxFirstDigit)) return false;
      if (!context.readDigitAndAdvance(secondInt, 1, maxSecondDigit)) return false;

      second = secondInt.value;

      if (context.checkAndAdvance('.')) {
        // fraction. do whatever seems fit.
        RefInt val = new RefInt(0);
        int digits = 0;
        while (context.readDigitAndAdvance(val, 1, 9)) {
          val.value *= 10;
          digits += 1;
          if (digits >= 8) // precision loss - ignore
          break;
        }

        if (digits == 0) return false;

        second += val.value * Math.pow(10.0, -digits - 1);

        // skip any further digits.
        while (context.readDigitAndAdvance(val, 0, 9)) ;
      }
    }

    //	 timezone
    if (context.checkAndAdvance('Z')) {
      // timezone specified, it is UTC.
      hasTZ = TZ_UTC;
      offsetTZ = 0;
    } else if (context.check('+') || context.check('-')) {
      // timezone offset, in hour:minute format
      boolean bNegative = context.check('-');
      context.advance();

      // do not check the hour part, for those who are obscure.
      RefInt temp = new RefInt(0);
      if (!context.readDigitAndAdvance(temp, 600, 9)) return false;
      if (!context.readDigitAndAdvance(temp, 60, 9)) return false;
      if (!context.checkAndAdvance(':')) return false;
      if (!context.readDigitAndAdvance(temp, 10, 5)) return false;
      if (!context.readDigitAndAdvance(temp, 1, 9)) return false;

      hasTZ = TZ_OFFSET;
      offsetTZ = bNegative ? -temp.value : temp.value;
    }

    if (context.isValid()) return false;

    if (year.value <= 0) year.value = 1;
    if (month.value == 0) month.value = 1;
    if (day.value == 0) day.value = 1;
    // if hour is 24 add a day.
    if (hour.value == 24) {
      hour.value = 0;
      Calendar c = Calendar.getInstance();
      c.set(year.value, month.value - 1, day.value);
      c.add(Calendar.DATE, 1);
      year.value = c.get(Calendar.YEAR);
      month.value = c.get(Calendar.MONTH) + 1;
      day.value = c.get(Calendar.DAY_OF_MONTH);
    }

    setInternalValues(
        year.value,
        month.value,
        day.value,
        hour.value,
        minute.value,
        (int) second,
        ((second * 1000) % 1000) / 1000,
        hasTZ,
        offsetTZ);

    return true;
  }