Why does my program only work if I avoid parse Try catch?

Asked

Viewed 138 times

2

I get a date from SQLITE but cannot understand where the error is, it is simply not visible.

String dateValue = empDatadevolucao.getText()
        .toString()
        .trim();

SimpleDateFormat ft = new SimpleDateFormat("dd/MM/yyyy");

//>> int date = Integer.parseInt(empDatadvl.getText().toString());
Date date = null;
try {
    date = ft.parse(dateValue);
} catch (ParseException e) {
    e.printStackTrace();
}

Calendar renova = Calendar.getInstance();
//Somente comentando renova.setTime(date); para evitar que caia no try catch do date = ft.parse(dataValue)

renova.setTime(date); 
renova.add(Calendar.DATE, 1);
date = renova.getTime();
String strDate = ft.format(date);

final TextView newDate =  findViewById(R.id.exibeData);
newDate.setText(strDate);

But if I comment it captures the calendar date, it does not format and parse. Delivers something like that:

data atual     15 abr 2019 
data renovação 16 abr 2019

Since the expected was for him to take the value of empDatadevolucao, showing 20/04/2019 and adding another day renova.add(Calendar.DATE, 1); (21/04/2019).

  • How does this dateValue return the date? I tested here with dateValue being "20/04/2019" and I’m sure the code, is returning in strDate "21/04/2019"

  • I receive the date so 15 Apr 2019

  • Hmm understood, the problem is in the abbreviated month name, coming home I send the right way to convert. Hence 1 hr more or less

1 answer

6


There’s no way the setTime fall into the try/catch of parse, for the call of setTime, besides afterward, is out of of try/catch.

What happens is this: dateValue contains the String "15 Apr 2019" (as per your comment). The SimpleDateFormat is using the format dd/MM/yyyy (day/month/year) - the detail is that in addition to the bars, MM corresponds to the numeric value of the month, but its string contains the name of the month ("abr"). Therefore parse makes a mistake.

In giving ParseException, you print the exception (e.printStackTrace()), but the code keeps running. And how it got error in parse, the variable date is null, and as we pass null for setTime, the result is another exception (in case, a NullPointerException).

That is, the setTime gives another error. He is not returning to the try/catch. The problem with this code is that ParseException, you keep running the rest. But if error occurs in parse, means that you failed to create the Date, then you shouldn’t go on.

One way to fix this is to put the entire code pad inside the try, and in the catch you place some error message saying that it was not possible to get the date.

Already to the date format (assuming the string you pass to the method parse be "15 Apr 2019"), you must change the format to use MMM instead of MM, as it will take the name of the abbreviated month (as stated in documentation). And as the name of the month is in Portuguese, use also a java.util.Locale to set the language to Portuguese:

SimpleDateFormat ft = new SimpleDateFormat("dd MMM yyyy", new Locale("pt", "BR"));
Date date = null;
try {
    date = ft.parse("15 abr 2019");
    Calendar renova = Calendar.getInstance();
    renova.setTime(date);
    ... some 1 dia, como já está fazendo
} catch (ParseException e) {
    // erro ao criar o Date, exiba alguma mensagem de erro
}

If you do not specify a Locale, will be used the default locale of the JVM, and it is not always guaranteed to be Portuguese. If you want to do Parsing of a string and already know what language it is in, it is better to pass the Locale corresponding to SimpleDateFormat.

If the format is 20 de abr de 2019, for example, just switch to:

SimpleDateFormat ft = new SimpleDateFormat("dd 'de' MMM 'de' yyyy", new Locale("pt", "BR"));

The text de should be between single quotes, so the letter d is not interpreted as the day, but as the character itself d.


java.time

From the Level 26 API (required minSdkVersion>=26, it is not enough to have compileSdkVersion>=26), it is possible to use the bundle java.time, the new Java date API, much higher than the Date and Calendar.

For the date, you can use a java.time.LocalDate, a class that represents only the day, month and year (which is exactly what you need). And to transform a String on a date, use a java.time.format.DateTimeFormatter:

import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.LocalDate;
import java.util.Locale;

DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // aceitar nome do mês em minúsculo
    .parseCaseInsensitive()
    // dia mês ano
    .appendPattern("dd MMM uuuu")
    // usar Locale para idioma português
    .toFormatter(new Locale("pt", "BR"));
LocalDate date = LocalDate.parse("15 abr 2019", fmt);
date = date.plusDays(1); // soma 1 dia
String strDate = fmt.format(date);

I used parseCaseInsensitive() because in some versions of the JVM the Portuguese months may be with the first capital letter, so it is interesting to use this option for the Parsing be done correctly.

Also note the use of uuuu instead of yyyy for the year. For a more detailed explanation about this (and about the API in general), take a look at in this question.

For the format 20 de abr de 2019, just change the line that has the Pattern for:

.appendPattern("dd 'de' MMM 'de' uuuu")

Under API Levels < 26, you can use Threeten Backport, an excellent backport of java.time. Most of the features of Java 8 are present, with some differences: instead of being in the package java.time, classes are in the package org.threeten.bp. See here how to set it up for Android.

  • 1

    That’s exactly what I was going to propose.

  • These tips were excellent, but I’m in API levels 22 as quoted is from 26. then I will have to wait for me to normalize the whole code all first and then make these fixes.

  • @user3873165 In fact, the first code I suggested with SimpleDateFormat you can use. What is exclusive of the 26 is the java.time, which replaces Date and Calendar :-)

  • referenced setTime because it uses an object of parse --> date = ft.parse(dateValue); if it parses, everything ok, if it does not, deviation, error, npe, etc...

  • @user3873165 But that’s what I said, if the parse gave error, there is no reason to continue the rest of the code, because you will not have a Date valid... It is better to show an error message saying that you could not read the date or something like that

  • yes, perfect, in that sense I just have to thank, but this is really the reason I’m here working together with the code, in fact an update of IDE Android Studio forced me to look for current solutions to my problems. Some functions were no longer working so I’m swapping one by one.

  • I really get the date as sql - en: 15 apr 2019

  • error: java.text.Parseexception: Unparseable date: "Apr 20, 2019"

  • @user3873165 I updated the answer. But basically, the format you pass to SimpleDateFormat always match the string you are passing to parse

Show 4 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.