title: Generic support for ISO 8601 format in Java 6
body: <p>Java 7 has introduced support in the <code>SimpleDateFormat</code> class for ISO 8601 format, via the character <code>X</code> (instead of lower or upper case <code>Z</code>). Supporting such formats in Java 6 requires preprocessing, so the best approach is the question.</p>
  
  <p>This new format is a superset of <code>Z</code> (uppercase Z), with 2 additional variations:</p>
  
  <ol>
  <li>The "minutes" field is optional (i.e., 2-digit instead of 4-digit timezones are valid)</li>
  <li>A colon character (':') can be used for separating the 2-digit "hours" field from the 2-digit "minutes" field).</li>
  </ol>
  
  <p>So, as one can observe from the <a href="http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html" rel="nofollow noreferrer">Java 7 documentation of <code>SimpleDateFormat</code></a>, the following 3 formats are now valid (instead of only the second one covered by <code>Z</code> in Java 6) and, of course, equivalent:</p>
  
  <ol>
  <li>-08</li>
  <li>-0800</li>
  <li>-08:00</li>
  </ol>
  
  <p>As discussed in an <a href="https://stackoverflow.com/questions/10614771/java-simpledateformat-pattern-for-w3c-xml-dates-with-timezone">earlier question</a> about a special case of supporting such an "expanded" timezone format, always with ':' as a separator, the best approach for backporting the Java 7 functionality into Java 6 is to subclass the <code>SimpleDateformat</code> class and override its <code>parse()</code> method, i.e:</p>
  
  <pre><code>public Date parse(String date, ParsePosition pos)
  {
      String iso = ... // Replace the X with a Z timezone string, using a regex
  
      if (iso.length() == date.length())
      {
          return null; // Not an ISO 8601 date
      }
  
      Date parsed = super.parse(iso, pos);
  
      if (parsed != null)
      {
          pos.setIndex(pos.getIndex()+1); // Adjust for ':'
      }
  
      return parsed;
  }
  </code></pre>
  
  <p>Note that the subclassed <code>SimpleDateFormat</code> objects above must be initialized with the corresponding <code>Z</code>-based pattern, i.e. if the subclass is <code>ExtendedSimpleDateformat</code> and you want to parse dates complying to the pattern <code>yyyy-MM-dd'T'HH:mm:ssX</code>, then you should use objects instantiated as</p>
  
  <pre><code>new ExtendedSimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
  </code></pre>
  
  <p>In the aforementioned <a href="https://stackoverflow.com/questions/10614771/java-simpledateformat-pattern-for-w3c-xml-dates-with-timezone">earlier question</a> the regex <code>:(?=[0-9]{2}$)</code> has been suggested for getting rid of the ':' and in a <a href="https://stackoverflow.com/questions/12951875/parsing-java-dates-with-truncated-timezone-information">similar question</a> the regex <code>(?&lt;=[+-]\d{2})$</code> has been suggested for appending the "minute" field as <code>00</code>, if needed.</p>
  
  <p>Obviously, running the 2 replacements successfully can be used for achieving full functionality. So, the <code>iso</code> local variable in the overridden <code>parse()</code> method would be set as</p>
  
  <pre><code>iso = date.replaceFirst(":(?=[0-9]{2}$)","");
  </code></pre>
  
  <p>or</p>
  
  <pre><code>iso = iso.replaceFirst("(?&lt;=[+-]\\d{2})$", "00");
  </code></pre>
  
  <p>with an <code>if</code> check in between to make sure that the <code>pos</code> value is also set properly later on and also for the <code>length()</code> comparison earlier.</p>
  
  <p>The question is: can we use a <strong>single regular expression</strong> to achieve the same effect, including the information needed for not unnecessarily checking the length and for correctly setting <code>pos</code> a few lines later?</p>
  
  <p>The implementation is intended for code that reads very large numbers of string fields that can be in any format (even totally non-date), selects only those which comply to the format and returns the parsed Java <code>Date</code> object.</p>
  
  <p>So, both <strong>accuracy</strong> and <strong>speed</strong> are of paramount importance (i.e., if using the 2 passes is faster, this approach is preferrable).</p>