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