Just to complement the other answers, it’s worth explaining why it’s better to use a date API instead of manipulating the string directly.
First because, in addition to giving more work, string manipulation does not guarantee that the date is valid (neither the one you receive, nor the final result).
For example, if the month is January (01
) and you simply subtract 1, the result will be zero, so the initial date was 09/01/2020
, the result would be something like 09/00/2020
. That is, a completely invalid date.
What if the initial date was 31/03/2020
? When subtracting 1 of the month, the result would be 31/02/2020
(February 31, completely wrong).
Of course you can even make the proper adjustments manually, but there are already date Apis to deal with these cases for you. The other advantage is that this same API also validates the date, which ensures that you will know if you pass an invalid date:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
...
String data = "09/04/2021";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/uuuu")
.withResolverStyle(ResolverStyle.STRICT);
// faz o parsing da data e subtrai 1 mês
LocalDate dt = LocalDate.parse(data, fmt).minusMonths(1);
String dataFinal = fmt.format(dt);
System.out.println(dataFinal); // 09/03/2021
I used ResolverStyle.STRICT
so that it accepts only valid dates. Without this, the behavior default is accept dates like April 31st (which is automatically adjusted to April 30th, see here an example). Using the mode STRICT
, April 31 launches an exception (DateTimeParseException
, that you can put in a block try
/catch
if you want).
I also used uuuu
instead of yyyy
next year, read here to know the difference.
It is worth remembering that date arithmetic is "bizarre" and often counter-intuitive. For example, if the date is March 31, 2020, the result of subtracting 1 month is February 29, 2020 (as February does not have 31 days, the adjustment is made for the last day of the month). The same is true if we subtract 1 month from 29 or 30 March 2020, the result will also be 29 February 2020 (and if the year was not leap, the adjustment would be made for the 28th).
If you want different results, you will have to adjust manually, because this is the way the API does the calculations.
Java <= 7
The above code holds for Java >= 8, as the API java.time
does not exist in previous versions.
For Java 6 and 7, you can use Threeten Backport, which is a backport of java.time
. Basically, it has the same classes and methods, the difference is that they are in the package org.threeten.bp
, instead of java.time
. More details at the end of this answer.
But if you don’t want to use an external library, one option is to use the old API: java.util.Date
, java.util.Calendar
and java.text.SimpleDateFormat
.
String data = "09/04/2021";
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
sdf.setLenient(false); // para não aceitar datas inválidas
Calendar cal = Calendar.getInstance();
cal.setTime(sdf.parse(data));
cal.add(Calendar.MONTH, -1); // subtrai 1 mês
String dataFinal = sdf.format(cal.getTime());
System.out.println(dataFinal); // 09/03/2021
I used setLenient(false)
not to accept invalid dates (otherwise 31 April is set to 1 May). In the non lenient mode, invalid dates throw a java.text.ParseException
.
Use the package classes
time
. Basically, take the String and convert toLocalDate
, Remove required amount, then convert to String again.– user201641