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");
}
}
}
}