0

I'm trying to input a string with a mix of characters and have some bit of code remove all but the part that matches the desired SimpleDateFormat

String wholeString = new String("The time is 7:00.");
String timeOnlyString = CODE TO TRIM STRING;
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
Date timeAsObject = sdf.parse(timeOnlyString);
String timeAsString = sdf.format(timeAsObject);
System.out.println(timeAsString);`

With this code I'd like

07:00

Printed in the console.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Use regular expressions or if the wholeString is constant width use substring, – LMC Aug 20 '21 at 02:07
  • Assuming `CODE TO TRIM STRING` actually returns _7:00_, your code works for me. It prints _07:00_ to the console. What is your actual problem? Does your code throw an exception? Does it not print _07:00_ to the console? – Abra Aug 20 '21 at 02:12
  • `CODE TO TRIM STRING` should return 7:00, but I have no clue what code to put in there to actually make it do that. I just put it as a proxy to fill the example code. – CaptianBarouq Aug 20 '21 at 03:02
  • 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 `LocalTime` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Aug 20 '21 at 04:32

3 Answers3

2

java.time

I recommend that you use java.time, the modern Java date and time API, for your time work.

    String wholeString = "The time is 7:00.";
    Matcher m = TIME_PATTERN.matcher(wholeString);
    while (m.find()) {
        String timeOnlyString = m.group();
        try {
            LocalTime timeAsObject
                    = LocalTime.parse(timeOnlyString, TIME_FORMATTER);
            System.out.println("Time found: " + timeAsObject);
        } catch (DateTimeParseException dtpe) {
            System.out.println("Looked a bit like a time but couldn’t be parsed as one: " + timeOnlyString);
        }
    }

I used these two static declarations:

private static final Pattern TIME_PATTERN
        = Pattern.compile("\\b\\d{1,2}:\\d{2}\\b");
private static final DateTimeFormatter TIME_FORMATTER
        = DateTimeFormatter.ofPattern("H:mm");

Output from my snippet is:

Time found: 07:00

The regular expression that I use for extracting the time from the whole string matches 1 or 2 digits, a colon and 2 digits. It requires a word boundary before and after so we don’t happen to extract a time from 987:12354 or letters1:11moreletters.

The format pattern string used for the DateTimeFormatter has just one H for hour of day. This accepts 1 or 2 digits, so we can parse 15:00 too.

I think that we should take into account that the regex may match more than once in the string, so I am extracting in a loop.

I am parsing in to java.time.LocalTime. This class is for a time of day (from 00:00 through 23:59:59.999999999), so suits your need much better than the outdated Date class (which represents neither a date nor a time of day, but a point in time without time zone).

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
2

You can use the regex, .*?(\d{1,2}:\d{1,2}(?:\:\d{1,2}(?:\.\d{1,9})?)?).* to match the whole string and replace it with the pattern matched by group#1.

Description of the regex:

  • .*? : Matches (lazily) any character any number of times
  • (: Start of capturing group#1
    • \d{1,2}:\d{1,2} : One to two digits followed by one to two digits
    • (?: : Start of the optional non-capturing group
      • \:\d{1,2} : : followed by one to two digits (for seconds)
        • (?: : Start of the optional non-capturing group
          • \.\d{1,9} : . followed by one to nine digits (for nano seconds)
        • )? : Close of optional non-capturing group
    • )? : Close of optional non-capturing group
  • ) : Close of capturing group#1
  • .*: Matches any character any number of times

Demo:

public class Main {
    public static void main(String[] args) {
        // Test strings
        String[] wholeStringArr = { "The time is 7:00.", "The time is 7:00:05.", "The time is 7:00:05.1.",
                "The time is 7:00:05.123.", "The time is 7:00:05.123456789." };

        for (String wholeString : wholeStringArr) {
            String timeOnlyString = wholeString.replaceAll(".*?(\\d{1,2}:\\d{1,2}(?:\\:\\d{1,2}(?:\\.\\d{1,9})?)?).*",
                    "$1");
            System.out.println(timeOnlyString);
        }
    }
}

Output:

7:00
7:00:05
7:00:05.1
7:00:05.123
7:00:05.123456789

ONLINE DEMO

java.time

The java.util Date-Time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.

Solution using java.time, the modern Date-Time API:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String wholeString = "The time is 7:00.";
        String timeOnlyString = wholeString.replaceAll(".*?(\\d{1,2}:\\d{1,2}(?:\\:\\d{1,2}(?:\\.\\d{1,9})?)?).*",
                "$1");

        DateTimeFormatter dtf = DateTimeFormatter
                .ofPattern("H:m[:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]", Locale.ENGLISH);
        LocalTime time = LocalTime.parse(timeOnlyString, dtf);
        System.out.println(time);
    }
}

Output:

07:00

ONLINE DEMO

Notice the optional patterns in the square brackets.

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


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0
String wholeString = "The time is 7:00.";
Pattern pattern = Pattern.compile("(0?[1-9]|1[0-2]):[0-5][0-9]");
Matcher matcher = pattern.matcher(wholeString);
if(matcher.find()) {
    String timeOnlyString = matcher.group();
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
    Date timeAsObject = sdf.parse(timeOnlyString);
    String timeAsString = sdf.format(timeAsObject);
    System.out.println(timeAsString);
}
Saravanakrishnan Pk
  • 451
  • 1
  • 5
  • 15
  • 1
    It may help make the answer more clear if you explain that you are using a regular expression and how that expression works. Also, I think you should mention that, since Java 8, it is recommended **not** to use class `SimpleDateFormat`. – Abra Aug 20 '21 at 03:40