Andry
Andry

Reputation: 383

Java Android Studio - Unparseable date error on phisycal device with Android 10

This part of code make a sort of conversion from an input like "January 1, 2020" to "01/01". The whole code works perfectly on devices with Android up to Pie and in AVD with devices with Q and R too. When I try to run it on phisycal Android devices with Android Q it doesn't run (I tried with 2 different devices a Mi Note 10 and a OnePlus 6T). I did a check on the debugger and I found this error as soon as it go in the IF loop (I think in the instruction: @SuppressLint("SimpleDateFormat") SimpleDateFormat dt = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");"

W/System.err: java.text.ParseException: Unparseable date: "Thu Nov 05 00:00:00 GMT+01:00 2020"

       String[] mese = new String[] {"January","February","March","April","May","June","July","August","September","October","November","December"};
       int a= 0 ;

       while (a < 12){ 
                    if(dato.contains(mese[a])){ 
                             System.out.println("Test 3");
                             DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
                             Date date = format.parse(dato);
                             @SuppressLint("SimpleDateFormat") SimpleDateFormat dt = new SimpleDateFormat("E MMM dd HH:mm:ss z yyyy");
                             Date date2 = dt.parse(String.valueOf(date));
                             @SuppressLint("SimpleDateFormat") SimpleDateFormat dt1 = new SimpleDateFormat("dd/MM");
                             assert date2 != null;
                             dato = dato.replaceAll(dato,dt1.format(date2));
                    }
                    a++;
                }

my pattern is wrong? I tried EEE MMM dd HH:mm:ss zzz yyyy and EEE MMM dd HH:mm:ss zzzz yyyy but same results

Upvotes: 0

Views: 773

Answers (2)

Anonymous
Anonymous

Reputation: 86296

java.time and desugaring or ThreeTenABP

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

java.time formatters are thread-safe, so we often prefer to declare them static:

private static final DateTimeFormatter sourceFormatter
        = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
private static final DateTimeFormatter targetFormatter
        = DateTimeFormatter.ofPattern("dd/MM");

Now your conversion goes like this:

    String dato = "November 5, 2020";
    LocalDate date = LocalDate.parse(dato, sourceFormatter);
    dato = date.format(targetFormatter);
    System.out.println(dato);

Output:

05/11

What went wrong in your code?

It seems to me that you were doing your format conversion in a way that was more complicated than needed. Rather than checking if there’s a month name in the string, why not just try to parse it? If there wasn’t, my code would throw a DateTimeParseException which you may then catch and handle the way that is appropriate to your situation. Your code was converting your String to Date to String to Date again and to String again. I didn’t understand the reason. Also you were using the SimpleDateFOrmat class. It is notoriously troublesome and long outdated. The second time you parsed from String to Date failed, and I bet I know why: For your first SimpleDateFormat you had remembered to specify Locale.ENGLISH, but you forgot on your second SimpleDateFormat. The string contained Thu and Nov in English, so if your Android Q and R devices had a different language setting, this explains. Finally for your purpose this line:

    dato = dato.replaceAll(dato,dt1.format(date2));

is the same as the simpler:

    dato = dt1.format(date2);

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

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. The latter is called ThreeTenABP. When using ThreeTenABP make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Upvotes: 1

Andry
Andry

Reputation: 383

I solved in this way not using anymore SimpleDateFormat:

         while (a < 12){
                    if(dato.contains(mese[a])){

                        String dateInString = dato;
                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
                        LocalDate dateTime = LocalDate.parse(dateInString, formatter);
                        DateTimeFormatter f2 = DateTimeFormatter.ofPattern("dd/MM");
                        String newDate = dateTime.format(f2);
                        dato = dato.replaceAll(dato,newDate);

                    }
                    a++;
                }

Upvotes: 1

Related Questions