3

I am trying to get previous 12 month into an arraylist, from the given month(taken from DB).

List<String> allDates = new ArrayList<String>();    

sqlQuery="select max(date) from Table_Name";

maxDate="Jan-2016"; (Result from Query);

To get previous 12 months from maxDate,where i use SimpleDateFormat.

I want to calculate the previous 12 months from Given Month (maxDate), not from current month, i tried the following code.

//  Parsing maxDate to an integer (say Jan-2016 = 0, Feb-2016= 1)
Date date = new SimpleDateFormat("MMM-yyyy").parse(maxDate);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int month=cal.get(Calendar.MONTH);
        System.out.println("month : "+month);

// Looping to get previous 12 months from current month.
SimpleDateFormat month_date = new SimpleDateFormat("MMM-yyyy");
          for (int i = 12; i > 0; i--) {
                Calendar calendar1 = Calendar.getInstance();
                calendar1.add(Calendar.MONTH, -i);
                String month_name1 = month_date.format(calendar1.getTime());
                allDates.add(month_name1);
            }
            System.out.println(allDates);

Since months are numbered from (0 - 11) i couldn't achieve it. Please suggest an idea to calculate previous 12 months from given month. Appreciate your help!

Disera
  • 208
  • 3
  • 15
  • Do they need to be in descending order? Can you take away a year, then iterate forwards in time? Also, what type of object is `allDates` ? – Clark Kent Mar 04 '16 at 13:51
  • I need it to be in descending order so that i can get previous 12 months. `allDates` here is an `ArrayList`. I need to add those 12 months to allDates. – Disera Mar 04 '16 at 13:57

3 Answers3

7

The problem is that in the loop you base the computation always from current date not from maxDate.

List<String> allDates = new ArrayList<>();
String maxDate = "Jan-2016";
SimpleDateFormat monthDate = new SimpleDateFormat("MMM-yyyy");
Calendar cal = Calendar.getInstance();
cal.setTime(monthDate.parse(maxDate));
for (int i = 1; i <= 12; i++) {
    String month_name1 = monthDate.format(cal.getTime());
    allDates.add(month_name1);
    cal.add(Calendar.MONTH, -1);
}
System.out.println(allDates);

output

[Jan-2016, Dec-2015, Nov-2015, Oct-2015, Sep-2015, Aug-2015, Jul-2015, Jun-2015, \
 May-2015, Apr-2015, Mar-2015, Feb-2015]

edit Short explanation what the snippet does.

  1. create a Calendar from the given maxDate and assign it to cal
  2. add the string Mon-Year of the current date in cal to the list allDates
  3. substract one month from the calendar cal.add(Calendar.MONTH, -1)
  4. repeat steps 2. and 3. twelve times

As mentioned by Basil. If you want to process the values in allDates later on as Date / Calendar think about not to generate a list of strings in between.

SubOptimal
  • 22,518
  • 3
  • 53
  • 69
  • Thanks so much! Can you please explain this line, `cal.add(Calendar.MONTH, -1);` I see that you have used `-1` instead of looping `i` ? And also i want Jan-2016 to be included into the ArrayList `allDates`, How can i achieve it? – Disera Mar 07 '16 at 06:55
  • @Disera I amend the snippet and add a short explanation what it does. – SubOptimal Mar 07 '16 at 07:12
  • Thanks a lot for the explanation! – Disera Mar 07 '16 at 07:33
3

ISO 8601

There is a sensible standard for representing date-time values as text: ISO 8601.

So rather than serialize your year-month value as Jan-2016 I strongly suggest you use the standard format, 2016-01. This format is intuitive to read even across languages other than English.

java.time

You are using the troublesome old date-time classes bundled with the earliest versions of Java. As you have learned, among their poor design choices is zero-based month numbers running 0-11.

Sun & Oracle gave up on those old classes, supplanting them with the java.time framework built into Java 8 and later.

YearMonth

Amongst those classes is just what you need: YearMonth. As the name describes, a combination of a year and a month.

Rather than dealing in strings, pass objects of this type instead. You can rely on this class across your code base given that the class is built into Java.

Parse

To parse your non-standard string, define a formatter. Specify a Locale for the human language by which to translate the name of the month.

DateTimeFormatter formatter = formatter.ofPattern( "MMM-yyyy" );
formatter = formatter.withLocale( Locale.US ) ;
YearMonth stop = YearMonth.parse( "Jan-2016" , formatter );

To parse a standard string, no need for a formatter. The java.time classes support parsing/generating ISO 8601 strings by default.

YearMonth stop = YearMonth.parse( "2016-01" );

Date-Time Math

The YearMonth class offers methods for adding and subtracting time.

YearMonth start = stop.minusYears( 1 );

Define a collection of type YearMonth.

List<YearMonth> yearMonths = new ArrayList<>( 12 );

Loop, incrementing a month at a time until we reach the stop month. You asked for the Half-Open approach where the beginning of the span of time is inclusive while the ending is exclusive. This Half-Open approach is common in date-time work.

YearMonth yearMonth = start ;
while ( yearMonth.isBefore( stop ) ) {
    yearMonths.add( yearMonth ) ;  // Add each incremented YearMonth to our collection.
    // Set up next loop.
    yearMonth = yearMonth.plusMonths( 1 );
}
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • 1
    Thanks for the Information! `YearMonth` class is very useful. – Disera Mar 07 '16 at 07:35
  • 1
    Didn't find addMonths method on yearMonth object instance. Instead, found this one in documentation: plusMonths(1). In this case you have to assign the result to iteration variable – Tobet Sep 02 '21 at 13:03
  • 1
    @Tobet Yes, you’re right, I stand corrected. Code fixed now. Thank you. – Basil Bourque Sep 02 '21 at 15:16
0
public static void main(String[] args) {        
    Calendar c = Calendar.getInstance();
    c.setTime(new Date()); //Give Your Date
    c.add(Calendar.MONTH, -12);
    Date fromDate = c.getTime();
    Date toDate = new Date(); //Give Your Date

    System.out.println("from "+fromDate);
    System.out.println(" to "+fromDate);
}

SQL Query:

select * from TABLE where Date between fromDate and toDate;
Leon
  • 2,926
  • 1
  • 25
  • 34
  • 1
    Thanks for wanting to contribute. Not that I can see that you contribute anything towards the question that isn’t already in the other answers. I believe a list of 12 months was asked for. – Ole V.V. Aug 30 '18 at 11:46