Type scanTimestamp()

in src/com/amazon/ion/impl/IonTokenReader.java [1490:1591]


    Type scanTimestamp(int c) throws IOException {

endofdate:
        for (;;) {  // fake for loop to create a label we can jump out of,
                    // because 4 or 5 levels of nested if's is just ugly

            // at this point we will have read leading digits and exactly 1 dash
            // in other words, we'll have read the year
            if (c == 'T') {
                // yearT is a valid timestamp value
                value.append((char)c);
                c = this.read(); // because we'll unread it before we return
                break endofdate;
            }
            if (c != '-') {
                // not a dash or a T after the year - so this is a bad value
                throw new IllegalStateException("invalid timestamp, expecting a dash here at " + this.position());
            }

            // append the dash and then read the month field
            value.append((char)c); // so append it, because we haven't already
            c = readDigits(2, "month");
            if (c == 'T') {
                // year-monthT is a valid timestamp value
                value.append((char)c);
                c = this.read(); // because we'll unread it before we return
                break endofdate;
            }
            if (c != '-') {
                // if the month isn't followed by a dash or a T it's an invalid month
                throw new IonException("invalid timestamp, expecting month at " + this.position());
            }

            // append the dash and read the day (or day-of-month) field
            value.append((char)c);
            c = readDigits(2, "day of month");
            if (c == 'T') {

check4timezone:
                for (;;) { // another fake label/ for=goto

                    // attach the 'T' to the value we're collecting
                    value.append((char)c);

                    // we're going to "watch" how many digits we read in the hours
                    // field.  It's 0 that's actually ok, since we can end at the
                    // 'T' we just read
                    int length_before_reading_hours = value.length();
                    // so read the hours
                    c = readDigits(2, "hours");
                    if (length_before_reading_hours == value.length()) {
                        // FIXME I don't think there should be a timezone here
                        break check4timezone;
                    }
                    if (c != ':') {
                        throw new IonException("invalid timestamp, expecting hours at " + this.position());
                    }
                    value.append((char)c);
                    // so read the minutes
                    c = readDigits(2, "minutes");
                    if (c != ':') {
                        if (c == '-' || c == '+' || c == 'Z') {
                            break check4timezone;
                        }
                        break endofdate;
                    }
                    value.append((char)c);
                    // so read the seconds
                    c = readDigits(2, "seconds");
                    if (c != '.') {
                        if (c == '-' || c == '+' || c == 'Z') {
                            break check4timezone;
                        }
                        break endofdate;
                    }
                    value.append((char)c);
                    // so read the fractional seconds
                    c = readDigits(32, "fractional seconds");
                    break check4timezone;
                }//check4timezone

                // now check to see if it's a timezone offset we're looking at
                if (c == '-' || c == '+') {
                    value.append((char)c);
                    // so read the timezone offset
                    c = readDigits(2, "timezone offset");
                    if (c != ':') break endofdate;
                    value.append((char)c);
                    c = readDigits(2, "timezone offset");
                }
                else if (c == 'Z') {
                    value.append((char)c);
                    c = this.read(); // because we'll unread it before we return
                }
            }
            break endofdate;
        }//endofdate

        checkAndUnreadNumericStopper(c);

        return Type.constTime;
    }