0

I am having a method which formats my particular data string

public static String dateFormatter(String dateToFormat){

        SimpleDateFormat dateParser = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);


        // All the fields in dateFormatter must be in dateParser
        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy, MMM d, EEE", Locale.UK);

        Date date = new Date();

        try {

            date = dateParser.parse(dateToFormat);

        } catch (ParseException e) {

            e.printStackTrace();

        }

        assert date != null;
        
        return dateFormatter.format(date);
    }

The issue am having is that the String date am parsing as dateToFormat can be in the following date format pattern

  1. 2021-03-02 which will use date format pattern of "yyyy-MM-dd" in dateParser
  2. 2021-03-02 20:16 which will use date format pattern of "yyyy-MM-dd HH:mm" in dateParser
  3. 2021-03-02 20:16:28 which will use date format pattern of "yyyy-MM-dd HH:mm:ss" in dateParser

I would like the dateParser to be assigned with an if statement instead of me going back to the code everytime to change so that the dateParser uses a particular format according to the date parsed for example

        SimpleDateFormat dateParser;

        if ("yyyy-MM-dd"){

            dateParser = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);

        }else if ("yyyy-MM-dd HH:mm") {

            dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK);

        }else if ("yyyy-MM-dd HH:mm:ss") {

            dateParser = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.UK);

        }

Where "yyyy-MM-dd" and "yyyy-MM-dd HH:mm" is the format pattern of the parsed String dateToFormat

Emmanuel Njorodongo
  • 1,004
  • 17
  • 35
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends. See if you either can use [desugaring](https://developer.android.com/studio/write/java8-support-table) or add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project, in order to use java.time, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Mar 05 '21 at 17:27

2 Answers2

0

Create 3 defferent formatter for yyyy-MM-dd, yyyy-MM-dd HH:mm, yyyy-MM-dd HH:mm:ss respectively formatter1, formatter2, formatter3

 private String dateFormatter(String dateToFormat) {
    Date date = null;
    SimpleDateFormat formatter1=new SimpleDateFormat("yyyy-MM-dd", Locale.UK);
    SimpleDateFormat formatter2=new SimpleDateFormat("yyyy-MM-dd HH:mm", Locale.UK);
    SimpleDateFormat formatter3=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.UK);
    try {
        try {
            date = formatter1.parse(dateToFormat);
        } catch (
                Exception exp) {
            try {
                date = formatter2.parse(dateToFormat);
            } catch (Exception exp2) {
                try {
                    date = formatter3.parse(dateToFormat);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
        }

        SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy, MMM d, EEE", Locale.UK);
        return dateFormatter.format(date);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
Ganesh Pokale
  • 1,538
  • 1
  • 14
  • 28
  • I there a way i can only use if statements so that i don't get to use many SimpleDateFormats @Ganesh Pokale – Emmanuel Njorodongo Mar 08 '21 at 03:35
  • @EmmanuelNjorogeOdongo it's possible If you can pass format(ex: yyyy-MM-dd) as function parameter ... then only one SimpleDateFormat is required – Ganesh Pokale Mar 08 '21 at 08:39
  • The Issue @Ganesh Pokale is that the date come from the server where i dont have control they may come in various date time patterns – Emmanuel Njorodongo Mar 08 '21 at 14:43
  • I thing then there is no option! you have to create multiple date formats – Ganesh Pokale Mar 10 '21 at 10:30
  • I think this link [ https://stackoverflow.com/questions/4024544/how-to-parse-dates-in-multiple-formats-using-simpledateformat ] explains how to check all the date formats using a for loop implementing this in your answer solution will make the solution one of the best in StackOverflow @Ganesh Pokale – Emmanuel Njorodongo Mar 11 '21 at 09:03
0

java.time and optional parts of the format pattern

Consider using java.time, the modern Java date and time API, for your date work. The following method does it. Since with java.time there is no reason to create the formatters anew for each call, I have placed them outside the method.

private static final DateTimeFormatter inputParser
        = DateTimeFormatter.ofPattern("uuuu-MM-dd[ HH:mm[:ss]]");
private static final DateTimeFormatter outputFormatter 
        = DateTimeFormatter.ofPattern("uuuu, MMM d, EEE", Locale.UK);

public static String dateFormatter(String dateToFormat){
    LocalDate date = LocalDate.parse(dateToFormat, inputParser);
    return date.format(outputFormatter);
}

Try it out:

    System.out.println("2021-03-02          -> " + dateFormatter("2021-03-02"));
    System.out.println("2021-03-02 20:16    -> " + dateFormatter("2021-03-02 20:16"));
    System.out.println("2021-03-02 20:16:28 -> " + dateFormatter("2021-03-02 20:16:28"));

Output is:

2021-03-02          -> 2021, Mar 2, Tue
2021-03-02 20:16    -> 2021, Mar 2, Tue
2021-03-02 20:16:28 -> 2021, Mar 2, Tue

The square brackets in the format pattern string for the input parser denote optional parts. So the time of day is allowed to be there or not. And if it’s there, the seconds are allowed to be present or absent.

This said, you should not want to process your date and time as strings in your app. Process a LocalDate, or if there’s any possibility that you will need the time of day, then for example a ZonedDateTime. When you get string input, parse it first thing. And only format back into a string when you must give string output.

With if statements

can your find a way that i can use SimpleDateFormat

I would not want to do that. The SimpleDateFormat class is a notorious troublemaker of a class and fortunately long outdated

I there a way i can only use if statements so that i don't get to use many SimpleDateFormats

It doesn’t get you fewer formatters, but you may use if statements. Just select by the length of the string;

public static String dateFormatter(String dateToFormat){
    LocalDate date;
    if (dateToFormat.length() == 10) { // uuuu-MM-dd
        date = LocalDate.parse(dateToFormat, dateParser);
    } else if (dateToFormat.length() == 16) { // uuuu-MM-dd HH:mm
        date = LocalDate.parse(dateToFormat, dateTimeNoSecsParser);
    } else if (dateToFormat.length() == 19) { // uuuu-MM-dd HH:mm:ss
        date = LocalDate.parse(dateToFormat, dateTimeWithSecsParser);
    } else {
        throw new IllegalArgumentException("Unsupported length " + dateToFormat.length());
    }
    return date.format(outputFormatter);
}

Only now we need to declare four formatters, three for parsing and one for formatting. I am leaving constructing the parsers to yourself.

I guess that the same if-else strucure will work with SimpleDateFormat too. You may even just select the format pattern string from the length of the input string and only construct one SimpleDateFormat instance in each call of the method. I repeat: I would not myself use SimpleDateformat.

Question: Doesn’t java.time require Android API level 26?

Call requires API level 26 (current min is 16): java.time.format.DateTimeFormatter#ofPattern

Edit: Contrary to what you might think from this error message java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • DateTimeFormatter.ofPattern requires API level 26 and above mine is only 16 can your find a way that i can use SimpleDateFormat @Ole V.V. Call requires API level 26 (current min is 16): java.time.format.DateTimeFormatter#ofPattern – Emmanuel Njorodongo Mar 08 '21 at 03:32
  • Have you looked into desugaring or into ThreeTenABP as I have described in the answer? – Ole V.V. Mar 08 '21 at 06:07