Check whether a date is a valid future date











up vote
3
down vote

favorite
2












I'm looking to increase the conciseness of this code. I realize that I can use Joda (or Java 8's new date API), but if I were to keep this to just Java 7, any suggestions? (I care less about whitespace and formatting.)



/**
* Tests whether the date input represents
* a real date in mm/dd/YYYY format that is after the current date.
* Useful for testing send dates and expiration dates.
*
* Tests against current date minus 24 hours
* so users in different time zones from the server can
* be accommodated.
*
* @param pDateString date to be tested
* @return true if date (@12:01 am) >= yesterday (@12:02am)
*/
public static boolean isValidFutureDate(String pDateString) {
if (!isValidDate(pDateString)) {
return false;
}
StringTokenizer st = new StringTokenizer(pDateString.trim(), "/");
if (st.countTokens() != 3) {
throw new NumberFormatException("Date format should be MM/DD/YYYY.");
}
String month = st.nextToken();
String day = st.nextToken();
String year = st.nextToken();
long oneDayInMillis = 86400000;
// set reference point to yesterday's date, 12:01am
GregorianCalendar ref = new GregorianCalendar();
ref.setTime(new Date(System.currentTimeMillis() - oneDayInMillis));
ref.set(Calendar.HOUR_OF_DAY, 0);
ref.set(Calendar.MINUTE, 1);
ref.set(Calendar.AM_PM, Calendar.AM);
// set comparison time to entered day, 12:02am
GregorianCalendar now = toDate(year, month, day);
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 2);
ref.set(Calendar.AM_PM, Calendar.AM);

return now.after(ref);
}

/**
* This method tests whether the date string passed in represents
* a real date in mm/dd/YYYY format.
*
* @param pDateString date to be tested
* @return a <code>boolean</code> value
*/
public static boolean isValidDate(String pDateString) {
StringTokenizer st= new StringTokenizer(pDateString.trim(), "/");
if (st.countTokens() != 3) {
throw new NumberFormatException("Date format should be MM/DD/YYYY.");
}
String month = st.nextToken();
String day = st.nextToken();
String year = st.nextToken();
return toDate(year, month, day) != null;
}

/**
* Converts a String set of date values to a GregorianCalendar object.
*
* @param year a <code>String</code> value
* @param month a <code>String</code> value
* @param day a <code>String</code> value
* @return a <code>GregorianCalendar</code> value
*/
public static GregorianCalendar toDate(final String year,
final String month,
final String day) {

int mm, dd, yyyy;

try {
if(year.length() != 4) {
throw new NumberFormatException("Please provide four(4) digits for the year.");
}
yyyy = Integer.parseInt(year);
if(yyyy == 0) {
throw new NumberFormatException("zero is an invalid year.");
}
}
catch(NumberFormatException nfe) {
throw new NumberFormatException(year + " is an invalid year.");
}

try {
mm = Integer.parseInt(month);
if(mm < 1 || mm > 12) {
throw new NumberFormatException(month + " is an invalid month.");
}
}
catch(NumberFormatException nfe) {
throw new NumberFormatException(month + " is an invalid month.");
}

try {
dd = Integer.parseInt(day);
}
catch(NumberFormatException nfe) {
throw new NumberFormatException(day + " is an invalid day.");
}

GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );
if(dd > gc.getActualMaximum(GregorianCalendar.DATE)) {
throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
}
if(dd < gc.getActualMinimum(GregorianCalendar.DATE)) {
throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
}
return new GregorianCalendar(yyyy,mm,dd);
}









