* @param strict true to be strict when parsing, false to be lenient
*
* @return 0 if parsing failed, otherwise the number of characters advanced
*/
private int parse(String text, int start, Date date, boolean strict) {
DateRecord cal = new DateRecord();
int[] parsePos = {start};
// For parsing abutting numeric fields. 'abutPat' is the
// offset into 'pattern' of the first of 2 or more abutting
// numeric fields. 'abutStart' is the offset into 'text'
// where parsing the fields begins. 'abutPass' starts off as 0
// and increments each time we try to parse the fields.
int abutPat = -1; // If >=0, we are in a run of abutting numeric fields.
int abutStart = 0;
int abutPass = 0;
for (int i = 0; i < patternParts.size(); ++i) {
PatternPart part = patternParts.get(i);
if (part.count > 0) {
if (abutPat < 0 && part.abutStart) {
abutPat = i;
abutStart = start;
abutPass = 0;
}
// Handle fields within a run of abutting numeric fields. Take
// the pattern "HHmmss" as an example. We will try to parse
// 2/2/2 characters of the input text, then if that fails,
// 1/2/2. We only adjust the width of the leftmost field; the
// others remain fixed. This allows "123456" => 12:34:56, but
// "12345" => 1:23:45. Likewise, for the pattern "yyyyMMdd" we
// try 4/2/2, 3/2/2, 2/2/2, and finally 1/2/2.
if (abutPat >= 0) {
// If we are at the start of a run of abutting fields, then
// shorten this field in each pass. If we can't shorten
// this field any more, then the parse of this set of
// abutting numeric fields has failed.
int count = part.count;
if (i == abutPat) {
count -= abutPass++;
if (count == 0) {
return 0;
}
}
if (!subParse(text, parsePos, part, count, cal)) {
// If the parse fails anywhere in the run, back up to the
// start of the run and retry.
i = abutPat - 1;
parsePos[0] = abutStart;
continue;
}
} else {
// Handle non-numeric fields and non-abutting numeric fields.
abutPat = -1;
if (!subParse(text, parsePos, part, 0, cal)) {
return 0;
}
}
} else {
// Handle literal pattern characters. These are any
// quoted characters and non-alphabetic unquoted characters.
abutPat = -1;
// A run of white space in the pattern matches a run
// of white space in the input text.
if (part.text.charAt(0) == ' ') {
// Advance over run in input text.
int s = parsePos[0];
skipSpace(text, parsePos);
// Must see at least one white space char in input.
if (parsePos[0] > s) {
continue;
}
} else if (text.startsWith(part.text, parsePos[0])) {
parsePos[0] += part.text.length();
continue;
}
// We fall through to this point if the match fails.
return 0;
}
}
// Calculate the date from the parts
if (!cal.calcDate(date, strict)) {
return 0;
}
// Return progress.
return parsePos[0] - start;