public static void parseDuration()

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();
        }
    }