1

I was thinking of creating a method that should return the number of valid dates. How can I use SimpleDateFormat?

class ValidatorDate {
public static int ValidDates(String[] words) {
    DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
    format.setLenient(false);
    }
}


 public class Main {
 public static void main(String[] args) {
    System.out.println(ValidatorDate.ValidDates(new String[]{"car","bench","01/04/2019", 
 "01/13/2019", "29/02/200s"}));
    // 2
  }
}
  • In your method: `return Arrays.stream(words).filter(e -> { //your validation here - 'e' its the current word from array }).mapToInt(e -> 1).sum();` – KunLun Jun 13 '20 at 12:43
  • I can't use streams. – George Chetan Jun 13 '20 at 12:44
  • 1
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalDate` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jun 13 '20 at 13:30

1 Answers1

2

You can parse each date and its numbers in a try/catch block, and increment a counter as follows:

public static void main(String[] args) {
     String[] dates = new String[]{"car","bench","01/04/2019", "01/13/2019", "29/02/200s"};
     System.out.println(validate(dates));
}
private static int validate(String[] dates){
     int count = 0;
     DateFormat format = new SimpleDateFormat("dd/MM/yyyy");
     format.setLenient(false);
     for(String date : dates) {
          try {
               format.parse(date);
               String[] dateParts = date.split("/");
               for(String str : dateParts)
                    Integer.parseInt(str);
               if(dateParts.length!=3 || dateParts[0].length()!=2 || dateParts[1].length()!=2 || dateParts[2].length()!=4)
                    throw new Exception();
               count++;
          } catch (Exception e) {
               System.out.println("Date " + date + " is not valid");
          }
     }
     return count;
}

Output:

Date car is not valid
Date bench is not valid
Date 01/13/2019 is not valid
Date 29/02/200s is not valid
1

EDIT : According to Ole's comment and this post, it's better to use more accurate libraries:

public static void main(String[] args) {
     String[] dates = new String[]{"car","bench","01/04/2019", "01/13/2019", "29/02/200s"};
     System.out.println(validate(dates));
}
private static int validate(String[] dates){
     int count = 0;
     for(String date : dates) {
          try {
               String[] dateParts = date.split("/");
               if(dateParts.length==3 && isDateValid(Integer.parseInt(dateParts[2]), Integer.parseInt(dateParts[1]), Integer.parseInt(dateParts[0])))
                    count++;
               else
                    throw new Exception();
          } catch (Exception e) {
               System.out.println("Date " + date + " is not valid");
          }
     }
     return count;
}
private static boolean isDateValid(int year, int month, int day) {
     boolean dateIsValid = true;
     try {
          LocalDate.of(year, month, day);
     } catch (DateTimeException e) {
          dateIsValid = false;
     }
     return dateIsValid;
}
Majed Badawi
  • 27,616
  • 4
  • 25
  • 48
  • 29/02/200s should be a valid date but I can't see why. – George Chetan Jun 13 '20 at 12:56
  • 2
    @GeorgeChetan `29/02/200s` is not valid because it doesn't have 4 digit in the "year part" and `SimpleDateFormat` is expecting 4 digits – MarcoLucidi Jun 13 '20 at 13:05
  • @MarcoLucidi If I remove the for loop it will count 29/02/200s as a valid date. It's there a problem with the regex? – George Chetan Jun 13 '20 at 13:17
  • 1
    @GeorgeChetan ops, I was wrong, it's the `Integer.parseInt(str)` that is trowing exception: `java.lang.NumberFormatException: For input string: "200s"`, the date is valid and `SimpleDateFormat` accepts it, but this `validate()` method treats it as invalid – MarcoLucidi Jun 13 '20 at 13:22
  • 1
    @MarcoLucidi this is why i added the for loop. Why is 200s a valid year according to the library? – Majed Badawi Jun 13 '20 at 13:28
  • 1
    According to your method `1/2/3/4` is a valid date. It isn’t. I don’t know whether the OP accepts `29/02/200` (without the `s`), but your code does. – Ole V.V. Jun 13 '20 at 13:35
  • 2
    @MajedBadawi the [`javadoc for parse()`](https://docs.oracle.com/javase/8/docs/api/java/text/DateFormat.html#parse-java.lang.String-) says that "The method may not use the entire text of the given string". I think it stops as soon as it sees an invalid char and if it can return a valid date using what it already parsed it will return it to you. I don't know why it works this way even after `.setLenient(false)` though. – MarcoLucidi Jun 13 '20 at 13:43
  • 1
    @MarcoLucidi It does — also after setting lenient false. – Ole V.V. Jun 13 '20 at 13:54
  • 1
    In my most honest opinion helping people how to use `SimpleDateFormat` is doing them an anti-favour. It’s much better to help them *stop* using that troublesome and out-dated class. – Ole V.V. Jun 13 '20 at 13:55