share|improve this question




























    up vote
    3
    down vote

    favorite
    2












    I'm looking to increase the conciseness of this code. I realize that I can use Joda (or Java 8's new date API), but if I were to keep this to just Java 7, any suggestions? (I care less about whitespace and formatting.)



    /**
    * Tests whether the date input represents
    * a real date in mm/dd/YYYY format that is after the current date.
    * Useful for testing send dates and expiration dates.
    *
    * Tests against current date minus 24 hours
    * so users in different time zones from the server can
    * be accommodated.
    *
    * @param pDateString date to be tested
    * @return true if date (@12:01 am) >= yesterday (@12:02am)
    */
    public static boolean isValidFutureDate(String pDateString) {
    if (!isValidDate(pDateString)) {
    return false;
    }
    StringTokenizer st = new StringTokenizer(pDateString.trim(), "/");
    if (st.countTokens() != 3) {
    throw new NumberFormatException("Date format should be MM/DD/YYYY.");
    }
    String month = st.nextToken();
    String day = st.nextToken();
    String year = st.nextToken();
    long oneDayInMillis = 86400000;
    // set reference point to yesterday's date, 12:01am
    GregorianCalendar ref = new GregorianCalendar();
    ref.setTime(new Date(System.currentTimeMillis() - oneDayInMillis));
    ref.set(Calendar.HOUR_OF_DAY, 0);
    ref.set(Calendar.MINUTE, 1);
    ref.set(Calendar.AM_PM, Calendar.AM);
    // set comparison time to entered day, 12:02am
    GregorianCalendar now = toDate(year, month, day);
    now.set(Calendar.HOUR_OF_DAY, 0);
    now.set(Calendar.MINUTE, 2);
    ref.set(Calendar.AM_PM, Calendar.AM);

    return now.after(ref);
    }

    /**
    * This method tests whether the date string passed in represents
    * a real date in mm/dd/YYYY format.
    *
    * @param pDateString date to be tested
    * @return a <code>boolean</code> value
    */
    public static boolean isValidDate(String pDateString) {
    StringTokenizer st= new StringTokenizer(pDateString.trim(), "/");
    if (st.countTokens() != 3) {
    throw new NumberFormatException("Date format should be MM/DD/YYYY.");
    }
    String month = st.nextToken();
    String day = st.nextToken();
    String year = st.nextToken();
    return toDate(year, month, day) != null;
    }

    /**
    * Converts a String set of date values to a GregorianCalendar object.
    *
    * @param year a <code>String</code> value
    * @param month a <code>String</code> value
    * @param day a <code>String</code> value
    * @return a <code>GregorianCalendar</code> value
    */
    public static GregorianCalendar toDate(final String year,
    final String month,
    final String day) {

    int mm, dd, yyyy;

    try {
    if(year.length() != 4) {
    throw new NumberFormatException("Please provide four(4) digits for the year.");
    }
    yyyy = Integer.parseInt(year);
    if(yyyy == 0) {
    throw new NumberFormatException("zero is an invalid year.");
    }
    }
    catch(NumberFormatException nfe) {
    throw new NumberFormatException(year + " is an invalid year.");
    }

    try {
    mm = Integer.parseInt(month);
    if(mm < 1 || mm > 12) {
    throw new NumberFormatException(month + " is an invalid month.");
    }
    }
    catch(NumberFormatException nfe) {
    throw new NumberFormatException(month + " is an invalid month.");
    }

    try {
    dd = Integer.parseInt(day);
    }
    catch(NumberFormatException nfe) {
    throw new NumberFormatException(day + " is an invalid day.");
    }

    GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );
    if(dd > gc.getActualMaximum(GregorianCalendar.DATE)) {
    throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
    }
    if(dd < gc.getActualMinimum(GregorianCalendar.DATE)) {
    throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
    }
    return new GregorianCalendar(yyyy,mm,dd);
    }









    share|improve this question


























      up vote
      3
      down vote

      favorite
      2









      up vote
      3
      down vote

      favorite
      2






      2





      I'm looking to increase the conciseness of this code. I realize that I can use Joda (or Java 8's new date API), but if I were to keep this to just Java 7, any suggestions? (I care less about whitespace and formatting.)



      /**
      * Tests whether the date input represents
      * a real date in mm/dd/YYYY format that is after the current date.
      * Useful for testing send dates and expiration dates.
      *
      * Tests against current date minus 24 hours
      * so users in different time zones from the server can
      * be accommodated.
      *
      * @param pDateString date to be tested
      * @return true if date (@12:01 am) >= yesterday (@12:02am)
      */
      public static boolean isValidFutureDate(String pDateString) {
      if (!isValidDate(pDateString)) {
      return false;
      }
      StringTokenizer st = new StringTokenizer(pDateString.trim(), "/");
      if (st.countTokens() != 3) {
      throw new NumberFormatException("Date format should be MM/DD/YYYY.");
      }
      String month = st.nextToken();
      String day = st.nextToken();
      String year = st.nextToken();
      long oneDayInMillis = 86400000;
      // set reference point to yesterday's date, 12:01am
      GregorianCalendar ref = new GregorianCalendar();
      ref.setTime(new Date(System.currentTimeMillis() - oneDayInMillis));
      ref.set(Calendar.HOUR_OF_DAY, 0);
      ref.set(Calendar.MINUTE, 1);
      ref.set(Calendar.AM_PM, Calendar.AM);
      // set comparison time to entered day, 12:02am
      GregorianCalendar now = toDate(year, month, day);
      now.set(Calendar.HOUR_OF_DAY, 0);
      now.set(Calendar.MINUTE, 2);
      ref.set(Calendar.AM_PM, Calendar.AM);

      return now.after(ref);
      }

      /**
      * This method tests whether the date string passed in represents
      * a real date in mm/dd/YYYY format.
      *
      * @param pDateString date to be tested
      * @return a <code>boolean</code> value
      */
      public static boolean isValidDate(String pDateString) {
      StringTokenizer st= new StringTokenizer(pDateString.trim(), "/");
      if (st.countTokens() != 3) {
      throw new NumberFormatException("Date format should be MM/DD/YYYY.");
      }
      String month = st.nextToken();
      String day = st.nextToken();
      String year = st.nextToken();
      return toDate(year, month, day) != null;
      }

      /**
      * Converts a String set of date values to a GregorianCalendar object.
      *
      * @param year a <code>String</code> value
      * @param month a <code>String</code> value
      * @param day a <code>String</code> value
      * @return a <code>GregorianCalendar</code> value
      */
      public static GregorianCalendar toDate(final String year,
      final String month,
      final String day) {

      int mm, dd, yyyy;

      try {
      if(year.length() != 4) {
      throw new NumberFormatException("Please provide four(4) digits for the year.");
      }
      yyyy = Integer.parseInt(year);
      if(yyyy == 0) {
      throw new NumberFormatException("zero is an invalid year.");
      }
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(year + " is an invalid year.");
      }

      try {
      mm = Integer.parseInt(month);
      if(mm < 1 || mm > 12) {
      throw new NumberFormatException(month + " is an invalid month.");
      }
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(month + " is an invalid month.");
      }

      try {
      dd = Integer.parseInt(day);
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(day + " is an invalid day.");
      }

      GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );
      if(dd > gc.getActualMaximum(GregorianCalendar.DATE)) {
      throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
      }
      if(dd < gc.getActualMinimum(GregorianCalendar.DATE)) {
      throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
      }
      return new GregorianCalendar(yyyy,mm,dd);
      }









      share|improve this question















      I'm looking to increase the conciseness of this code. I realize that I can use Joda (or Java 8's new date API), but if I were to keep this to just Java 7, any suggestions? (I care less about whitespace and formatting.)



      /**
      * Tests whether the date input represents
      * a real date in mm/dd/YYYY format that is after the current date.
      * Useful for testing send dates and expiration dates.
      *
      * Tests against current date minus 24 hours
      * so users in different time zones from the server can
      * be accommodated.
      *
      * @param pDateString date to be tested
      * @return true if date (@12:01 am) >= yesterday (@12:02am)
      */
      public static boolean isValidFutureDate(String pDateString) {
      if (!isValidDate(pDateString)) {
      return false;
      }
      StringTokenizer st = new StringTokenizer(pDateString.trim(), "/");
      if (st.countTokens() != 3) {
      throw new NumberFormatException("Date format should be MM/DD/YYYY.");
      }
      String month = st.nextToken();
      String day = st.nextToken();
      String year = st.nextToken();
      long oneDayInMillis = 86400000;
      // set reference point to yesterday's date, 12:01am
      GregorianCalendar ref = new GregorianCalendar();
      ref.setTime(new Date(System.currentTimeMillis() - oneDayInMillis));
      ref.set(Calendar.HOUR_OF_DAY, 0);
      ref.set(Calendar.MINUTE, 1);
      ref.set(Calendar.AM_PM, Calendar.AM);
      // set comparison time to entered day, 12:02am
      GregorianCalendar now = toDate(year, month, day);
      now.set(Calendar.HOUR_OF_DAY, 0);
      now.set(Calendar.MINUTE, 2);
      ref.set(Calendar.AM_PM, Calendar.AM);

      return now.after(ref);
      }

      /**
      * This method tests whether the date string passed in represents
      * a real date in mm/dd/YYYY format.
      *
      * @param pDateString date to be tested
      * @return a <code>boolean</code> value
      */
      public static boolean isValidDate(String pDateString) {
      StringTokenizer st= new StringTokenizer(pDateString.trim(), "/");
      if (st.countTokens() != 3) {
      throw new NumberFormatException("Date format should be MM/DD/YYYY.");
      }
      String month = st.nextToken();
      String day = st.nextToken();
      String year = st.nextToken();
      return toDate(year, month, day) != null;
      }

      /**
      * Converts a String set of date values to a GregorianCalendar object.
      *
      * @param year a <code>String</code> value
      * @param month a <code>String</code> value
      * @param day a <code>String</code> value
      * @return a <code>GregorianCalendar</code> value
      */
      public static GregorianCalendar toDate(final String year,
      final String month,
      final String day) {

      int mm, dd, yyyy;

      try {
      if(year.length() != 4) {
      throw new NumberFormatException("Please provide four(4) digits for the year.");
      }
      yyyy = Integer.parseInt(year);
      if(yyyy == 0) {
      throw new NumberFormatException("zero is an invalid year.");
      }
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(year + " is an invalid year.");
      }

      try {
      mm = Integer.parseInt(month);
      if(mm < 1 || mm > 12) {
      throw new NumberFormatException(month + " is an invalid month.");
      }
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(month + " is an invalid month.");
      }

      try {
      dd = Integer.parseInt(day);
      }
      catch(NumberFormatException nfe) {
      throw new NumberFormatException(day + " is an invalid day.");
      }

      GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );
      if(dd > gc.getActualMaximum(GregorianCalendar.DATE)) {
      throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
      }
      if(dd < gc.getActualMinimum(GregorianCalendar.DATE)) {
      throw new NumberFormatException(CalendarUtils.months[gc.get(GregorianCalendar.MONTH)] + " " + dd + " is an invalid day in "+gc.get(GregorianCalendar.YEAR) + ".");
      }
      return new GregorianCalendar(yyyy,mm,dd);
      }






      java performance datetime validation cyclomatic-complexity






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited yesterday









      200_success

      127k15149412




      127k15149412










      asked Feb 8 '15 at 4:09









      bphilipnyc

      152119




      152119






















          3 Answers
          3






          active

          oldest

          votes

















          up vote
          4
          down vote



          accepted










          Correctness



          My first point is that the current date is accepted as a valid future date. That is odd, and it is certainly not according to :




          Tests whether the date input represents a real date in mm/dd/YYYY
          format that is after the current date.




          Simplicity



          Secondly, assuming the current date should return false, the entire implementation can be as simple as :



          public static boolean isValidDate(String pDateString) throws ParseException {
          Date date = new SimpleDateFormat("MM/dd/yyyy").parse(pDateString);
          return new Date().before(date);
          }


          Testable



          Lastly, this method is difficult to test. Does it work when now falls in a DST overlap period? Does it work on 29th of February? Does it work in the time zone "Australia/Darwin"?



          While you may not use Java 8, you can certainly make a Clock abstraction of your own to get around this.






          share|improve this answer























          • Points all well taken.
            – bphilipnyc
            Feb 9 '15 at 22:43


















          up vote
          1
          down vote














          try {
          if(year.length() != 4) {
          throw new NumberFormatException("Please provide four(4) digits for the year.");
          }
          yyyy = Integer.parseInt(year);
          if(yyyy == 0) {
          throw new NumberFormatException("zero is an invalid year.");
          }
          }
          catch(NumberFormatException nfe) {
          throw new NumberFormatException(year + " is an invalid year.");
          }



          What happens if there is a non-numeric character in the year string? You could either accept a three digit year or reject a four digit year. E.g. -800 would be acceptable under this check but +2016 would not.



          What happens if someone provides a five digit year? You'd throw an exception even though that would be a valid future date.



          You catch anything that is a NumberFormatException but then throw another NumberFormatException with a less-specific message.



          try {
          yyyy = Integer.parseInt(year);
          if ( yyyy <= 0 ) {
          throw new NumberFormatException("zero is an invalid year.");
          }
          }
          catch(NumberFormatException nfe) {
          throw new NumberFormatException(year + " is an invalid year.");
          }

          if ( yyyy < 100 ) {
          throw new NumberFormatException("Please provide all digits for the year (" + year + ").");
          }


          This version accepts years with three or more digits but rejects two digit years (often abbreviations for four digit years). It throws a general invalid year exception if parseInt fails or if the year is non-positive. If the year is between 0 and 100, it assumes that it is abbreviated and asks for more digits.



          This still catches and rethrows the exception on non-positive years, but it doesn't discard any information in doing so.



          If you want to reject three digit years as well, you can just increase the boundary from 100 to 1000. However, I'm strongly against rejecting five or more digits, as that essentially puts an expiration date on your code. It may be early, but why introduce an unnecessary Y10K problem?






          share|improve this answer




























            up vote
            1
            down vote













            GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );


            Never do this. It's just confusing, use mm-1.



            throw new NumberFormatException("zero is an invalid year.");


            And negative is fine?



            Your many catch-clauses provide a detailed message, but does anyone need it? A date isn't that complicated... a single catch clause stating "expected MM/DD/YYYY, got ..." should do.





            If you really want to make it fast, then you surely shouldn't tokenize the string twice. And most probably you shouldn't write soooo much code.



            You could also store the current midnight and start a ScheduledThreadPoolExecutor to update it regularly as this fooling around with the Calender can cost quite some time.



            There's a SimpleDateFormat class doing about everything you need. But you don't need to convert anything to date for the comparison. Working with ints fully suffices. Working with the inputs chars would be most efficient, but a bit tedious.





            To keep it simple:



            // updated via the `ScheduledThreadPoolExecutor`
            private int year;
            private int month;
            private int day;

            private static final Pattern DATE_PATTERN =
            Pattern.compile("\s*(\d{1,2})/(\d{1,2})/(\d{4}))\s*");

            public static boolean isValidDate(String date) {
            Matcher m = Pattern.matcher(date); // no trimming needed
            checkArgument(m.matches(), ...);
            int inputYear = Integer.parseInt(m.group(3));
            checkArgument(inputYear >= 1, ...);

            int inputMonth = Integer.parseInt(m.group(1));
            checkArgument(inputMonth >= 1 && inputMonth <= 12, ...);

            int inputDay = Integer.parseInt(m.group(2));
            checkArgument(inputDay >= 1 && inputDay <= daysInMonth(inputYear, inputMonth), ...);

            if (inputYear < year) return false;
            if (inputYear > year) return true;

            if (inputMonth < month) return false;
            if (inputMonth > month) return true;

            return inputDay > day;
            }


            I'm leaving daysInMonth as an exercise. :D You surely know that one-line conditionals are against the conventions (but I love them). checkArgument is from Guava.





            As already said, solution reading the input char by char would be faster, but I'd go the opposite direction. Most probably, the speed is more than good enough, and the problem is called "stringly typed programming". Never use strings, when something better is available. Unfortunately, JDK Date is rather worse (worst class ever?), so if you don't want to use Joda, you should write your own. Immutable.This is rather trivial as long as you implement only what you really need and delegate to one the terrible JDK classes.






            share|improve this answer























            • Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
              – bphilipnyc
              Feb 8 '15 at 5:02










            • @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
              – maaartinus
              Feb 8 '15 at 7:31






            • 1




              There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
              – Toby Speight
              yesterday











            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f79913%2fcheck-whether-a-date-is-a-valid-future-date%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            4
            down vote



            accepted










            Correctness



            My first point is that the current date is accepted as a valid future date. That is odd, and it is certainly not according to :




            Tests whether the date input represents a real date in mm/dd/YYYY
            format that is after the current date.




            Simplicity



            Secondly, assuming the current date should return false, the entire implementation can be as simple as :



            public static boolean isValidDate(String pDateString) throws ParseException {
            Date date = new SimpleDateFormat("MM/dd/yyyy").parse(pDateString);
            return new Date().before(date);
            }


            Testable



            Lastly, this method is difficult to test. Does it work when now falls in a DST overlap period? Does it work on 29th of February? Does it work in the time zone "Australia/Darwin"?



            While you may not use Java 8, you can certainly make a Clock abstraction of your own to get around this.






            share|improve this answer























            • Points all well taken.
              – bphilipnyc
              Feb 9 '15 at 22:43















            up vote
            4
            down vote



            accepted










            Correctness



            My first point is that the current date is accepted as a valid future date. That is odd, and it is certainly not according to :




            Tests whether the date input represents a real date in mm/dd/YYYY
            format that is after the current date.




            Simplicity



            Secondly, assuming the current date should return false, the entire implementation can be as simple as :



            public static boolean isValidDate(String pDateString) throws ParseException {
            Date date = new SimpleDateFormat("MM/dd/yyyy").parse(pDateString);
            return new Date().before(date);
            }


            Testable



            Lastly, this method is difficult to test. Does it work when now falls in a DST overlap period? Does it work on 29th of February? Does it work in the time zone "Australia/Darwin"?



            While you may not use Java 8, you can certainly make a Clock abstraction of your own to get around this.






            share|improve this answer























            • Points all well taken.
              – bphilipnyc
              Feb 9 '15 at 22:43













            up vote
            4
            down vote



            accepted







            up vote
            4
            down vote



            accepted






            Correctness



            My first point is that the current date is accepted as a valid future date. That is odd, and it is certainly not according to :




            Tests whether the date input represents a real date in mm/dd/YYYY
            format that is after the current date.




            Simplicity



            Secondly, assuming the current date should return false, the entire implementation can be as simple as :



            public static boolean isValidDate(String pDateString) throws ParseException {
            Date date = new SimpleDateFormat("MM/dd/yyyy").parse(pDateString);
            return new Date().before(date);
            }


            Testable



            Lastly, this method is difficult to test. Does it work when now falls in a DST overlap period? Does it work on 29th of February? Does it work in the time zone "Australia/Darwin"?



            While you may not use Java 8, you can certainly make a Clock abstraction of your own to get around this.






            share|improve this answer














            Correctness



            My first point is that the current date is accepted as a valid future date. That is odd, and it is certainly not according to :




            Tests whether the date input represents a real date in mm/dd/YYYY
            format that is after the current date.




            Simplicity



            Secondly, assuming the current date should return false, the entire implementation can be as simple as :



            public static boolean isValidDate(String pDateString) throws ParseException {
            Date date = new SimpleDateFormat("MM/dd/yyyy").parse(pDateString);
            return new Date().before(date);
            }


            Testable



            Lastly, this method is difficult to test. Does it work when now falls in a DST overlap period? Does it work on 29th of February? Does it work in the time zone "Australia/Darwin"?



            While you may not use Java 8, you can certainly make a Clock abstraction of your own to get around this.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited yesterday









            Alireza Noorali

            1034




            1034










            answered Feb 9 '15 at 20:18









            bowmore

            5,16911422




            5,16911422












            • Points all well taken.
              – bphilipnyc
              Feb 9 '15 at 22:43


















            • Points all well taken.
              – bphilipnyc
              Feb 9 '15 at 22:43
















            Points all well taken.
            – bphilipnyc
            Feb 9 '15 at 22:43




            Points all well taken.
            – bphilipnyc
            Feb 9 '15 at 22:43












            up vote
            1
            down vote














            try {
            if(year.length() != 4) {
            throw new NumberFormatException("Please provide four(4) digits for the year.");
            }
            yyyy = Integer.parseInt(year);
            if(yyyy == 0) {
            throw new NumberFormatException("zero is an invalid year.");
            }
            }
            catch(NumberFormatException nfe) {
            throw new NumberFormatException(year + " is an invalid year.");
            }



            What happens if there is a non-numeric character in the year string? You could either accept a three digit year or reject a four digit year. E.g. -800 would be acceptable under this check but +2016 would not.



            What happens if someone provides a five digit year? You'd throw an exception even though that would be a valid future date.



            You catch anything that is a NumberFormatException but then throw another NumberFormatException with a less-specific message.



            try {
            yyyy = Integer.parseInt(year);
            if ( yyyy <= 0 ) {
            throw new NumberFormatException("zero is an invalid year.");
            }
            }
            catch(NumberFormatException nfe) {
            throw new NumberFormatException(year + " is an invalid year.");
            }

            if ( yyyy < 100 ) {
            throw new NumberFormatException("Please provide all digits for the year (" + year + ").");
            }


            This version accepts years with three or more digits but rejects two digit years (often abbreviations for four digit years). It throws a general invalid year exception if parseInt fails or if the year is non-positive. If the year is between 0 and 100, it assumes that it is abbreviated and asks for more digits.



            This still catches and rethrows the exception on non-positive years, but it doesn't discard any information in doing so.



            If you want to reject three digit years as well, you can just increase the boundary from 100 to 1000. However, I'm strongly against rejecting five or more digits, as that essentially puts an expiration date on your code. It may be early, but why introduce an unnecessary Y10K problem?






            share|improve this answer

























              up vote
              1
              down vote














              try {
              if(year.length() != 4) {
              throw new NumberFormatException("Please provide four(4) digits for the year.");
              }
              yyyy = Integer.parseInt(year);
              if(yyyy == 0) {
              throw new NumberFormatException("zero is an invalid year.");
              }
              }
              catch(NumberFormatException nfe) {
              throw new NumberFormatException(year + " is an invalid year.");
              }



              What happens if there is a non-numeric character in the year string? You could either accept a three digit year or reject a four digit year. E.g. -800 would be acceptable under this check but +2016 would not.



              What happens if someone provides a five digit year? You'd throw an exception even though that would be a valid future date.



              You catch anything that is a NumberFormatException but then throw another NumberFormatException with a less-specific message.



              try {
              yyyy = Integer.parseInt(year);
              if ( yyyy <= 0 ) {
              throw new NumberFormatException("zero is an invalid year.");
              }
              }
              catch(NumberFormatException nfe) {
              throw new NumberFormatException(year + " is an invalid year.");
              }

              if ( yyyy < 100 ) {
              throw new NumberFormatException("Please provide all digits for the year (" + year + ").");
              }


              This version accepts years with three or more digits but rejects two digit years (often abbreviations for four digit years). It throws a general invalid year exception if parseInt fails or if the year is non-positive. If the year is between 0 and 100, it assumes that it is abbreviated and asks for more digits.



              This still catches and rethrows the exception on non-positive years, but it doesn't discard any information in doing so.



              If you want to reject three digit years as well, you can just increase the boundary from 100 to 1000. However, I'm strongly against rejecting five or more digits, as that essentially puts an expiration date on your code. It may be early, but why introduce an unnecessary Y10K problem?






              share|improve this answer























                up vote
                1
                down vote










                up vote
                1
                down vote










                try {
                if(year.length() != 4) {
                throw new NumberFormatException("Please provide four(4) digits for the year.");
                }
                yyyy = Integer.parseInt(year);
                if(yyyy == 0) {
                throw new NumberFormatException("zero is an invalid year.");
                }
                }
                catch(NumberFormatException nfe) {
                throw new NumberFormatException(year + " is an invalid year.");
                }



                What happens if there is a non-numeric character in the year string? You could either accept a three digit year or reject a four digit year. E.g. -800 would be acceptable under this check but +2016 would not.



                What happens if someone provides a five digit year? You'd throw an exception even though that would be a valid future date.



                You catch anything that is a NumberFormatException but then throw another NumberFormatException with a less-specific message.



                try {
                yyyy = Integer.parseInt(year);
                if ( yyyy <= 0 ) {
                throw new NumberFormatException("zero is an invalid year.");
                }
                }
                catch(NumberFormatException nfe) {
                throw new NumberFormatException(year + " is an invalid year.");
                }

                if ( yyyy < 100 ) {
                throw new NumberFormatException("Please provide all digits for the year (" + year + ").");
                }


                This version accepts years with three or more digits but rejects two digit years (often abbreviations for four digit years). It throws a general invalid year exception if parseInt fails or if the year is non-positive. If the year is between 0 and 100, it assumes that it is abbreviated and asks for more digits.



                This still catches and rethrows the exception on non-positive years, but it doesn't discard any information in doing so.



                If you want to reject three digit years as well, you can just increase the boundary from 100 to 1000. However, I'm strongly against rejecting five or more digits, as that essentially puts an expiration date on your code. It may be early, but why introduce an unnecessary Y10K problem?






                share|improve this answer













                try {
                if(year.length() != 4) {
                throw new NumberFormatException("Please provide four(4) digits for the year.");
                }
                yyyy = Integer.parseInt(year);
                if(yyyy == 0) {
                throw new NumberFormatException("zero is an invalid year.");
                }
                }
                catch(NumberFormatException nfe) {
                throw new NumberFormatException(year + " is an invalid year.");
                }



                What happens if there is a non-numeric character in the year string? You could either accept a three digit year or reject a four digit year. E.g. -800 would be acceptable under this check but +2016 would not.



                What happens if someone provides a five digit year? You'd throw an exception even though that would be a valid future date.



                You catch anything that is a NumberFormatException but then throw another NumberFormatException with a less-specific message.



                try {
                yyyy = Integer.parseInt(year);
                if ( yyyy <= 0 ) {
                throw new NumberFormatException("zero is an invalid year.");
                }
                }
                catch(NumberFormatException nfe) {
                throw new NumberFormatException(year + " is an invalid year.");
                }

                if ( yyyy < 100 ) {
                throw new NumberFormatException("Please provide all digits for the year (" + year + ").");
                }


                This version accepts years with three or more digits but rejects two digit years (often abbreviations for four digit years). It throws a general invalid year exception if parseInt fails or if the year is non-positive. If the year is between 0 and 100, it assumes that it is abbreviated and asks for more digits.



                This still catches and rethrows the exception on non-positive years, but it doesn't discard any information in doing so.



                If you want to reject three digit years as well, you can just increase the boundary from 100 to 1000. However, I'm strongly against rejecting five or more digits, as that essentially puts an expiration date on your code. It may be early, but why introduce an unnecessary Y10K problem?







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Feb 8 '15 at 5:20









                Brythan

                6,61431536




                6,61431536






















                    up vote
                    1
                    down vote













                    GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );


                    Never do this. It's just confusing, use mm-1.



                    throw new NumberFormatException("zero is an invalid year.");


                    And negative is fine?



                    Your many catch-clauses provide a detailed message, but does anyone need it? A date isn't that complicated... a single catch clause stating "expected MM/DD/YYYY, got ..." should do.





                    If you really want to make it fast, then you surely shouldn't tokenize the string twice. And most probably you shouldn't write soooo much code.



                    You could also store the current midnight and start a ScheduledThreadPoolExecutor to update it regularly as this fooling around with the Calender can cost quite some time.



                    There's a SimpleDateFormat class doing about everything you need. But you don't need to convert anything to date for the comparison. Working with ints fully suffices. Working with the inputs chars would be most efficient, but a bit tedious.





                    To keep it simple:



                    // updated via the `ScheduledThreadPoolExecutor`
                    private int year;
                    private int month;
                    private int day;

                    private static final Pattern DATE_PATTERN =
                    Pattern.compile("\s*(\d{1,2})/(\d{1,2})/(\d{4}))\s*");

                    public static boolean isValidDate(String date) {
                    Matcher m = Pattern.matcher(date); // no trimming needed
                    checkArgument(m.matches(), ...);
                    int inputYear = Integer.parseInt(m.group(3));
                    checkArgument(inputYear >= 1, ...);

                    int inputMonth = Integer.parseInt(m.group(1));
                    checkArgument(inputMonth >= 1 && inputMonth <= 12, ...);

                    int inputDay = Integer.parseInt(m.group(2));
                    checkArgument(inputDay >= 1 && inputDay <= daysInMonth(inputYear, inputMonth), ...);

                    if (inputYear < year) return false;
                    if (inputYear > year) return true;

                    if (inputMonth < month) return false;
                    if (inputMonth > month) return true;

                    return inputDay > day;
                    }


                    I'm leaving daysInMonth as an exercise. :D You surely know that one-line conditionals are against the conventions (but I love them). checkArgument is from Guava.





                    As already said, solution reading the input char by char would be faster, but I'd go the opposite direction. Most probably, the speed is more than good enough, and the problem is called "stringly typed programming". Never use strings, when something better is available. Unfortunately, JDK Date is rather worse (worst class ever?), so if you don't want to use Joda, you should write your own. Immutable.This is rather trivial as long as you implement only what you really need and delegate to one the terrible JDK classes.






                    share|improve this answer























                    • Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                      – bphilipnyc
                      Feb 8 '15 at 5:02










                    • @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                      – maaartinus
                      Feb 8 '15 at 7:31






                    • 1




                      There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                      – Toby Speight
                      yesterday















                    up vote
                    1
                    down vote













                    GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );


                    Never do this. It's just confusing, use mm-1.



                    throw new NumberFormatException("zero is an invalid year.");


                    And negative is fine?



                    Your many catch-clauses provide a detailed message, but does anyone need it? A date isn't that complicated... a single catch clause stating "expected MM/DD/YYYY, got ..." should do.





                    If you really want to make it fast, then you surely shouldn't tokenize the string twice. And most probably you shouldn't write soooo much code.



                    You could also store the current midnight and start a ScheduledThreadPoolExecutor to update it regularly as this fooling around with the Calender can cost quite some time.



                    There's a SimpleDateFormat class doing about everything you need. But you don't need to convert anything to date for the comparison. Working with ints fully suffices. Working with the inputs chars would be most efficient, but a bit tedious.





                    To keep it simple:



                    // updated via the `ScheduledThreadPoolExecutor`
                    private int year;
                    private int month;
                    private int day;

                    private static final Pattern DATE_PATTERN =
                    Pattern.compile("\s*(\d{1,2})/(\d{1,2})/(\d{4}))\s*");

                    public static boolean isValidDate(String date) {
                    Matcher m = Pattern.matcher(date); // no trimming needed
                    checkArgument(m.matches(), ...);
                    int inputYear = Integer.parseInt(m.group(3));
                    checkArgument(inputYear >= 1, ...);

                    int inputMonth = Integer.parseInt(m.group(1));
                    checkArgument(inputMonth >= 1 && inputMonth <= 12, ...);

                    int inputDay = Integer.parseInt(m.group(2));
                    checkArgument(inputDay >= 1 && inputDay <= daysInMonth(inputYear, inputMonth), ...);

                    if (inputYear < year) return false;
                    if (inputYear > year) return true;

                    if (inputMonth < month) return false;
                    if (inputMonth > month) return true;

                    return inputDay > day;
                    }


                    I'm leaving daysInMonth as an exercise. :D You surely know that one-line conditionals are against the conventions (but I love them). checkArgument is from Guava.





                    As already said, solution reading the input char by char would be faster, but I'd go the opposite direction. Most probably, the speed is more than good enough, and the problem is called "stringly typed programming". Never use strings, when something better is available. Unfortunately, JDK Date is rather worse (worst class ever?), so if you don't want to use Joda, you should write your own. Immutable.This is rather trivial as long as you implement only what you really need and delegate to one the terrible JDK classes.






                    share|improve this answer























                    • Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                      – bphilipnyc
                      Feb 8 '15 at 5:02










                    • @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                      – maaartinus
                      Feb 8 '15 at 7:31






                    • 1




                      There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                      – Toby Speight
                      yesterday













                    up vote
                    1
                    down vote










                    up vote
                    1
                    down vote









                    GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );


                    Never do this. It's just confusing, use mm-1.



                    throw new NumberFormatException("zero is an invalid year.");


                    And negative is fine?



                    Your many catch-clauses provide a detailed message, but does anyone need it? A date isn't that complicated... a single catch clause stating "expected MM/DD/YYYY, got ..." should do.





                    If you really want to make it fast, then you surely shouldn't tokenize the string twice. And most probably you shouldn't write soooo much code.



                    You could also store the current midnight and start a ScheduledThreadPoolExecutor to update it regularly as this fooling around with the Calender can cost quite some time.



                    There's a SimpleDateFormat class doing about everything you need. But you don't need to convert anything to date for the comparison. Working with ints fully suffices. Working with the inputs chars would be most efficient, but a bit tedious.





                    To keep it simple:



                    // updated via the `ScheduledThreadPoolExecutor`
                    private int year;
                    private int month;
                    private int day;

                    private static final Pattern DATE_PATTERN =
                    Pattern.compile("\s*(\d{1,2})/(\d{1,2})/(\d{4}))\s*");

                    public static boolean isValidDate(String date) {
                    Matcher m = Pattern.matcher(date); // no trimming needed
                    checkArgument(m.matches(), ...);
                    int inputYear = Integer.parseInt(m.group(3));
                    checkArgument(inputYear >= 1, ...);

                    int inputMonth = Integer.parseInt(m.group(1));
                    checkArgument(inputMonth >= 1 && inputMonth <= 12, ...);

                    int inputDay = Integer.parseInt(m.group(2));
                    checkArgument(inputDay >= 1 && inputDay <= daysInMonth(inputYear, inputMonth), ...);

                    if (inputYear < year) return false;
                    if (inputYear > year) return true;

                    if (inputMonth < month) return false;
                    if (inputMonth > month) return true;

                    return inputDay > day;
                    }


                    I'm leaving daysInMonth as an exercise. :D You surely know that one-line conditionals are against the conventions (but I love them). checkArgument is from Guava.





                    As already said, solution reading the input char by char would be faster, but I'd go the opposite direction. Most probably, the speed is more than good enough, and the problem is called "stringly typed programming". Never use strings, when something better is available. Unfortunately, JDK Date is rather worse (worst class ever?), so if you don't want to use Joda, you should write your own. Immutable.This is rather trivial as long as you implement only what you really need and delegate to one the terrible JDK classes.






                    share|improve this answer














                    GregorianCalendar gc = new GregorianCalendar( yyyy, --mm, 1 );


                    Never do this. It's just confusing, use mm-1.



                    throw new NumberFormatException("zero is an invalid year.");


                    And negative is fine?



                    Your many catch-clauses provide a detailed message, but does anyone need it? A date isn't that complicated... a single catch clause stating "expected MM/DD/YYYY, got ..." should do.





                    If you really want to make it fast, then you surely shouldn't tokenize the string twice. And most probably you shouldn't write soooo much code.



                    You could also store the current midnight and start a ScheduledThreadPoolExecutor to update it regularly as this fooling around with the Calender can cost quite some time.



                    There's a SimpleDateFormat class doing about everything you need. But you don't need to convert anything to date for the comparison. Working with ints fully suffices. Working with the inputs chars would be most efficient, but a bit tedious.





                    To keep it simple:



                    // updated via the `ScheduledThreadPoolExecutor`
                    private int year;
                    private int month;
                    private int day;

                    private static final Pattern DATE_PATTERN =
                    Pattern.compile("\s*(\d{1,2})/(\d{1,2})/(\d{4}))\s*");

                    public static boolean isValidDate(String date) {
                    Matcher m = Pattern.matcher(date); // no trimming needed
                    checkArgument(m.matches(), ...);
                    int inputYear = Integer.parseInt(m.group(3));
                    checkArgument(inputYear >= 1, ...);

                    int inputMonth = Integer.parseInt(m.group(1));
                    checkArgument(inputMonth >= 1 && inputMonth <= 12, ...);

                    int inputDay = Integer.parseInt(m.group(2));
                    checkArgument(inputDay >= 1 && inputDay <= daysInMonth(inputYear, inputMonth), ...);

                    if (inputYear < year) return false;
                    if (inputYear > year) return true;

                    if (inputMonth < month) return false;
                    if (inputMonth > month) return true;

                    return inputDay > day;
                    }


                    I'm leaving daysInMonth as an exercise. :D You surely know that one-line conditionals are against the conventions (but I love them). checkArgument is from Guava.





                    As already said, solution reading the input char by char would be faster, but I'd go the opposite direction. Most probably, the speed is more than good enough, and the problem is called "stringly typed programming". Never use strings, when something better is available. Unfortunately, JDK Date is rather worse (worst class ever?), so if you don't want to use Joda, you should write your own. Immutable.This is rather trivial as long as you implement only what you really need and delegate to one the terrible JDK classes.







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Feb 8 '15 at 7:42

























                    answered Feb 8 '15 at 4:51









                    maaartinus

                    12.3k12668




                    12.3k12668












                    • Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                      – bphilipnyc
                      Feb 8 '15 at 5:02










                    • @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                      – maaartinus
                      Feb 8 '15 at 7:31






                    • 1




                      There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                      – Toby Speight
                      yesterday


















                    • Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                      – bphilipnyc
                      Feb 8 '15 at 5:02










                    • @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                      – maaartinus
                      Feb 8 '15 at 7:31






                    • 1




                      There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                      – Toby Speight
                      yesterday
















                    Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                    – bphilipnyc
                    Feb 8 '15 at 5:02




                    Nice catch about tokenizing the String twice and the negative value. Guava isn't part of Java 7 though...
                    – bphilipnyc
                    Feb 8 '15 at 5:02












                    @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                    – maaartinus
                    Feb 8 '15 at 7:31




                    @bphilipnyc Sure, I missed this point, however, I can hardly imagine writing anything without it. If you don't have checkArgument, then write your own; it makes the code more readable and surprisingly even slightly faster (assuming you do it right).
                    – maaartinus
                    Feb 8 '15 at 7:31




                    1




                    1




                    There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                    – Toby Speight
                    yesterday




                    There might be a reason to reject year 0, but accept negative years, if the code intended to deal with conventional notation (where 1 B.C. is astronomical Year 0, and so on). But the code appears not to do that...
                    – Toby Speight
                    yesterday


















                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f79913%2fcheck-whether-a-date-is-a-valid-future-date%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Morgemoulin

                    Scott Moir

                    Souastre