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