61

I have a date of type java.util.Date

I want to subtract three months from it.

Not finding a lot of joy in the API.

Daniel Rikowski
  • 71,375
  • 57
  • 251
  • 329
AJM
  • 32,054
  • 48
  • 155
  • 243
  • 9
    You are not going to find a lot of joy with Java's date/time API because it's one of the worst in the JDK (performance, threading, illogical, ...). I recommend Joda Time as a replacement. This library is heavily influencing the new date/time JSR-310 that will be added to Java either in Java 7 or later. – SteveD Aug 21 '09 at 10:34

11 Answers11

120

Here's the plain JDK version, it needs the Calendar class as a helper:

Date referenceDate = new Date();
Calendar c = Calendar.getInstance(); 
c.setTime(referenceDate); 
c.add(Calendar.MONTH, -3);
return c.getTime();

But you should seriously consider using the Joda library, because of various shortcomings of the Date and Calendar classes. With Joda you can do the following:

new DateTime().minusMonths(3).toDate();

Or if you want to subtract from a given date instead of the current:

new DateTime(referenceDate).minusMonths(3).toDate();

Update for Java 8: With Java 8 you can also use the new JSR 310 API (which is inspired by Joda):

LocalDateTime.from(referenceDate.toInstant()).minusMonths(3);
Daniel Rikowski
  • 71,375
  • 57
  • 251
  • 329
17
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.MONTH, -3);

Set your date using setTime method.

bluish
  • 26,356
  • 27
  • 122
  • 180
firstthumb
  • 4,627
  • 6
  • 35
  • 45
  • 2
    "set your date using setTime method" - and in that simple sentence is the summation of all that is wrong with java.util.Date :-) – Brian Agnew Aug 21 '09 at 11:26
  • @Firstthumb: The most important problems is that Date is not immutable. The setter shows that problem. But contrary to Brian's comment there are other problems. See the Joda site for some explanations on why they created the Joda library. – Daniel Rikowski Aug 21 '09 at 12:11
  • 2
    java.util.Date is standard for java. You are right. Its performance is not good. But I insist on that my answer is one of the solutions to AJM's question – firstthumb Aug 21 '09 at 12:19
7

Using Java 8 you can do it like this,

Date d = Date.from(LocalDate.now().minusMonths(3).atStartOfDay(ZoneId.systemDefault()).toInstant());

The LocalDate class has a lot of methods to help you make easy computations about dates like the above,

// Add 2 months
Date d = Date.from(LocalDate.now().plusMonths(2).atStartOfDay(ZoneId.systemDefault()).toInstant());
// Add 5 days
Date d = Date.from(LocalDate.now().plusDays(5).atStartOfDay(ZoneId.systemDefault()).toInstant());
// Minus 1 day and 1 year
Date d = Date.from(LocalDate.now().minusYears(1).minusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant());

In order to compute time you can use the LocalDateTime class,

// Minus 1 year, minus 1 days, plus 1 hour
Date d = Date.from(LocalDateTime.now().minusYears(1).minusDays(1).plusHours(1).toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant());
Georgios Syngouroglou
  • 18,813
  • 9
  • 90
  • 92
4

I always recommend Joda for this sort of stuff. It has a much nicer API, and doesn't suffer from threading issues that the standard Java date/time has (e.g. issues with SimpleDateFormat, or general mutability).

e.g.

DateTime result = dt.minusMonths(3);
Brian Agnew
  • 268,207
  • 37
  • 334
  • 440
3

You want today - 3 Month formatted as dd MMMM yyyy

     SimpleDateFormat format = new SimpleDateFormat("dd MMMM yyyy");

     Calendar c = Calendar.getInstance(); 
     c.setTime(new Date()); 
     c.add(Calendar.MONTH, -3);

     Date d = c.getTime();
     String res = format.format(d);

     System.out.println(res);

So this code can do the job ;)

Valentin Montmirail
  • 2,594
  • 1
  • 25
  • 53
3

Ok with java.sql.Date (subclass of java.util.Date) and JDK's 8 LocalDate help you can do it in one line ;)

Date date = java.sql.Date.valueOf(LocalDate.now().minus(3, ChronoUnit.MONTHS));
Patrik Bego
  • 4,009
  • 1
  • 26
  • 24
2

The Date class itself isn't enough (+: You've got to use the Calendar class here

Something along these lines

GregorianCalendar lCalendar = new GregorianCalendar();
lCalendar.setTime( aDate );
lCalendar.add(Calendar.MONTH, -3);

p.s. the snippet above is not tested to be compilable.

Everyone
  • 2,366
  • 2
  • 26
  • 39
  • 3
    Is there a reason why you do GregorianCalendar lCalendar = new GregorianCalendar(); instead of Calendar lCalendar = Calendar.getInstance()? – Jesper Aug 21 '09 at 10:48
  • Instantiating GregorianCalendar directly shows certain knowledge of the inner-workings of the java.util.Calendar. However, to obtain your calendar via the factory Calendar.getInstance() automatically provides the best-fitting calendar based on important information about your location. If that be a GregorianCalendar, then a GregorianCalendar you shall get. The factory, therefore, is the more versatile approach. – Stephen Isienyi Apr 26 '16 at 15:38
1
public static Date getDateMonthsAgo(int numOfMonthsAgo)
{
    Calendar c = Calendar.getInstance(); 
    c.setTime(new Date()); 
    c.add(Calendar.MONTH, -1 * numOfMonthsAgo);
    return c.getTime();
}

will return the date X months in the past. Similarily, here's a function that returns the date X days in the past.

public static Date getDateDaysAgo(int numOfDaysAgo)
{
    Calendar c = Calendar.getInstance(); 
    c.setTime(new Date()); 
    c.add(Calendar.DAY_OF_YEAR, -1 * numOfDaysAgo);
    return c.getTime();
}
TheWestIsThe...
  • 442
  • 4
  • 14
0

You can use Apache Commons Lang3 DateUtils addMonths function.

static Date addMonths(Date date, int amount)

Adds a number of months to a date returning a new object. The original Date is unchanged. The amount to add, may be negative, so you can go 3 months back.

Robert Niestroj
  • 15,299
  • 14
  • 76
  • 119
0

You can use

Date d1 = new Date()
d1.setMonth(d1.month-3)

Hope this helps

0

String startDate="15/10/1987";

    Date date = new SimpleDateFormat("dd/MM/yyyy").parse(startDate);
    String formattedDate = new SimpleDateFormat("yyyy-MM-dd").format(date);
    LocalDate today = LocalDate.parse(formattedDate);
    String endDate=today.minusMonths(3).toString();
prasad
  • 11
  • 1