-3

I want to verify that a date is correctly formatted from user input. I cannot figure out how to include whitespace in my Regex and accept two different types of formats.

Example

Here are the two correct formats:

  1. April 30, 2021
  2. 04/30/2021

Those should be matched by the regex in below code.

Code

public GeoCountDownTimer(String geoDate) {

    for (int i = 0; i < geoDate.length(); i++) {
        if (!String.valueOf(geoDate.charAt(i)).matches("[a-zA-Z0-9]")) {
            System.out.println("Incorrect formatting at: " + geoDate.charAt(i) + "\n");
        }
    }
}
Ethan
  • 35
  • 9
  • 2
    But your `geoDate.matches` is operating on the whole string every iteration ? – Computable Jan 31 '22 at 19:34
  • Super, you added the examples. Now, please add (1) the issue, unexpected behavior/output or error-message resulting from your code, (2) a concrete question. Then we can reopen this great question. – hc_dev Feb 01 '22 at 10:07

2 Answers2

1

am trying to exclude everything but a-z, 0-9 and spaces

That'll work for any string containing letters, digits, spaces and semicolons (you didn't mention any punctuation but there's a ; in your example "January; 21 2022").

geoDate.matches("[\\w\\s;]+")

But if geoDate has a fixed structure I'd suggest you use this condition instead:

geoDate.matches("\\p{Alpha}{3,9}; \\d{2} \\d{4}")

Character classes that are used above:

\p{Alpha} - an alphabetic character

\w - a word character: [a-zA-Z_0-9]

\d - a digit: [0-9]

\s - a whitespace character: [ \t\n\x0B\f\r]

And {} - is a quantifier, that allows to specify a number of matches.

X{n,m} - X, at least n but not more than m times

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/regex/Pattern.html

Alexander Ivanchenko
  • 25,667
  • 5
  • 22
  • 46
  • This looks like it solves my issue, but I am marking the answer above as the selected answer because it offers an easier solution to Regex that I was unaware of. – Ethan Feb 01 '22 at 04:57
1

Looks like date validation and parsing. This can be solved using distinct approaches:

  1. (high-level) date-parsing functions (e.g. java.text.DateFormat)
  2. (low-level) regular-expressions (regex)

I would strongly recommend the first, because it is more exact and well-tested, plus communicates intent to peers.

Using Java's date-formats

See Parse a String to Date in Java, using SimpleDateFormat:

String geoDate = "January; 21 2022":

SimpleDateFormat sdf = new SimpleDateFormat("MMMMM; dd yyyy");
try {
    Date date = sdf.parse(geoDate);
    System.out.println(date);
} catch (ParseException e) {
    e.printStackTrace();
}

Note: for interpreting the month-name according the expected locale (e.g. "January" for US-en) you can specify a Locale to the constructor: SimpleDateFormat(pattern, locale).

Using regex

Research for similar questions like: Trying to improve regex for date validation

A simple regex could look like this (only matching, now capture-groups for extraction):

String geoDate = "January; 21 2022":

String regex_alphanum = "[a-zA-Z0-9 ]+";  // added a space
System.out.println(geoDate.matches(regex_alphanum)); // does not match because semicolon

String regex_alphanum_semicolon = "[a-zA-Z0-9 ;]+"; // added the semicolon
System.out.println(geoDate.matches(regex_alphanum_semicolon)); // matches

Note: the quantifier (+) added to the character-range matches at least one or many occurrences.

Disadvantage: Even a tuned regex would probably match "Mey; 99 0021" which is not a valid date or allow input for a date that does not exist like "February, 29 2022" (2022 is not a leap year).

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • I think I am going to go with the `SimpleDateFormat` option, seems a bit easier and better for my use case. How would I have this work with two separate formats without using some sort of choice variable by the user denoting which format they plan on using so I can call the appropriate method? – Ethan Feb 01 '22 at 15:26
  • @EthanOnweller Please clarify your question first: (a) state the problem with your code and (b) ask this question there. This way your question helps other users and can be reopened to get further answers ️ – hc_dev Feb 01 '22 at 15:45