int colon = tok.indexOf(':'); int slash = tok.indexOf('/'); int hyphen = tok.indexOf('-');   int punctOffset = tok.length(); if (colon >= 0) punctOffset = Math.min(punctOffset, colon); if (slash >= 0) punctOffset = Math.min(punctOffset, slash); if (hyphen >= 0) punctOffset = Math.min(punctOffset, hyphen);   if (punctOffset == tok.length()) punctOffset = -1;  int num; try { num = Integer.parseInt(punctOffset < 0 ? tok : tok.substring(0, punctOffset)); } catch (NumberFormatException ex) { throw new IllegalArgumentException(tok); }            if (num > 70 && (punctOffset < 0 || punctOffset == slash)) year = num > 1900 ? num - 1900 : num; else if (punctOffset > 0 && punctOffset == colon)
int punctOffset = tok.length(); int num = 0; int punct; for (int i = 0;  ;  i++) { if (i >= punctOffset) { punct = -1; break; } else { punct = tok.charAt(i); if (punct >= '0' && punct <= '9') { if (num > 999999999) throw new IllegalArgumentException(tok); num = 10 * num + (punct - '0'); } else { punctOffset = i; break; } }  }  if (punct == ':')
  public static long parse(String string)  {    // Initialize date/time fields before parsing begins.    int year = -1;    int month = -1;    int day = -1;    int hour = -1;    int minute = -1;    int second = -1;    int timezone = 0;    boolean localTimezone = true;    // Trim out any nested stuff in parentheses now to make parsing easier.    StringBuffer buf = new StringBuffer();    int off = 0;    int openParenOffset, tmpMonth;    while ((openParenOffset = string.indexOf('(', off)) >= 0)      {	// Copy part of string leading up to open paren.	buf.append(string.substring(off, openParenOffset));	off = skipParens(string, openParenOffset);      }    buf.append(string.substring(off));    // Make all chars upper case to simplify comparisons later.    // Also ignore commas; treat them as delimiters.    StringTokenizer strtok =      new StringTokenizer(buf.toString().toUpperCase(), " \t\n\r,");    while (strtok.hasMoreTokens())      {	String tok = strtok.nextToken();	char firstch = tok.charAt(0);	if ((firstch == '+' || firstch == '-') && year >= 0)	  {	    timezone = parseTz(tok, firstch);	    localTimezone = false;	  }	else if (firstch >= '0' && firstch <= '9')	  {	    while (tok != null && tok.length() > 0)	      {	        // A colon or slash may be valid in the number.	        // Find the first of these before calling parseInt.	        int colon = tok.indexOf(':');	        int slash = tok.indexOf('/');	        int hyphen = tok.indexOf('-');		// We choose tok.length initially because it makes		// processing simpler.	        int punctOffset = tok.length();		if (colon >= 0)		  punctOffset = Math.min(punctOffset, colon);	        if (slash >= 0)	          punctOffset = Math.min(punctOffset, slash);	        if (hyphen >= 0)	          punctOffset = Math.min(punctOffset, hyphen);		// Following code relies on -1 being the exceptional		// case.		if (punctOffset == tok.length())		  punctOffset = -1;	        int num;	        try	          {		    num = Integer.parseInt(punctOffset < 0 ? tok :					   tok.substring(0, punctOffset));	          }	        catch (NumberFormatException ex)	          {		    throw new IllegalArgumentException(tok);	          }		// TBD: Spec says year can be followed by a slash.  That might		// make sense if using YY/MM/DD formats, but it would fail in		// that format for years <= 70.  Also, what about 1900?  That		// is interpreted as the year 3800; seems that the comparison		// should be num >= 1900 rather than just > 1900.		// What about a year of 62 - 70?  (61 or less could be a (leap)		// second).  70/MM/DD cause an exception but 71/MM/DD is ok		// even though there's no ambiguity in either case.		// For the parse method, the spec as written seems too loose.		// Until shown otherwise, we'll follow the spec as written.	        if (num > 70 && (punctOffset < 0 || punctOffset == slash))		  year = num > 1900 ? num - 1900 : num;		else if (punctOffset > 0 && punctOffset == colon)		  {		    if (hour < 0)		      hour = num;		    else		      minute = num;		  }		else if (punctOffset > 0 && punctOffset == slash)		  {		    if (month < 0)		      month = num - 1;		    else		      day = num;		  }		else if (hour >= 0 && minute < 0)		  minute = num;		else if (minute >= 0 && second < 0)		  second = num;		else if (day < 0)		  day = num;		else		  throw new IllegalArgumentException(tok);		// Advance string if there's more to process in this token.		if (punctOffset < 0 || punctOffset + 1 >= tok.length())		  tok = null;		else		  tok = tok.substring(punctOffset + 1);	      }	  }	else if (firstch >= 'A' && firstch <= 'Z')	  {	    if (tok.equals("AM"))	      {		if (hour < 1 || hour > 12)		  throw new IllegalArgumentException(tok);		if (hour == 12)		  hour = 0;	      }	    else if (tok.equals("PM"))	      {		if (hour < 1 || hour > 12)		  throw new IllegalArgumentException(tok);		if (hour < 12)		  hour += 12;	      }	    else if (parseDayOfWeek(tok))	      ; // Ignore it; throw the token away.	    else if (tok.equals("UT") || tok.equals("UTC") || tok.equals("GMT"))	      localTimezone = false;	    else if (tok.startsWith("UT") || tok.startsWith("GMT"))	      {		int signOffset = 3;		if (tok.charAt(1) == 'T' && tok.charAt(2) != 'C')		  signOffset = 2;	        char sign = tok.charAt(signOffset);		if (sign != '+' && sign != '-')		  throw new IllegalArgumentException(tok);	        timezone = parseTz(tok.substring(signOffset), sign);	        localTimezone = false;	      }	    else if ((tmpMonth = parseMonth(tok)) >= 0)	      month = tmpMonth;	    else if (tok.length() == 3 && tok.charAt(2) == 'T')	      {		// Convert timezone offset from hours to minutes.		char ch = tok.charAt(0);		if (ch == 'E')		  timezone = -5 * 60;		else if (ch == 'C')		  timezone = -6 * 60;		else if (ch == 'M')		  timezone = -7 * 60;		else if (ch == 'P')		  timezone = -8 * 60;		else		  throw new IllegalArgumentException(tok);		// Shift 60 minutes for Daylight Savings Time.		if (tok.charAt(1) == 'D')		  timezone += 60;		else if (tok.charAt(1) != 'S')		  throw new IllegalArgumentException(tok);	        localTimezone = false;	      }	    else	      throw new IllegalArgumentException(tok);	  }	else	  throw new IllegalArgumentException(tok);      }    // Unspecified minutes and seconds should default to 0.    if (minute < 0)      minute = 0;    if (second < 0)      second = 0;    // Throw exception if any other fields have not been recognized and set.    if (year < 0 || month < 0 || day < 0 || hour < 0)      throw new IllegalArgumentException("Missing field");    // Return the time in either local time or relative to GMT as parsed.    // If no time-zone was specified, get the local one (in minutes) and    // convert to milliseconds before adding to the UTC.    return UTC(year, month, day, hour, minute, second) + (localTimezone ?		new Date(year, month, day).getTimezoneOffset() * 60 * 1000:		-timezone * 60 * 1000);  }