function _subparse()

in trinidad-impl/src/main/javascript/META-INF/adf/jsLibs/DateFormat.js [509:875]


function _subparse(
  inString,      // the pattern string, such as "yyMMdd"
  localeSymbols,
  locale,
  formatType,    // the current format char, such as 'y'
  startIndex,    // index into inString
  charCount,     // the number of chars of type formatType
  parseContext,  // information pertaining to the user input string
  parsedTime
  )
{
  // Start index of the string being parsed (as opposed
  // to startIndex, which is the index on the format mask)
  var inStartIndex = parseContext.currIndex;
    
  var nextFormatType = (startIndex + charCount < inString.length) ? 
    inString.charAt(startIndex + charCount) : null;
    
  // Consider the pattern "yyMMdd". Say that formatType is 'y' and nextFormatType is 'M'. Normally 
  // we would allow for leniency such that the user could input 2 or 4 digits for the year, but 
  // since this pattern contains no date separators and both the year and month can consist of 
  // digits, there's no easy way of telling whether the first 4 digits apply to just the year, or 
  // to both the year and month. Therefore, if nextFormatType is one of the reserved format types, 
  // then we go into strict parsing mode for formatType, where charCount represents the maximum 
  // number of user input characters that will be parsed when matching the current formatType.
  var isStrict = ("DFMSWdhkHKmswy".indexOf(nextFormatType) != -1);

  if ((formatType >= 'A') && (formatType <= 'Z') ||
      (formatType >= 'a') && (formatType <= 'z'))
  {
    switch (formatType)
    {
      case 'D': // day in year
        var dayOfYear = _accumulateNumber(parseContext, !isStrict ? 3 : charCount);
        if (dayOfYear == null)
          return false;
        else
          parseContext.parsedDayOfYear = dayOfYear;
        break;
      
      case 'E': // day in week
      {
        // extract the day but do nothing with it, as there is not setDay()
        // on Date
        var dayIndex = _matchArray(parseContext,
                                   (charCount <= 3)
                                     ? localeSymbols.getShortWeekdays()
                                     : localeSymbols.getWeekdays());
                                     
        if (dayIndex == null)
        {
          return false;
        }
      }
      break;
      
      case 'F': // day of week in month
        // skip this number
        if (_accumulateNumber(parseContext, !isStrict ? 2 : charCount) == null)
        {
          return false;
        }
        break;
      
      case 'G': // era designator
      {
        var eraIndex = _matchArray(parseContext, localeSymbols.getEras());
        
        if (eraIndex != null)
        {
          if (eraIndex == 0)
          {
            parseContext.parsedBC = true;
          }
        }
        else
        {
          return false;
        }
      }
      break;
                  
      case 'M': // month in year
      {
        var monthIndex;
        var monthOffset = 0;

        if (charCount <= 2)
        {
          // match month number
          monthIndex = _accumulateNumber(parseContext, !isStrict ? 2 : charCount);
          
          // subtract 1 from the monthIndex to make it 0-based
          monthOffset = -1;
        }
        else
        {
          var nameArray = (charCount == 3)
                            ? localeSymbols.getShortMonths()
                            : localeSymbols.getMonths();

          monthIndex = _matchArray(parseContext, nameArray);
        }

        if (monthIndex != null)
        {
          parseContext.parsedMonth = (monthIndex + monthOffset);
        }
        else
        {
          return false;
        }
      }
      break;

      case 'S': // millisecond (0 - 999)
      {
        var milliseconds = _accumulateNumber(parseContext, !isStrict ? 3 : charCount);

        if (milliseconds != null)
        {
          parseContext.parsedMilliseconds = milliseconds;
        }
        else
        {
          return false;
        }
      }
      break;
      
      case 'W': // week in month
        // skip this number
        if (_accumulateNumber(parseContext, !isStrict ? 2 : charCount) == null)
        {
          return false;
        }
        break;
      
      case 'a': // am/pm marker
      {
        var amPMIndex = _matchArray(parseContext,
                                    localeSymbols.getAmPmStrings());
        
        if (amPMIndex == null)
        {
          return false;
        }
        else
        {
          if (amPMIndex == 1)
          {
            parseContext.isPM = true;
          }
        }
      }
      break;
      
      case 'd': // day in month
      {
        var dayOfMonth = _accumulateNumber(parseContext, !isStrict ? 2 : charCount);
                
        if (dayOfMonth != null)
        {
          parseContext.parsedDate = dayOfMonth;
        }
        else
        {
          return false;
        }
      }
      break;
        
      case 'h': // hour in am/pm (1-12)
      case 'k': // hour in day (1-24)
      case 'H': // hour in day (0-23)
      case 'K': // hour in am/pm (0-11)
      {
        var hour = _accumulateNumber(parseContext, !isStrict ? 2 : charCount);
        
        if (hour != null)
        {
          if ((formatType == 'h') && (hour == 12))
            hour = 0;
          if ((formatType == 'k') && (hour == 24))
            hour = 0;

          parseContext.parsedHour = hour;
        }
        else
        {
          return false;
        }
      }
      break;


      case 'm': // minute in hour 0 - 59)
      {
        var minutes = _accumulateNumber(parseContext, !isStrict ? 2 : charCount);
        
        if (minutes != null)
        {
          parseContext.parsedMinutes = minutes;
        }
        else
        {
          return false;
        }
      }
      break;
      
      case 's': // seconds in minute 0 - 59)
      {
        var seconds = _accumulateNumber(parseContext, !isStrict ? 2 : charCount);

        if (seconds != null)
        {
          parseContext.parsedSeconds = seconds;
        }
        else
        {
          return false;
        }
      }
      break;

      case 'w': // week in year
        // skip this number
        if (_accumulateNumber(parseContext, !isStrict ? 2 : charCount) == null)
        {
          return false;
        }
        break;

      case 'y': // year
      {
        // Trinidad-2386: Javascript accepts up to 6 digit year lengths, use maxLength = 6
        var year = _accumulateNumber(parseContext, !isStrict ? 6 : charCount);
        var enteredChars = parseContext.currIndex - inStartIndex;
        // if we have a 2-digit year, add in the default year
        if (year != null)
        {
          if ((enteredChars > 2) &&
              (charCount <= 2) &&
              (year <= 999))
          {
            // Block bonus characters;  if they've specified
            // a two-year mask, and there's more than two characters,
            // there might be a problem.  But allow four digits.
            return false;
          }
          else if ((charCount <= 2) && (year >= 0) && (year <= 100))
          {
            year = _fix2DYear(year, locale);
          }
          else if (charCount == 4)
          {
            if (enteredChars <= 2)
              year = _fix2DYear(year);
          }

          // There is no year "0"
          if (year == 0)
            return false;
            
          // Trinidad-2013: Thai Buddhist Calendar is offset by 543 years
          if (locale == "th_TH")
            year -= _THAI_BUDDHIST_YEAR_OFFSET;
            
          parseContext.parsedFullYear = year;
        }
        else
        {
          return false;
        }
      }
      break;
        
      case 'z': // GMT timezone - "GMT Sign Hours : Minutes"
      {
        // consume the GMT portion
        if (!_matchText(parseContext, "GMT"))
        {
          // GMT is must for timeZone entry.
          return false;
        }
        
        // if we have any more chars then parse the remaining "+HH:mm" string.
        if( (parseContext.parseString.length - parseContext.currIndex) > 0)
        {
          // consume the plus or minus
          if(_matchArray(parseContext, ["-", "+"]) == null)
          {
            return false;
          }
          
          // accumulate the hour offset number
          var hourOffset = _accumulateNumber(parseContext, 2);
          if(hourOffset == null)
          {
            return false;
          }
          parseContext.hourOffset = hourOffset;
          
          // consume the separator between HH and mm
          if (!_matchText(parseContext, ":"))
          {
            return false;
          }
          
          // accumulate minute offset number (should have 2 digits)
          var minOffset;
          if(((parseContext.parseString.length - parseContext.currIndex) < 2) ||
             (minOffset = _accumulateNumber(parseContext, 2)) == null)
          {
            return false;
          }
          parseContext.minOffset = minOffset;
        }
      }
      break;
      
      case 'Z': // RFC 822 timezone - "Sign TwoDigitHours Minutes"
      {
        // RFC 822 TimeZone format should have 5 chars (+/-HHmm)
        if ((parseContext.parseString.length - parseContext.currIndex) < 5)
        {
          return false;
        }
        
        // consume the plus or minus
        if(_matchArray(parseContext, ["-", "+"]) == null)
        {
          return false;
        }
          
        // accumulate the hour offset number
        var hourOffset = _accumulateNumber(parseContext, 2)
        if(hourOffset == null)
        {
          return false;
        }
        parseContext.hourOffset = hourOffset;
        
        // accumulate the minute offset number
        var minOffset = _accumulateNumber(parseContext, 2)
        if(minOffset == null)
        {
          return false;
        }
        parseContext.minOffset = null;
      }
      break;
    
      default:
    }
  }
  else
  {
    // consume constants
    return _matchText(parseContext,
                      inString.substring(startIndex, startIndex + charCount));
  }
  
  // match succeeded
  return true;
}