in asterixdb/asterix-om/src/main/java/org/apache/asterix/om/base/temporal/ADurationParserFactory.java [103:267]
public static <T> void parseDuration(T durationString, final int start, int length, IAObject mutableObject,
ADurationParseOption parseOption, StringUtil.ICharAccessor<T> charAccessor) throws HyracksDataException {
int offset = 0;
int value = 0, hour = 0, minute = 0, second = 0, millisecond = 0, year = 0, month = 0, day = 0;
State state = State.NOTHING_READ;
short sign = 1;
if (charAccessor.charAt(durationString, start + offset) == '-') {
offset++;
sign = -1;
}
if (charAccessor.charAt(durationString, start + offset) != 'P') {
throw new HyracksDataException(durationErrorMessage + ": Missing leading 'P'.");
}
offset++;
for (; offset < length; offset++) {
if (charAccessor.charAt(durationString, start + offset) >= '0'
&& charAccessor.charAt(durationString, start + offset) <= '9') {
// accumulate the digit fields
value = value * DECIMAL_UNIT + charAccessor.charAt(durationString, start + offset) - '0';
} else {
switch (charAccessor.charAt(durationString, start + offset)) {
case 'Y':
if (state.compareTo(State.YEAR) < 0) {
if (parseOption == ADurationParseOption.DAY_TIME) {
throw new HyracksDataException(onlyDayTimeErrorMessage);
}
year = value;
state = State.YEAR;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong YEAR feild.");
}
break;
case 'M':
if (state.compareTo(State.TIME) < 0) {
if (state.compareTo(State.MONTH) < 0) {
if (parseOption == ADurationParseOption.DAY_TIME) {
throw new HyracksDataException(onlyDayTimeErrorMessage);
}
month = value;
state = State.MONTH;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong MONTH field.");
}
} else if (state.compareTo(State.MIN) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
minute = value;
state = State.MIN;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong MIN field.");
}
break;
case 'D':
if (state.compareTo(State.DAY) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
day = value;
state = State.DAY;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong DAY field");
}
break;
case 'T':
if (state.compareTo(State.TIME) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
state = State.TIME;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong TIME field.");
}
break;
case 'H':
if (state.compareTo(State.HOUR) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
hour = value;
state = State.HOUR;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong HOUR field.");
}
break;
case '.':
if (state.compareTo(State.MILLISEC) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
int i = 1;
for (; offset + i < length; i++) {
if (charAccessor.charAt(durationString, start + offset + i) >= '0'
&& charAccessor.charAt(durationString, start + offset + i) <= '9') {
if (i < 4) {
millisecond = millisecond * DECIMAL_UNIT
+ (charAccessor.charAt(durationString, start + offset + i) - '0');
} else {
throw new HyracksDataException(
durationErrorMessage + ": wrong MILLISECOND field.");
}
} else {
break;
}
}
offset += i;
state = State.MILLISEC;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong MILLISECOND field.");
}
case 'S':
if (state.compareTo(State.SEC) < 0) {
if (parseOption == ADurationParseOption.YEAR_MONTH) {
throw new HyracksDataException(onlyYearMonthErrorMessage);
}
second = value;
state = State.SEC;
} else {
throw new HyracksDataException(durationErrorMessage + ": wrong SECOND field.");
}
break;
default:
throw new HyracksDataException(durationErrorMessage + ": wrong format for duration.");
}
value = 0;
}
}
if (state.compareTo(State.TIME) == 0) {
throw new HyracksDataException(durationErrorMessage + ": no time fields after time separator.");
}
int totalMonths = sign * (year * 12 + month);
long totalMilliseconds = sign * (day * GregorianCalendarSystem.CHRONON_OF_DAY
+ hour * GregorianCalendarSystem.CHRONON_OF_HOUR + minute * GregorianCalendarSystem.CHRONON_OF_MINUTE
+ second * GregorianCalendarSystem.CHRONON_OF_SECOND + millisecond);
if (sign > 0) {
if (totalMonths < 0) {
throw new HyracksDataException(durationErrorMessage
+ ": total number of months is beyond its max value (-2147483647 to 2147483647).");
}
if (totalMilliseconds < 0) {
throw new HyracksDataException(durationErrorMessage
+ ": total number of milliseconds is beyond its max value (-9223372036854775808 to 9223372036854775807).");
}
}
if (mutableObject instanceof AMutableDuration) {
((AMutableDuration) mutableObject).setValue(totalMonths, totalMilliseconds);
} else if (mutableObject instanceof AMutableYearMonthDuration) {
((AMutableYearMonthDuration) mutableObject).setMonths(totalMonths);
} else if (mutableObject instanceof AMutableDayTimeDuration) {
((AMutableDayTimeDuration) mutableObject).setMilliseconds(totalMilliseconds);
} else {
throw new IllegalArgumentException();
}
}