-3

I have input time string which indicates time in various formats, like "1PM" (format is: hha), "1300" (format is: kkmm) and I want to convert it into a single format, say "1300" (kkmm).

How can I know what the format of the input time string is (hha or kkmm, etc.)?

I know how to convert it into a desired format, but I'm struggling to know the format of input string.

    String inputTime = '1PM';
    SimpleDateFormat inputFormat = new SimpleDateFormat('hha');
    SimpleDateFormat outputFormat = new SimpleDateFormat('kkmm');

    Date date = inputFormat.parse(inputTime);

    String output = outputFormat.format(date);

OUTPUT is: 1300.

Here, I'm passing input format as 'hha' in first line of code. I want to avoid that and extract time format from the inputTime string.

Dinesh
  • 35
  • 9
  • you want to check if string contains hha or kkmm? – Lalit Verma Dec 03 '17 at 10:23
  • Could you clarify which parts of your question are actual strings and which parts are descriptions? For example, use backticks - \`hello\` -> `hello`. Your expected output doesn't seem to match the inputs, which is a little unhelpful. Have you tried simply checking what the strings contain? Or, if you need to match a *pattern*, have you considered regular expressions? – jonrsharpe Dec 03 '17 at 10:25
  • 1
    I have attempted to clarify, please review and ensure my interpretation is correct. Also, please add a [mcve] of your current implementation that illustrates your specific problem. – jonrsharpe Dec 03 '17 at 10:29
  • @jonrsharpe Thanks for the edit. I have attached my code. I hope it is clear now. – Dinesh Dec 03 '17 at 10:41
  • And what have *you tried?* For example, think about what the differences are if you run `inputFormat.parse("1300")` vs. `inputFormat.parse("1PM")`, and how you could use that to decide what to do next. Do you just support those two formats, or are you trying something broader (and correspondingly more complex)? – jonrsharpe Dec 03 '17 at 10:43
  • If I pass 1300, java.text.ParseException will be thrown because I have given dateformat as "hha" to SimpleDateFormat inputFormat = new SimpleDateFormat('hha'); – Dinesh Dec 03 '17 at 10:48
  • @jonrsharpe I want to accept any time format from user and convert it into kkmm. – Dinesh Dec 03 '17 at 10:59
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/160374/discussion-between-dinesh-and-jonrsharpe). – Dinesh Dec 03 '17 at 11:03
  • 1
    Then see e.g. https://stackoverflow.com/q/3389348/3001761, https://stackoverflow.com/q/4024544/3001761. And no, thank you. – jonrsharpe Dec 03 '17 at 11:04
  • Those are very useful links, @jonrsharpe. – Ole V.V. Dec 03 '17 at 15:38
  • There are basically two ways: (1) Make a simple test to determine which format to use; for example, if the string ends in `M`, use `hha`, otherwise `HHmm`. (2) Try each possible format in turn, catch any exception and see which one doesn’t throw any. Take care to check if you have two formats that may match the same input. – Ole V.V. Dec 03 '17 at 15:42
  • And why are you using the troublesome and long outdated `SimpleDateFormat` class? Your best first step would be to throw it out. Instead use `LocalTime` and `DateTimeFormatter` from [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). That API is much nicer to work with. – Ole V.V. Dec 03 '17 at 15:54

1 Answers1

1

java.time

Is there any particular reason why are you using the troublesome and long outdated SimpleDateFormat class? Your best first step would be to throw it out. Instead use LocalTime and DateTimeFormatter from java.time, the modern Java date and time API. That API is much nicer to work with.

There are basically two ways to go about your problem. I will present them in turn using java.time.

Option 1: look at the string and decide its format

Make a simple test to determine which format to use; for example, if the string ends in M, use ha, otherwise Hmm.

private static DateTimeFormatter formatterWithAmPm
        = DateTimeFormatter.ofPattern("ha", Locale.ENGLISH);
private static DateTimeFormatter formatterWithMinutes
        = DateTimeFormatter.ofPattern("Hmm");

public static LocalTime parseTime(String inputTime) {
    if (inputTime.endsWith("M")) {
        return LocalTime.parse(inputTime, formatterWithAmPm);
    } else {
        return LocalTime.parse(inputTime, formatterWithMinutes);
    } 
}

I was frankly surprised to see that format pattern string Hmm parses 123 as 01:23 and 1234 as 12:34, but it’s very convenient.

I think this option lends itself best to few constant formats. It wouldn’t be too easy to extends with further formats at a later time.

Option 2: try all relevant formats until one works

Try each possible format in turn, catch any exception and see which one doesn’t throw any.

private static final DateTimeFormatter[] parseFormatters
        = Arrays.asList("ha", "Hmm") // add more format pattern strings as required
            .stream()
            .map(fps -> DateTimeFormatter.ofPattern(fps, Locale.ENGLISH))
            .toArray(DateTimeFormatter[]::new);

public static LocalTime parseTime(String inputTime) {
    DateTimeParseException aCaughtException = null;
    for (DateTimeFormatter formatter : parseFormatters) {
        try {
            return LocalTime.parse(inputTime, formatter);
        } catch (DateTimeParseException dtpe) {
            aCaughtException = dtpe;
            // otherwise ignore, try next formatter
        }
    }
    throw aCaughtException; 
}

Take care to check if you have two formats that may match the same input and yield different results. This also means that you cannot distinguish all thinkable formats in this way. It’s not too unreasonable to imagine a format where 1300 means minute 1300 of the day, that is 21:40. It could even mean second 1300 of the day, 00:21:40.

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