0

I've created a class to receive an object with a date and verify by a method if the date is writen correctly. The problem is that my code doesn't work to verify the characters correctly.

Here I have the objects called at main function:

 hoje.constructor("12/03/2023"); //right date
 amanha.constructor("0//03/2003"); //wrong date

And here are the method construtor() at Date Class:

 public void constructor(String dateInsert){

        if (dateInsert.length() != 10){
            this.date = "01/01/0001";
        } else {
            boolean isADate = true;
            for(int i = 0 ; i < dateInsert.length() ; i++){
                char c = dateInsert.charAt(i);
                String letter = "" + c;
                
                if(Character.isDigit(c) == false && letter == "/"){
                    if(i != 2 || i != 5){
                        isADate = false;
                    } else {
                        isADate = true;
                    }
                } else {
                    isADate = true;
                }
            }

            if(isADate == true){
                this.data = dateInsert;
            } else {
                this.data = "01/01/0001";
            }
        }     
  }
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java – OldProgrammer Mar 13 '23 at 21:48
  • 1
    The format is fixed. Start by looking at character positions 2 & 5 and check that they are `/` characters, if they are, you can split the String in these and then simply do a `String` to `int` conversation test. Oh, and `letter == "/"` is not how you compare `String`s, see [How do I compare strings in Java?](https://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) for more details - although, I would have just compared the `character` – MadProgrammer Mar 13 '23 at 22:03
  • 1
    You should also start with the assumption that the format is correct and only change `isADate` (to `false`) when it's not - never set it back to `true` in the loop. You should also exit the loop once you've proven the format to be incorrect – MadProgrammer Mar 13 '23 at 22:04
  • @OldProgrammer In this case simpler: `c == '/'` (comparing chars rather than strings). You are correct that the OP’s way (`letter == "/"`) did not work. – Ole V.V. Mar 14 '23 at 08:31

2 Answers2

2

I just want to point out that this kind of thing is a bad idea, but, since you're only comparing the "format" against a "fixed format", I won't go on a wild rant.

The format is fixed. Start by looking at character positions 2 & 5 and check that they are / characters, if they are, you can split the String on these and then simply do a String to int conversation test. Oh, and letter == "/" is not how you compare Strings, see How do I compare strings in Java? for more details - although, I would have just compared the character

The core problem (apart from comparing Strings incorrectly), is you reset the isADate to true in the loop

You should start with the assumption that the format is correct and only change isADate (to false) when it's not - never set it back to true in the loop. You should also exit the loop once you've proven the format to be incorrect.

For example...

boolean isADate = true;
for (int i = 0; i < dateInsert.length(); i++) {
    char c = dateInsert.charAt(i);

    if (i == 2 || i == 5) {
        if (c != '/') {
            isADate = false;
            break;
        }
    } else if (!Character.isDigit(c)) {
        isADate = false;
        break;
    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
2

The Answer by MadProgrammer is correct and wise.

Parsing with DateTimeFormatter

The better way to validate dates is to define a DateTimeFormatter with a formatting pattern that matches your expected input.

DateTimeFormatter f = DateTimeForatter.ofPattern( "MM/dd/uuuu" ) ;

Attempt to parse your actual input. Trap for DateTimeParseException indicating the input did not meet your expectations.

try {
    LocalDate ld = LocalDate.parse( input , f ) ;
} catch ( DateTimeParseException e ) {
    … handle faulty input
}

ISO 8601

The ultimate solution is to educate the publisher of your data about the benefits of using only standard ISO 8601 formats when exchanging date-time values textually.

Avoid exchanging data in localized or invented formats. The standard formats are designed to be easy for machines to parse, and easy for humans to read across various cultures. The standard formats are designed to avoid ambiguities.

The java.time classes in Java 8+ use the standard ISO 8601 formats by default when parsing/generating text.

The standard format for a date-only value is YYYY-MM-DD such as 2023-12-03. Notice the logic of year-month-day: bigger, middle, smallest. And this text when sorted alphabetically is also in chronological order.

Jakarta Bean Validation

You may find Jakarta Bean Validation 3.0 useful as a way of validating data inputs.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • This would be my preferred method - but I'm assuming (which is bad of me) that this is some kind of "assignment" and the requirement is to validate the format of the date as apposed to validating the date itself – MadProgrammer Mar 13 '23 at 23:26
  • @MadProgrammer Agreed. Thus my up-vote and mention of your Answer. I added my Answer for posterity, for those folks doing real work rather than schoolwork. – Basil Bourque Mar 13 '23 at 23:29
  • Also agreed ! – MadProgrammer Mar 13 '23 at 23:36