Here you can find the source of parse(String date)
public static Calendar parse(String date) throws ParseException
//package com.java2s; //License from project: Apache License import java.util.*; import java.text.ParsePosition; import java.text.ParseException; public class Main { /**/*www . j av a2 s . c om*/ * ID to represent the 'GMT' string */ private static final String GMT_ID = "GMT"; public static Calendar parse(String date) throws ParseException { return parse(date, new ParsePosition(0)); } /** * Parse a date from ISO-8601 formatted string. It expects a format * [yyyy-MM-dd|yyyyMMdd][T(hh:mm[:ss[.sss]]|hhmm[ss[.sss]])]?[Z|[+-]hh:mm]] * * @param date ISO string to parse in the appropriate format. * @param pos The position to start parsing from, updated to where parsing stopped. * @return the parsed Calendar * @throws ParseException if the date is not in the appropriate format */ public static Calendar parse(String date, ParsePosition pos) throws ParseException { Exception fail = null; try { int offset = pos.getIndex(); // extract year int year = parseInt(date, offset, offset += 4); if (checkOffset(date, offset, '-')) { offset += 1; } // extract month int month = parseInt(date, offset, offset += 2); if (checkOffset(date, offset, '-')) { offset += 1; } // extract day int day = parseInt(date, offset, offset += 2); // default time value int hour = 0; int minutes = 0; int seconds = 0; int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time if (checkOffset(date, offset, 'T')) { // extract hours, minutes, seconds and milliseconds hour = parseInt(date, offset += 1, offset += 2); if (checkOffset(date, offset, ':')) { offset += 1; } minutes = parseInt(date, offset, offset += 2); if (checkOffset(date, offset, ':')) { offset += 1; } // second and milliseconds can be optional if (date.length() > offset) { char c = date.charAt(offset); if (c != 'Z' && c != '+' && c != '-') { seconds = parseInt(date, offset, offset += 2); // milliseconds can be optional in the format if (checkOffset(date, offset, '.')) { milliseconds = parseInt(date, offset += 1, offset += 3); } } } } // extract timezone String timezoneId; if (date.length() <= offset) { //No time zone indicator, using default timezoneId = TimeZone.getDefault().getID(); } else { char timezoneIndicator = date.charAt(offset); if (timezoneIndicator == '+' || timezoneIndicator == '-') { String timezoneOffset = date.substring(offset); timezoneId = GMT_ID + timezoneOffset; offset += timezoneOffset.length(); } else if (timezoneIndicator == 'Z') { timezoneId = "UTC"; offset += 1; } else { throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator); } } TimeZone timezone = TimeZone.getTimeZone(timezoneId); String act = timezone.getID(); if (!act.equals(timezoneId)) { /* 22-Jan-2015, tatu: Looks like canonical version has colons, but we may be given * one without. If so, don't sweat. * Yes, very inefficient. Hopefully not hit often. * If it becomes a perf problem, add 'loose' comparison instead. */ String cleaned = act.replace(":", ""); if (!cleaned.equals(timezoneId)) { throw new IndexOutOfBoundsException("Mismatching time zone indicator: " + timezoneId + " given, resolves to " + timezone.getID()); } } Calendar calendar = new GregorianCalendar(timezone); calendar.set(Calendar.YEAR, year); calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minutes); calendar.set(Calendar.SECOND, seconds); calendar.set(Calendar.MILLISECOND, milliseconds); calendar.getTime(); pos.setIndex(offset); return calendar; // If we get a ParseException it'll already have the right message/offset. // Other exception types can convert here. } catch (IndexOutOfBoundsException e) { fail = e; } catch (NumberFormatException e) { fail = e; } catch (IllegalArgumentException e) { fail = e; } String input = (date == null) ? null : ('"' + date + "'"); String msg = fail.getMessage(); if (msg == null || msg.isEmpty()) { msg = "(" + fail.getClass().getName() + ")"; } ParseException ex = new ParseException("Failed to parse date [" + input + "]: " + msg, pos.getIndex()); ex.initCause(fail); throw ex; } /** * Parse an integer located between 2 given offsets in a string * * @param value the string to parse * @param beginIndex the start index for the integer in the string * @param endIndex the end index for the integer in the string * @return the int * @throws NumberFormatException if the value is not a number */ private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException { if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) { throw new NumberFormatException(value); } // use same logic as in Integer.parseInt() but less generic we're not supporting negative values int i = beginIndex; int result = 0; int digit; if (i < endIndex) { digit = Character.digit(value.charAt(i++), 10); if (digit < 0) { throw new NumberFormatException("Invalid number: " + value); } result = -digit; } while (i < endIndex) { digit = Character.digit(value.charAt(i++), 10); if (digit < 0) { throw new NumberFormatException("Invalid number: " + value); } result *= 10; result -= digit; } return -result; } /** * Check if the expected character exist at the given offset in the value. * * @param value the string to check at the specified offset * @param offset the offset to look for the expected character * @param expected the expected character * @return true if the expected character exist at the given offset */ private static boolean checkOffset(String value, int offset, char expected) { return (offset < value.length()) && (value.charAt(offset) == expected); } }