2

What is the best way to parse time that a user typed in a text field in GWT? Default time formats require users to enter time exactly as the time format for locale specifies it.

I want to be more flexible as there are many different ways users can enter time. For example, entries like "8", "8p", "8pm", "8.15pm", "13:15", "1315", "13.15" should be valid.

Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58

1 Answers1

3

I ended up with my own method that I want to share. This method returns time in milliseconds, which can be displayed using any data formats for the selected locale.

Any suggestions to improve it are highly appreciated.

EDIT: Improved following suggestions in comments.

public static Long parseTime(String value) {

    // ";" is a common typo - we are not punishing users for it
    value = value.trim().toLowerCase().replace(";", ":");

    RegExp time12 = RegExp.compile("^(1[012]|[1-9])([:.][0-5][0-9])?(\\s)?(a|p|am|pm)?$");
    RegExp time24 = RegExp.compile("^(([01]?[0-9]|2[0-3])[:.]?([0-5][0-9])?)$");

    if (time12.test(value) || time24.test(value)) {

        String hours = "0", minutes = "0";

        if (value.contains(":") || value.contains(".")) {
            String[] values = value.split("[:.]");
            hours =  values[0];
            minutes = values[1].substring(0, 2);
        } else {
            // Process strings like "8", "8p", "8pm", "2300"
            if (value.contains("a")) {
                hours = value.substring(0, value.indexOf("a")).trim();
            } else if (value.contains("p")) {
                hours = value.substring(0, value.indexOf("p")).trim();
            } else if (value.length() < 3) {
                hours = value;
            } else {
                hours =  value.substring(0, value.length() - 2);
                minutes = value.substring(value.length() - 2);
            }
        }
        if (value.contains("a") && hours.equals("12")) {
            // 12am is actually zero hours
            hours = "0";
        }

        Long time = (Long.valueOf(hours) * 60 + Long.valueOf(minutes)) * 60 * 1000;

        if (value.contains("p") && !hours.equals("12")) {
            // "pm" adds 12 hours to the total, except for 12pm
            time += 12 * 60 * 60 * 1000;
        }

        return time;
    }
    return null;
}
Andrei Volgin
  • 40,755
  • 6
  • 49
  • 58
  • 2
    You may want to replace `[:.;]?([0-5][0-9])?` with `([:.;]?[0-5][0-9])?`, or if you want to allow inputs like `"8:"`, you should handle a possible `ArrayIndexOutOfBoundsException`. You're also currently allowing inputs like "14 am". I guess you could either divide the regex with a `|`, or add a look-behind to the `(a|p|am|pm)` to avoid that. – Lone nebula May 22 '13 at 04:57
  • @Lone nebula Great suggestions. Thank you! I will edit the answer to reflect them. – Andrei Volgin May 22 '13 at 06:18