Problema com Data em Java

Boa noite pessoal. Caso esteja repetido peço desculpas. Estou tentando fazer uma lógica para que quando o usuário deixar o campo data em branco, retorne uma mensagem de erro, mas não estou conseguindo. Eu já transformei a data de Date para String e depois para inteiro. Estou usando os seguintes Imports:

import java.util.Date;
import java.util.Locale;
import java.util.Scanner;
import java.text.ParseException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

System.out.print(“Entre com a data de inicio (entrar com o padrão dd/MM/yyyy) :”);
dt_Inicio = sc.nextLine();

String dataEmUmFormato = (dt_Inicio);
DateFormat df = new SimpleDateFormat(“dd/MM/yyyy”);
Date dt = df.parse(dataEmUmFormato);
((SimpleDateFormat) df).applyPattern(“yyyyMMdd”);
String dataFormatada = df.format(dt);
int novaDt_Inicio = Integer.parseInt(dataFormatada);

Fiz a seguinte lógica:

if(dataFormatada.trim().isEmpty()){ // Já usei o null e o equals e não resolveu
System.out.println(“A data não pode ficar vazia”);
}

Quando eu deixo a data em branco e aperto enter, ele retorna erro.
erro [code]Unparseable date : “”

Se alguém puder me ajudar onde estou errando, eu agradeço.

Isso não funciona pois dataFormatada é o retorno do método format(), que não vai ser “vazio”.
Vc deveria fazer a verificação na variável “dt_Inicio”.

Boa noite e obrigado, mas também não funcionou na dt_inicio.

Você deu retorno dentro do if?

Hum. Não… Boa… Vou tentar e posto aqui. Obrigado mais uma vez.

return puro?

Dá essa msg de erro:

Exception in thread “main” java.text.ParseException: Unparseable date: “”
at java.base/java.text.DateFormat.parse(DateFormat.java:396)
at CadastraAnuncio.main(CadastraAnuncio.java:50)

E a verificação tem que ser antes de chamar o método parse()

Antes disso?
int novaDt_Inicio = Integer.parseInt(dataFormatada);

Me desculpa, pois sou novo em programação. Estou aprendendo tem pouco tempo.

Meu código está assim:

public class CadastraAnuncio {

public static void main(String[] args) throws ParseException{
	Locale.setDefault(Locale.US);
	Scanner sc = new Scanner(System.in); 
	
	String dt_Inicio, dt_Termino;
	double invest_Dia, tot_Investido;
	
	System.out.print("Entre com o nome do anúncio: ");
	String nom_Anuncio = sc.nextLine();	

	//Só sairá do loop quando digitar um anúncio
	
	while (nom_Anuncio.isEmpty()) {
		System.out.println("Favor digitar o anúncio!!!");
		nom_Anuncio = sc.nextLine();	
	}
	
	
	System.out.print("Entre com o nome do cliente: ");
	String cliente = sc.nextLine();
	
	// Só sairá do loop quando digitar o nome do cliente
	
	while (cliente.isEmpty()) {
		System.out.println("Favor digitar o nome do cliente!!!");
		cliente = sc.nextLine();
	}
	
	System.out.print("Entre com a data de inicio (entrar com o padrão dd/MM/yyyy) :");
	dt_Inicio = sc.nextLine();
		
	String dataEmUmFormato = (dt_Inicio);
	DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
	Date dt = df.parse(dataEmUmFormato);
	((SimpleDateFormat) df).applyPattern("yyyyMMdd");
	String dataFormatada = df.format(dt);
	
	if(dt_Inicio.trim().isEmpty()) {
		System.out.println("o campo não pode ficar vazio");
		return;
	}
	
	System.out.print("Entre com a data de termino (entrar com o padrão dd/MM/yyyy) :");
	dt_Termino = sc.nextLine();
	
	String novaDataEmUmFormato = (dt_Termino);
	DateFormat df2 = new SimpleDateFormat("dd/MM/yyyy");
	Date dt2 = df2.parse(novaDataEmUmFormato);
	((SimpleDateFormat) df2).applyPattern("yyyyMMdd");
	 String novaDataFormatada = df2.format(dt2);
	
	int novaDt_Inicio = Integer.parseInt(dataFormatada);
	int novaDt_Termino = Integer.parseInt(novaDataFormatada);
	
	
	if (novaDt_Inicio != novaDt_Termino) {
			System.out.print("Entre com o investimento do dia: R$ ");
			invest_Dia = sc.nextDouble();
			
			tot_Investido = (novaDt_Termino - novaDt_Inicio) * invest_Dia; // Cálculo valor total do dia
			System.out.printf("O total dos investimentos é : R$ %.2f%n " , tot_Investido);
	}else{
		
		// Data Inicial maior que a final
		
		System.out.println("");
		System.out.println("A data inicial não pode ser igual ou maior que a data final");
		System.out.println("");
		
		// Entrar novamente com os novos dados da data
		
		System.out.print("Entre com a nova data de inicio (entrar com o padrão dd/MM/yyyy) :");
		String dt_Inicio2 = sc.nextLine();
		
		String outraDataEmUmFormato = (dt_Inicio2);
		DateFormat ndf = new SimpleDateFormat("dd/MM/yyyy");
		Date ndt = ndf.parse(outraDataEmUmFormato);
		((SimpleDateFormat) ndf).applyPattern("yyyyMMdd");
		String outraDataFormatada = ndf.format(ndt);
		
		System.out.print("Entre com a nova data de termino (entrar com o padrão dd/MM/yyyy) :");
		String dt_Termino2 = sc.nextLine();
		
		String outraNovaDataEmUmFormato = (dt_Termino2);
		DateFormat ndf2 = new SimpleDateFormat("dd/MM/yyyy");
		Date ndt2 = ndf2.parse(outraNovaDataEmUmFormato);
		((SimpleDateFormat) ndf2).applyPattern("yyyyMMdd");
		String outraNovaDataFormatada = ndf2.format(ndt2);

		int novaDt_Inicio2 = Integer.parseInt(outraDataFormatada);
		int novaDt_Termino2 = Integer.parseInt(outraNovaDataFormatada);
		
		System.out.print("Entre com o investimento do dia: R$ ");
		invest_Dia = sc.nextDouble();
		
		tot_Investido = (novaDt_Termino2 - novaDt_Inicio2) * invest_Dia; // Cálculo valor total do dia
		System.out.printf("O total dos investimentos é : R$ %.2f%n " , tot_Investido);
	}
	sc.close();		
}

}

Antes dessa linha, que é a que está tendo o erro.

Algumas sugestões/considerações:


Usar Locale.setDefault muda o locale default para toda a JVM, e isso afeta todas as aplicações que estiverem rodando na mesma JVM (para um exercício, não faz diferença, mas para aplicações maiores compartilhando o ambiente com outras, isso pode causar problemas, ainda mais se cada aplicação precisar de um locale diferente).

Então prefira setar o locale nos objetos que precisam dele, por exemplo:

Scanner sc = new Scanner(System.in).useLocale(Locale.US);

Use as convenções de nomenclatura da linguagem, que prefere nomesAssim em vez de nomes_Assim.

Em vez de criar um SimpleDateFormat toda hora e ficar alterando o formato, crie apenas uma instância para cada formato e reuse-as. Outro detalhe é que SimpleDateFormat nem sempre valida corretamente o formato (exemplos), mas você pode forçar isso desligando o modo leniente. Então ficaria assim:

SimpleDateFormat dmy = new SimpleDateFormat("dd/MM/yyyy");
dmy.setLenient(false);
SimpleDateFormat ymd = new SimpleDateFormat("yyyyMMdd");
ymd.setLenient(false);

Aí, quando você precisar do formato dd/MM/yyyy, basta usar dmy, e quando precisar do formato yyyyMMdd, use ymd. Não precisa ficar criando outra instância toda hora, e nem setando o pattern. E para saber se a data digitada foi válida, você deve capturar a exceção para cada caso.

Mas sinceramente, não precisa do segundo formato. Você fez isso só para transformá-lo em int e poder “subtrair”, mas para calcular a diferença entre datas isso é completamente desnecessário. Até porque seu cálculo está completamente errado. Por exemplo, para as datas “31/12/2020” e “31/01/2021”, você acaba subtraindo 20210131 - 20201231, resultando em 8900 dias (mas a diferença entre essas datas é de 31 dias).

Então uma forma seria simplesmente usar as próprias datas para fazer o cálculo. E também não precisa ficar repetindo o código que lê as datas, use os loops a seu favor. Uma sugestão seria fazer assim:

public class CadastraAnuncio {
    private static final Scanner INPUT = new Scanner(System.in).useLocale(Locale.US);
    private static final SimpleDateFormat DMY;
    static {
        DMY = new SimpleDateFormat("dd/MM/yyyy");
        DMY.setLenient(false); // para validar corretamente as datas
    }

    static Date lerData(String mensagem) {
        while (true) { // enquanto a data for inválida, pede que digite novamente
            System.out.print(mensagem);
            try {
                // lê a string e já passa para parse, que retorna o Date
                return DMY.parse(INPUT.nextLine());
            } catch (ParseException e) {
                System.out.println("Digite uma data válida no formato indicado");
            }
        }
    }

    public static void main(String[] args) {
        Date dataInicio, dataFim;
        while (true) {
            dataInicio = lerData("Entre com a data de inicio (entrar com o padrão dd/MM/yyyy) :");
            dataFim = lerData("Entre com a data de termino (entrar com o padrão dd/MM/yyyy) :");
            if (dataInicio.before(dataFim)) {
                System.out.print("Entre com o investimento do dia: R$ ");
                double investDia = Double.parseDouble(INPUT.nextLine());
                long dias = (dataFim.getTime() - dataInicio.getTime()) / (1000 * 60 * 60 * 24);
                double totalInvestido = investDia * dias;
                System.out.printf("O total dos investimentos é : R$ %.2f%n ", totalInvestido);
                break; // sai do while
            } else {
                // se data inicial não é menor que a data final, mostra mensagem e volta pro início do while (aí vai pedir que digite novamente)
                System.out.println("\nA data inicial deve ser menor que a data final\n");
            }
        }
    }
}

Para a diferença, infelizmente Date não dá um modo mais preciso, então usei getTime(), que retorna a quantidade de milissegundos decorridas desde o Unix Epoch. Aí basta pegar a diferença em milissegundos e converter para dias.


Java >= 8

Se estiver usando Java >= 8, prefira usar a API java.time, muito mais moderna e simples, e também já possui métodos prontos para calcular a diferença entre as datas (no exemplo abaixo usei ChronoUnit). Ficaria assim:

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.time.format.ResolverStyle;
import java.time.temporal.ChronoUnit;
import java.util.Locale;
import java.util.Scanner;

public class CadastraAnuncio {
    private static final Scanner INPUT = new Scanner(System.in).useLocale(Locale.US);
    // usar ResolverStyle.STRICT para validar corretamente as datas
    private static final DateTimeFormatter DMY = DateTimeFormatter.ofPattern("dd/MM/uuuu").withResolverStyle(ResolverStyle.STRICT);

    static LocalDate lerData(String mensagem) {
        while (true) { // enquanto a data for inválida, pede que digite novamente
            System.out.print(mensagem);
            try {
                return LocalDate.parse(INPUT.nextLine(), DMY);
            } catch (DateTimeParseException e) {
                System.out.println("Digite uma data válida no formato indicado");
            }
        }
    }

    public static void main(String[] args) {
        LocalDate dataInicio, dataFim;
        while (true) {
            dataInicio = lerData("Entre com a data de inicio (entrar com o padrão dd/MM/yyyy) :");
            dataFim = lerData("Entre com a data de termino (entrar com o padrão dd/MM/yyyy) :");
            if (dataInicio.isBefore(dataFim)) {
                System.out.print("Entre com o investimento do dia: R$ ");
                double investDia = Double.parseDouble(INPUT.nextLine());
                // *** calcular diferença em dias ***
                long dias = ChronoUnit.DAYS.between(dataInicio, dataFim);
                double totalInvestido = investDia * dias;
                System.out.printf("O total dos investimentos é : R$ %.2f%n ", totalInvestido);
                break; // sai do while
            } else {
                // se data inicial não é menor que a data final, mostra mensagem e volta pro início do while (aí vai pedir que digite novamente)
                System.out.println("\nA data inicial deve ser menor que a data final\n");
            }
        }
    }
}

Obrigado Roinu. Vou tentar fazer e vê se parou o erro.

Boa tarde Hugo. Opa obrigado pela dica. O meu Java é acima do 8. Eu não tenho muito conhecimento dessa linguagem, por isso não usei o try e catch e nem API. Vou tentar fazer se se resolver o meu problema eu encerro o post.

Boa tarde Roinu. Obrigado. Funcionou da forma como vc falou. Eu refatorei o código conforme o Hugo me orientou.

1 curtida

Funcionou Hugo. Eu usei o seu exemplo e refatorei meu código seguindo suas dicas. Muito obrigado.

1 curtida