1

My string value;

09:00-10:00,12:00-14:30,16:00-18:00 (this string repeats time intervals n times like this)

and I want to find out that a string is in the correct format using pattern matching;

Pattern.matches("<Pattern Here>", stringValue);

is it possible?

I tried;

Pattern.matches("^[0-9:0-9-0-9:0-9,]+$", value);

But doesn't work properly

6
  • 1
    "is it possible?" - Yes. Commented Nov 22, 2022 at 21:40
  • 3
    What error are you getting? Be specific. And consider design choices, i.e. splitting the bad data into an array first, then parsing each individually against your pattern. Commented Nov 22, 2022 at 21:42
  • 1
    Read a tutorial on regular expressions, rather than just guessing. Commented Nov 22, 2022 at 21:47
  • 2
    What does "correct" mean? Commented Nov 22, 2022 at 21:48
  • 1
    as @tgdavies pointed out, one could make the argument that the question is ill-defined. If we, for example, factor in leap seconds (en.wikipedia.org), the problem might not be solvable through regular expressions. Commented Nov 22, 2022 at 21:59

2 Answers 2

6

You can check if the string matches the regex, ^(?:(?:\d{2}:\d{2}\-\d{2}:\d{2})(?:,(?!$))?)*$. Note that you do not need to put starts-with (i.e. ^) and ends-with (i.e. $) when using String#matches.

If the string passes this validation, split the string on , and - and then use java.time API to validate the individual time strings.

Demo:

import java.time.LocalTime;
import java.time.format.DateTimeParseException;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(hasCorrectFormat("09:00-10:00,12:00-14:30,16:00-18:00")); // true
        System.out.println(hasCorrectFormat("09:00-10:00,12:00-1:30,16:00-18:00")); // false -> 1:30 is not in desired
                                                                                    // format
        System.out.println(hasCorrectFormat("09:00-10:00")); // true
        System.out.println(hasCorrectFormat("09:00 10:00")); // false
        System.out.println(hasCorrectFormat("09:00-10:00,09:00 10:00")); // false
        System.out.println(hasCorrectFormat("09:00-10:00-12:00-14:30,16:00-18:00")); // false
        System.out.println(hasCorrectFormat("09:00-10:00,12:00-14:30,16:00-18:00,")); // false
    }

    static boolean hasCorrectFormat(String strTimeRanges) {
        if (!strTimeRanges.matches("(?:(?:\\d{2}:\\d{2}\\-\\d{2}:\\d{2})(?:,(?!$))?)*"))
            return false;
        String[] times = strTimeRanges.split("[-,]");
        for (String time : times) {
            try {
                LocalTime.parse(time);
            } catch (DateTimeParseException e) {
                return false;
            }
        }
        return true;
    }
}

Output:

true
false
true
false
false
false
false

Regex demo

Learn more about the modern Date-Time API from Trail: Date Time.


The valuable comment from Ole V.V. has prompted me to extend my original answer to show how one can use java.time API to compare the times in individual time ranges. I hope this gives enough hints for learners to extend the solution further based on the complexity of the requirements.

import java.time.LocalTime;
import java.time.format.DateTimeParseException;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00,12:00-14:30,16:00-18:00")); // true
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00,12:00-1:30,16:00-18:00")); // false -> 1:30
        System.out.println(hasCorrectFormatAndRanges("10:00-09:00,12:00-14:30,16:00-18:00")); // false -> 10:00-09:00
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00")); // true
        System.out.println(hasCorrectFormatAndRanges("09:00 10:00")); // false
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00,09:00 10:00")); // false
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00-12:00-14:30,16:00-18:00")); // false
        System.out.println(hasCorrectFormatAndRanges("09:00-10:00,12:00-14:30,16:00-18:00,")); // false
    }

    static boolean hasCorrectFormatAndRanges(String strTimeRanges) {
        if (!strTimeRanges.matches("(?:(?:\\d{2}:\\d{2}\\-\\d{2}:\\d{2})(?:,(?!$))?)*"))
            return false;
        String[] timeRanges = strTimeRanges.split(",");
        for (String timeRange : timeRanges) {
            String[] times = timeRange.split("-");
            try {
                if (LocalTime.parse(times[1]).isBefore(LocalTime.parse(times[0])))
                    return false;
            } catch (DateTimeParseException e) {
                return false;
            }
        }
        return true;
    }
}

Output:

true
false
false
true
false
false
false
false
Sign up to request clarification or add additional context in comments.

6 Comments

This would not validate that two time values are separated by a " - ", and it would not validate that two time values are separate by two other time values with a ", ". Example: take the 1st (valid) String and replace all occurences of "," with "-" or vice-versa. The now invalid format will evaluate to true.
@Turing85 Thanks for taking the time to review this. I have updated the answer to meet this requirement.
Still not correct. String "09:00-10:00-12:00-14:30,16:00-18:00" (notice the "-" between "10:00" and "12:00") evaluates to true.
Well... now one could argue whether "09:00-10:00,12:00-14:30,16:00-18:00," should be valid or not. One way or another, I'd suggest to update the explanation. The original explanation does not really fit the code anymore.
This allows for further validating that the times come in order if desired. Like.
|
4

You can use the following pattern for any given range of 2 times in the form of 24h clock:

private static final String HOURLY_TIME_PATTERN = "([01][0-9]|2[0-3]):([0-5][0-9])";
private static final String TIME_RANGER_PATTERN = HOURLY_TIME_PATTERN + "-" + HOURLY_TIME_PATTERN;
private static final String PATTERN = "^" + TIME_RANGER_PATTERN + "(," + TIME_RANGER_PATTERN + "?)*$";
private static final Pattern pattern = Pattern.compile(PATTERN);

public static void main(String[] args) {
    String input = "09:00-10:00,12:00-14:30,16:00-18:00";
    if (pattern.matcher(input).matches()) {
        System.out.println("We have a match!");
    }
}

Explanation:

  • HOURLY_TIME_PATTERN is the pattern required for a single hour in a 24h format (e.g. 16:25)
  • TIME_RANGER_PATTERN is the pattern to find a single time range (e.g. 16:25-22:50)
  • PATTERN - is the pattern that ensure that we have at least 1 time range, and any other time range must be lead by a comma (we can have zero or more of them)

10 Comments

This would only find a single match, and wouldn't allow multiple values, as stated in the post.
oh, I though that each of them is separate input :) will fix the pattern
This regex it pretty complicated now, but it works...
Some parenthesis can be removed. And since the regex seems to be used only for validation, we could/should make the groups non-capturing. Furthermore, we can define "sub-patterns" through Strings to structure the pattern more, and then construct the final pattern through String concatenation.
One could split-up all of this even further. Ideone demo. @YonatanKarp-Rudin feel free to "steal" what you want if you want to add some.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.