Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You can revert your thinking - try to fail as quickly as possible when the String <em>definitely</em> is no date:</p> <ul> <li>it's <code>null</code></li> <li>its <code>length</code> is not 8 (based on your example date format!)</li> <li>it <a href="http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric%28java.lang.CharSequence%29" rel="nofollow noreferrer">contains anything other that a number</a> (if your date format is only for numerical dates)</li> </ul> <p>If none of those apply, then try to parse it - preferably with a pre-made static <code>Format</code> object, don't create one on every method run.</p> <hr> <p><em>EDIT after comments</em></p> <p>Based on <a href="https://stackoverflow.com/questions/10013998/fastest-way-to-parse-a-yyyymmdd-date-in-java/10014172#10014172">this neat trick</a>, I wrote a fast validation method. It looks ugly, but is significantly faster than the usual library methods (which should be used in any standard situation!), because <em>it relies on your specific date format</em> and does not create a <code>Date</code> object. It handles the date as an <code>int</code> and goes on from that.</p> <p>I tested the <code>daysInMonth()</code> method just a little bit (<a href="https://stackoverflow.com/a/1021332/1273080">the leap year condition taken from Peter Lawrey</a>), so I hope there's no apparent bug.</p> <p>A quick (estimated!) microbenchmark indicated a speedup by a factor of 30.</p> <pre><code>public static boolean isValidDate(String dateString) { if (dateString == null || dateString.length() != "yyyyMMdd".length()) { return false; } int date; try { date = Integer.parseInt(dateString); } catch (NumberFormatException e) { return false; } int year = date / 10000; int month = (date % 10000) / 100; int day = date % 100; // leap years calculation not valid before 1581 boolean yearOk = (year &gt;= 1581) &amp;&amp; (year &lt;= 2500); boolean monthOk = (month &gt;= 1) &amp;&amp; (month &lt;= 12); boolean dayOk = (day &gt;= 1) &amp;&amp; (day &lt;= daysInMonth(year, month)); return (yearOk &amp;&amp; monthOk &amp;&amp; dayOk); } private static int daysInMonth(int year, int month) { int daysInMonth; switch (month) { case 1: // fall through case 3: // fall through case 5: // fall through case 7: // fall through case 8: // fall through case 10: // fall through case 12: daysInMonth = 31; break; case 2: if (((year % 4 == 0) &amp;&amp; (year % 100 != 0)) || (year % 400 == 0)) { daysInMonth = 29; } else { daysInMonth = 28; } break; default: // returns 30 even for nonexistant months daysInMonth = 30; } return daysInMonth; } </code></pre> <p>P.S. Your example method above will return <code>true</code> for "99999999". Mine will only return true for existent dates :).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload