下面列出了java.text.ParsePosition#setIndex ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* 得到两个时间差
* @param startTime
* @param toTime
* @return
*/
public static long dateDiffToMinuteD(String startTime, String toTime){
long diff = 0l;
if(StringUtils.checkEmpty(startTime) != null && StringUtils.checkEmpty(toTime) != null){
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm");
ParsePosition pos = new ParsePosition(0);
Date startTimeD = format.parse(startTime, pos);
pos.setIndex(0);
Date toTimeD = format.parse(toTime, pos);
diff = (startTimeD.getTime() - toTimeD.getTime())/ ONE_THOUSAND/SIXTY;
}
return diff;
}
private int processSet(String regex, int i, StringBuilder result, UnicodeSet temp, ParsePosition pos) {
try {
pos.setIndex(i);
UnicodeSet x = temp.clear().applyPattern(regex, pos, symbolTable, 0);
x.complement().complement(); // hack to fix toPattern
result.append(x.toPattern(false));
i = pos.getIndex() - 1; // allow for the loop increment
return i;
} catch (Exception e) {
throw (IllegalArgumentException) new IllegalArgumentException("Error in " + regex).initCause(e);
}
}
private int nextToken(CharSequence csq, ParsePosition pos) {
final int length = csq.length();
while (pos.getIndex() < length) {
char c = csq.charAt(pos.getIndex());
if (isUnitIdentifierPart(c)) {
return IDENTIFIER;
} else if (c == '(') {
return OPEN_PAREN;
} else if (c == ')') {
return CLOSE_PAREN;
} else if ((c == '^') || (c == '¹') || (c == '²') || (c == '³')) {
return EXPONENT;
} else if (c == '*') {
char c2 = csq.charAt(pos.getIndex() + 1);
if (c2 == '*') {
return EXPONENT;
} else {
return MULTIPLY;
}
} else if (c == '·') {
return MULTIPLY;
} else if (c == '/') {
return DIVIDE;
} else if (c == '+') {
return PLUS;
} else if ((c == '-') || Character.isDigit(c)) {
int index = pos.getIndex()+1;
while ((index < length) &&
(Character.isDigit(c) || (c == '-') || (c == '.') || (c == 'E'))) {
c = csq.charAt(index++);
if (c == '.') {
return FLOAT;
}
}
return INTEGER;
}
pos.setIndex(pos.getIndex() + 1);
}
return EOF;
}
public static void main(String[] args) {
String date = "13 Jan 2005 21:45:34 ABC";
String format = "dd MMM yyyy HH:mm:ss z";
ParsePosition pp = new ParsePosition(0);
pp.setIndex(0);
SimpleDateFormat sd = new SimpleDateFormat(format, Locale.ENGLISH);
Date d = sd.parse(date, pp);
int errorIndex = pp.getErrorIndex();
if (errorIndex == 21) {
System.out.println(": passed");
} else {
System.out.println(": failed");
throw new RuntimeException("Failed with wrong index: " + errorIndex);
}
}
/**
* Consume a quoted string, adding it to <code>appendTo</code> if
* specified.
*
* @param pattern pattern to parse
* @param pos current parse position
* @param appendTo optional StringBuffer to append
* @param escapingOn whether to process escaped quotes
* @return <code>appendTo</code>
*/
private StringBuffer appendQuotedString(String pattern, ParsePosition pos,
StringBuffer appendTo, boolean escapingOn) {
// start of generated patch
int start=pos.getIndex();
char[] c=pattern.toCharArray();
if(escapingOn&&c[start]==QUOTE){
next(pos);
return appendTo==null?null:appendTo.append(QUOTE);
}
// end of generated patch
/* start of original code
int start = pos.getIndex();
char[] c = pattern.toCharArray();
if (escapingOn && c[start] == QUOTE) {
return appendTo == null ? null : appendTo.append(QUOTE);
}
end of original code*/
int lastHold = start;
for (int i = pos.getIndex(); i < pattern.length(); i++) {
if (escapingOn && pattern.substring(i).startsWith(ESCAPED_QUOTE)) {
appendTo.append(c, lastHold, pos.getIndex() - lastHold).append(
QUOTE);
pos.setIndex(i + ESCAPED_QUOTE.length());
lastHold = pos.getIndex();
continue;
}
switch (c[pos.getIndex()]) {
case QUOTE:
next(pos);
return appendTo == null ? null : appendTo.append(c, lastHold,
pos.getIndex() - lastHold);
default:
next(pos);
}
}
throw new IllegalArgumentException(
"Unterminated quoted string at position " + start);
}
/**
* <p>Parses a string representing a date by trying a variety of different parsers.</p>
*
* <p>The parse will try each parse pattern in turn.
* A parse is only deemed successful if it parses the whole of the input string.
* If no parse patterns match, a ParseException is thrown.</p>
*
* @param str the date to parse, not null
* @param parsePatterns the date format patterns to use, see SimpleDateFormat, not null
* @param lenient Specify whether or not date/time parsing is to be lenient.
* @return the parsed date
* @throws IllegalArgumentException if the date string or pattern array is null
* @throws ParseException if none of the date patterns were suitable
* @see java.util.Calender#isLenient()
*/
private static Date parseDateWithLeniency(String str, String[] parsePatterns,
boolean lenient) throws ParseException {
if (str == null || parsePatterns == null) {
throw new IllegalArgumentException("Date and Patterns must not be null");
}
SimpleDateFormat parser = new SimpleDateFormat();
parser.setLenient(lenient);
ParsePosition pos = new ParsePosition(0);
for (int i = 0; i < parsePatterns.length; i++) {
String pattern = parsePatterns[i];
// LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat
if (parsePatterns[i].endsWith("ZZ")) {
pattern = pattern.substring(0, pattern.length() - 1);
}
parser.applyPattern(pattern);
pos.setIndex(0);
String str2 = str;
// LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException
if (parsePatterns[i].endsWith("ZZ")) {
int signIdx = indexOfSignChars(str2, 0);
while (signIdx >=0) {
str2 = reformatTimezone(str2, signIdx);
signIdx = indexOfSignChars(str2, ++signIdx);
}
}
Date date = parser.parse(str2, pos);
if (date != null && pos.getIndex() == str2.length()) {
return date;
}
}
throw new ParseException("Unable to parse the date: " + str, -1);
}
public static void main(String[] args) {
String date = "13 Jan 2005 21:45:34 ABC";
String format = "dd MMM yyyy HH:mm:ss z";
ParsePosition pp = new ParsePosition(0);
pp.setIndex(0);
SimpleDateFormat sd = new SimpleDateFormat(format, Locale.ENGLISH);
Date d = sd.parse(date, pp);
int errorIndex = pp.getErrorIndex();
if (errorIndex == 21) {
System.out.println(": passed");
} else {
System.out.println(": failed");
throw new RuntimeException("Failed with wrong index: " + errorIndex);
}
}
private DateTimeParseContext parseUnresolved0(CharSequence text, ParsePosition position) {
Objects.requireNonNull(text, "text");
Objects.requireNonNull(position, "position");
DateTimeParseContext context = new DateTimeParseContext(this);
int pos = position.getIndex();
pos = printerParser.parse(context, text, pos);
if (pos < 0) {
position.setErrorIndex(~pos); // index not updated from input
return null;
}
position.setIndex(pos); // errorIndex not updated from input
return context;
}
/** Read and return a tuple value from the current position in the given string. An exception is thrown if a
* valid number is not found. The parsing position is advanced past the parsed number and any trailing separator.
* @param str the string being parsed
* @param pos the current parsing position
* @return the tuple value
* @throws IllegalArgumentException if the configured prefix is not null and is not found at the current
* parsing position, ignoring preceding whitespace
*/
private double readTupleValue(String str, ParsePosition pos) {
final int startIdx = pos.getIndex();
int endIdx = str.indexOf(separator, startIdx);
if (endIdx < 0) {
if (suffix != null) {
endIdx = str.indexOf(suffix, startIdx);
}
if (endIdx < 0) {
endIdx = str.length();
}
}
final String substr = str.substring(startIdx, endIdx);
try {
final double value = Double.parseDouble(substr);
// advance the position and move past any terminating separator
pos.setIndex(endIdx);
matchSequence(str, separator, pos);
return value;
} catch (NumberFormatException exc) {
throw parseFailure(String.format("unable to parse number from string \"%s\"", substr), str, pos, exc);
}
}
private DateTimeParseContext parseUnresolved0(CharSequence text, ParsePosition position) {
Objects.requireNonNull(text, "text");
Objects.requireNonNull(position, "position");
DateTimeParseContext context = new DateTimeParseContext(this);
int pos = position.getIndex();
pos = printerParser.parse(context, text, pos);
if (pos < 0) {
position.setErrorIndex(~pos); // index not updated from input
return null;
}
position.setIndex(pos); // errorIndex not updated from input
return context;
}
/**
* Parse a zone ID.
* @param text the text contains a time zone ID string at the position.
* @param pos the position.
* @return The zone ID parsed.
*/
private static String parseZoneID(String text, ParsePosition pos) {
String resolvedID = null;
if (ZONE_ID_TRIE == null) {
synchronized (TimeZoneFormat.class) {
if (ZONE_ID_TRIE == null) {
// Build zone ID trie
TextTrieMap<String> trie = new TextTrieMap<String>(true);
String[] ids = TimeZone.getAvailableIDs();
for (String id : ids) {
trie.put(id, id);
}
ZONE_ID_TRIE = trie;
}
}
}
int[] matchLen = new int[] {0};
Iterator<String> itr = ZONE_ID_TRIE.get(text, pos.getIndex(), matchLen);
if (itr != null) {
resolvedID = itr.next();
pos.setIndex(pos.getIndex() + matchLen[0]);
} else {
// TODO
// We many need to handle rule based custom zone ID (See ZoneMeta.parseCustomID),
// such as GM+05:00. However, the public parse method in this class also calls
// parseOffsetLocalizedGMT and custom zone IDs are likely supported by the parser,
// so we might not need to handle them here.
pos.setErrorIndex(pos.getIndex());
}
return resolvedID;
}
private DateTimeParseContext parseUnresolved0(CharSequence text, ParsePosition position) {
Objects.requireNonNull(text, "text");
Objects.requireNonNull(position, "position");
DateTimeParseContext context = new DateTimeParseContext(this);
int pos = position.getIndex();
pos = printerParser.parse(context, text, pos);
if (pos < 0) {
position.setErrorIndex(~pos); // index not updated from input
return null;
}
position.setIndex(pos); // errorIndex not updated from input
return context;
}
/**
* Dispatches to the inherited version of this function, but makes
* sure that lenientParse is off.
*/
public Number doParse(String text, ParsePosition parsePosition, double baseValue,
double upperBound, boolean lenientParse) {
// we don't have to do anything special to do the parsing here,
// but we have to turn lenient parsing off-- if we leave it on,
// it SERIOUSLY messes up the algorithm
// if withZeros is true, we need to count the zeros
// and use that to adjust the parse result
int zeroCount = 0;
if (withZeros) {
String workText = text;
ParsePosition workPos = new ParsePosition(1);
//int digit;
while (workText.length() > 0 && workPos.getIndex() != 0) {
workPos.setIndex(0);
/*digit = */ruleSet.parse(workText, workPos, 1).intValue(); // parse zero or nothing at all
if (workPos.getIndex() == 0) {
// we failed, either there were no more zeros, or the number was formatted with digits
// either way, we're done
break;
}
++zeroCount;
parsePosition.setIndex(parsePosition.getIndex() + workPos.getIndex());
workText = workText.substring(workPos.getIndex());
while (workText.length() > 0 && workText.charAt(0) == ' ') {
workText = workText.substring(1);
parsePosition.setIndex(parsePosition.getIndex() + 1);
}
}
text = text.substring(parsePosition.getIndex()); // arrgh!
parsePosition.setIndex(0);
}
// we've parsed off the zeros, now let's parse the rest from our current position
Number result = super.doParse(text, parsePosition, withZeros ? 1 : baseValue, upperBound, false);
if (withZeros) {
// any base value will do in this case. is there a way to
// force this to not bother trying all the base values?
// compute the 'effective' base and prescale the value down
long n = result.longValue();
long d = 1;
while (d <= n) {
d *= 10;
}
// now add the zeros
while (zeroCount > 0) {
d *= 10;
--zeroCount;
}
// d is now our true denominator
result = new Double(n/(double)d);
}
return result;
}
@Override
public String match(CharSequence text, ParsePosition pos) {
int off = pos.getIndex();
int end = text.length();
int len = key.length();
int koff = 0;
while (koff < len && off < end) {
if (isLenientChar(text.charAt(off))) {
off++;
continue;
}
if (!isEqual(key.charAt(koff++), text.charAt(off++))) {
return null;
}
}
if (koff != len) {
return null;
}
if (child != null && off != end) {
int off0 = off;
while (off0 < end && isLenientChar(text.charAt(off0))) {
off0++;
}
if (off0 < end) {
PrefixTree c = child;
do {
if (isEqual(c.c0, text.charAt(off0))) {
pos.setIndex(off0);
String found = c.match(text, pos);
if (found != null) {
return found;
}
break;
}
c = c.sibling;
} while (c != null);
}
}
pos.setIndex(off);
return value;
}
@Override
public String match(CharSequence text, ParsePosition pos) {
int off = pos.getIndex();
int end = text.length();
int len = key.length();
int koff = 0;
while (koff < len && off < end) {
if (isLenientChar(text.charAt(off))) {
off++;
continue;
}
if (!isEqual(key.charAt(koff++), text.charAt(off++))) {
return null;
}
}
if (koff != len) {
return null;
}
if (child != null && off != end) {
int off0 = off;
while (off0 < end && isLenientChar(text.charAt(off0))) {
off0++;
}
if (off0 < end) {
PrefixTree c = child;
do {
if (isEqual(c.c0, text.charAt(off0))) {
pos.setIndex(off0);
String found = c.match(text, pos);
if (found != null) {
return found;
}
break;
}
c = c.sibling;
} while (c != null);
}
}
pos.setIndex(off);
return value;
}
/**
* Parses the specified string, beginning at the specified position, according
* to this formatter's rules. This will match the string against all of the
* formatter's public rule sets and return the value corresponding to the longest
* parseable substring. This function's behavior is affected by the lenient
* parse mode.
* @param text The string to parse
* @param parsePosition On entry, contains the position of the first character
* in "text" to examine. On exit, has been updated to contain the position
* of the first character in "text" that wasn't consumed by the parse.
* @return The number that corresponds to the parsed text. This will be an
* instance of either Long or Double, depending on whether the result has a
* fractional part.
* @see #setLenientParseMode
* @stable ICU 2.0
*/
@Override
public Number parse(String text, ParsePosition parsePosition) {
// parsePosition tells us where to start parsing. We copy the
// text in the string from here to the end inro a new string,
// and create a new ParsePosition and result variable to use
// for the duration of the parse operation
String workingText = text.substring(parsePosition.getIndex());
ParsePosition workingPos = new ParsePosition(0);
Number tempResult = null;
// keep track of the largest number of characters consumed in
// the various trials, and the result that corresponds to it
Number result = NFRule.ZERO;
ParsePosition highWaterMark = new ParsePosition(workingPos.getIndex());
// iterate over the public rule sets (beginning with the default one)
// and try parsing the text with each of them. Keep track of which
// one consumes the most characters: that's the one that determines
// the result we return
for (int i = ruleSets.length - 1; i >= 0; i--) {
// skip private or unparseable rule sets
if (!ruleSets[i].isPublic() || !ruleSets[i].isParseable()) {
continue;
}
// try parsing the string with the rule set. If it gets past the
// high-water mark, update the high-water mark and the result
tempResult = ruleSets[i].parse(workingText, workingPos, Double.MAX_VALUE);
if (workingPos.getIndex() > highWaterMark.getIndex()) {
result = tempResult;
highWaterMark.setIndex(workingPos.getIndex());
}
// commented out because this API on ParsePosition doesn't exist in 1.1.x
// if (workingPos.getErrorIndex() > highWaterMark.getErrorIndex()) {
// highWaterMark.setErrorIndex(workingPos.getErrorIndex());
// }
// if we manage to use up all the characters in the string,
// we don't have to try any more rule sets
if (highWaterMark.getIndex() == workingText.length()) {
break;
}
// otherwise, reset our internal parse position to the
// beginning and try again with the next rule set
workingPos.setIndex(0);
}
// add the high water mark to our original parse position and
// return the result
parsePosition.setIndex(parsePosition.getIndex() + highWaterMark.getIndex());
// commented out because this API on ParsePosition doesn't exist in 1.1.x
// if (highWaterMark.getIndex() == 0) {
// parsePosition.setErrorIndex(parsePosition.getIndex() + highWaterMark.getErrorIndex());
// }
return result;
}
/**
* Parse the given property pattern at the given parse position.
* @param symbols TODO
*/
private UnicodeSet applyPropertyPattern(String pattern, ParsePosition ppos, SymbolTable symbols) {
int pos = ppos.getIndex();
// On entry, ppos should point to one of the following locations:
// Minimum length is 5 characters, e.g. \p{L}
if ((pos+5) > pattern.length()) {
return null;
}
boolean posix = false; // true for [:pat:], false for \p{pat} \P{pat} \N{pat}
boolean isName = false; // true for \N{pat}, o/w false
boolean invert = false;
// Look for an opening [:, [:^, \p, or \P
if (pattern.regionMatches(pos, "[:", 0, 2)) {
posix = true;
pos = Utility.skipWhitespace(pattern, pos+2);
if (pos < pattern.length() && pattern.charAt(pos) == '^') {
++pos;
invert = true;
}
} else if (pattern.regionMatches(true, pos, "\\p", 0, 2) ||
pattern.regionMatches(pos, "\\N", 0, 2)) {
char c = pattern.charAt(pos+1);
invert = (c == 'P');
isName = (c == 'N');
pos = Utility.skipWhitespace(pattern, pos+2);
if (pos == pattern.length() || pattern.charAt(pos++) != '{') {
// Syntax error; "\p" or "\P" not followed by "{"
return null;
}
} else {
// Open delimiter not seen
return null;
}
// Look for the matching close delimiter, either :] or }
int close = pattern.indexOf(posix ? ":]" : "}", pos);
if (close < 0) {
// Syntax error; close delimiter missing
return null;
}
// Look for an '=' sign. If this is present, we will parse a
// medium \p{gc=Cf} or long \p{GeneralCategory=Format}
// pattern.
int equals = pattern.indexOf('=', pos);
String propName, valueName;
if (equals >= 0 && equals < close && !isName) {
// Equals seen; parse medium/long pattern
propName = pattern.substring(pos, equals);
valueName = pattern.substring(equals+1, close);
}
else {
// Handle case where no '=' is seen, and \N{}
propName = pattern.substring(pos, close);
valueName = "";
// Handle \N{name}
if (isName) {
// This is a little inefficient since it means we have to
// parse "na" back to UProperty.NAME even though we already
// know it's UProperty.NAME. If we refactor the API to
// support args of (int, String) then we can remove
// "na" and make this a little more efficient.
valueName = propName;
propName = "na";
}
}
applyPropertyAlias(propName, valueName, symbols);
if (invert) {
complement();
}
// Move to the limit position after the close delimiter
ppos.setIndex(close + (posix ? 2 : 1));
return this;
}
/**
* Parse the given property pattern at the given parse position.
* @param symbols TODO
*/
private UnicodeSet applyPropertyPattern(String pattern, ParsePosition ppos, SymbolTable symbols) {
int pos = ppos.getIndex();
// On entry, ppos should point to one of the following locations:
// Minimum length is 5 characters, e.g. \p{L}
if ((pos+5) > pattern.length()) {
return null;
}
boolean posix = false; // true for [:pat:], false for \p{pat} \P{pat} \N{pat}
boolean isName = false; // true for \N{pat}, o/w false
boolean invert = false;
// Look for an opening [:, [:^, \p, or \P
if (pattern.regionMatches(pos, "[:", 0, 2)) {
posix = true;
pos = PatternProps.skipWhiteSpace(pattern, (pos+2));
if (pos < pattern.length() && pattern.charAt(pos) == '^') {
++pos;
invert = true;
}
} else if (pattern.regionMatches(true, pos, "\\p", 0, 2) ||
pattern.regionMatches(pos, "\\N", 0, 2)) {
char c = pattern.charAt(pos+1);
invert = (c == 'P');
isName = (c == 'N');
pos = PatternProps.skipWhiteSpace(pattern, (pos+2));
if (pos == pattern.length() || pattern.charAt(pos++) != '{') {
// Syntax error; "\p" or "\P" not followed by "{"
return null;
}
} else {
// Open delimiter not seen
return null;
}
// Look for the matching close delimiter, either :] or }
int close = pattern.indexOf(posix ? ":]" : "}", pos);
if (close < 0) {
// Syntax error; close delimiter missing
return null;
}
// Look for an '=' sign. If this is present, we will parse a
// medium \p{gc=Cf} or long \p{GeneralCategory=Format}
// pattern.
int equals = pattern.indexOf('=', pos);
String propName, valueName;
if (equals >= 0 && equals < close && !isName) {
// Equals seen; parse medium/long pattern
propName = pattern.substring(pos, equals);
valueName = pattern.substring(equals+1, close);
}
else {
// Handle case where no '=' is seen, and \N{}
propName = pattern.substring(pos, close);
valueName = "";
// Handle \N{name}
if (isName) {
// This is a little inefficient since it means we have to
// parse "na" back to UProperty.NAME even though we already
// know it's UProperty.NAME. If we refactor the API to
// support args of (int, String) then we can remove
// "na" and make this a little more efficient.
valueName = propName;
propName = "na";
}
}
applyPropertyAlias(propName, valueName, symbols);
if (invert) {
complement();
}
// Move to the limit position after the close delimiter
ppos.setIndex(close + (posix ? 2 : 1));
return this;
}
/**
* <p>Parsing is not supported.</p>
*
* @param source the string to parse
* @param pos the parsing position
* @return <code>null</code> as not supported
*/
public Object parseObject(String source, ParsePosition pos) {
pos.setIndex(0);
pos.setErrorIndex(0);
return null;
}
/**
* Convenience method to advance parse position by 1
*
* @param pos ParsePosition
* @return <code>pos</code>
*/
private ParsePosition next(ParsePosition pos) {
pos.setIndex(pos.getIndex() + 1);
return pos;
}