How to change dynamically date format

Viewed 1137

I have a problem with time format.Some time I have values in hh:mm:ss and some times in mm:ss format.

My code looks like:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String time = "01:48:00"
Date remainedTimeDate = sdf.parse(time);

It works, when I got format hh:mm:ss but when I have time in format mm:ss I got an error like, value can not be parsed. Is it possible to dynamically change date format?

3 Answers

There is no in-built feature in the date-time API to do so. Moreover, the legacy date-time API (java.util date-time types and their formatting API, SimpleDateFormat) are outdated and error-prone. It is recommended to stop using them completely and switch to java.time, the modern date-time API* .

You can match the string with the regex pattern, \d{1,2}:\d{1,2} which means one or two digits separated by a colon. If the match is successful, prepend 00: to the string to convert it into HH:mm:ss format.

Demo:

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Optional;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] arg) {
        // Test
        Stream.of(
                    "01:48:00", 
                    "48:00"
        ).forEach(s -> parseToTime(s).ifPresent(System.out::println));
    }

    static Optional<LocalTime> parseToTime(String s) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("H:m:s");
        if (s.matches("\\d{1,2}:\\d{1,2}")) {
            s = "00:" + s;
        }
        LocalTime time = null;
        try {
            time = LocalTime.parse(s, dtf);
        } catch (DateTimeParseException e) {
            System.out.println(s + " could not be parsed into time.");
        }
        return Optional.ofNullable(time);
    }
}

Output:

01:48
00:48

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.

java.time.Duration

Assuming that your string denotes an amount of time (for example, a duration), the right class to use for it in Java is Duration from java.time, the modern Java date and time API. Unfortunately Duration cannot parse your strings out of the box. It has a parse method that only accepts ISO 8601 format. ISO 8601 format for a duration goes like for example PT1H48M30S. It looks unusual at first, but is straightforward to read when you know how. Read the example just given as a period of time of 1 hour 48 minutes 30 seconds. So to parse your strings in hh:mm:ss and mm:ss format I first convert them to ISO 8601 using a couple of regular expressions.

    // Strings can be hh:mm:ss or just mm:ss
    String[] examples = { "01:48:30", "26:57" };
    for (String example : examples) {
        // First try to replace form with two colons, then form with one colon.
        // Exactly one of them should succeed.
        String isoString = example.replaceFirst("^(\\d+):(\\d+):(\\d+)$", "PT$1H$2M$3S")
                .replaceFirst("^(\\d+):(\\d+)$", "PT$1M$2S");
        Duration dur = Duration.parse(isoString);
        System.out.format("%8s -> %-10s -> %7d milliseconds%n", example, dur, dur.toMillis());
    }

In addition my code also shows how to convert each duration to milliseconds. Output is:

01:48:30 -> PT1H48M30S -> 6510000 milliseconds
   26:57 -> PT26M57S   -> 1617000 milliseconds

Links

Yeah you can do that. Based on an If Condition like Say, If the Hour and Min are in Smaller Case, you can change the constructor. But Please know that simple date format is not thread safe. Either make method as synchronized or lock the Simple Date Format object.

Related