user2976522
user2976522

Reputation: 57

Calendar day of month Android

I choose the starting date (example 31/01/2014) and ending date (example 31/12/2014), I insert a record every month. If I get the next month is February 28th, but then I always get 28 though March, April, etc. .. How can I fix? I hope I explained

SimpleDateFormat sdf1 = new SimpleDateFormat( "yyyy-MM-dd" );
ContentValues cv = new ContentValues();

for(
  int i=0; 
  calendar1.getTime().before(calendar2.getTime()); 
  i++
) {
  calendar1.add(Calendar.MONTH, 1);

  if (calendar1.getTime().before(calendar2.getTime())) {
    String strDate = sdf1.format(calendar1.getTime());
    cv.put(etableTable.DATE, strDate);  
    db.insert(etableTable.TABLE_NAME, null, cv);
    ...
  }
}

Upvotes: 1

Views: 2616

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 339342

tl;dr

List < LocalDate > endOfMonths = 
    start
    .datesUntil( end )                  // Returns `Stream` of `LocalDate` objects.
    .map ( YearMonth :: from )          // For each `LocalDate`, produce a `YearMonth`. Returns a `Stream` of `YearMonth` objects.
    .distinct ()                        // Eliminate duplicates.
    .map ( YearMonth :: atEndOfMonth )  // For each `YearMonth`, produce a `LocalDate` that is the last date of that month. Returns a `Stream` of `LocalDate` objects.
    .toList () ;                        // Collect `LocalDate` objects into an unmodifiable `List`. 

Avoid legacy date-time classes

Avoid the terribly-flawed legacy classes such as Date, Calendar, SimpleDateFormat, etc. In modern Java (8+) use only the java.time classes.

YearMonth

If you want to work with specific months, use YearMonth class.

We can easily get all the months of your date range. Start by getting all the dates as LocalDate objects.

LocalDate start = LocalDate.parse ( "2013-01-01" ) ;  // Standard ISO 8601 formatted text.
LocalDate end = LocalDate.parse( "2013-12-31" ) ;
List < LocalDate > datesOfYear = start.datesUntil( end ).toList() ;

For each date, get its year-month. Eliminate duplicates.

List < YearMonth > yearMonths = 
    datesOfYear
    .stream ()
    .map ( YearMonth :: from ) 
    .distinct ()
    .toList () ;

Of course, we could combine those operations.

List < YearMonth > yearMonths = 
    start
    .datesUntil( end )             // Returns `Stream` of `LocalDate` objects.
    .map ( YearMonth :: from )     // For each `LocalDate`, produce a `YearMonth`. Returns a `Stream` of `YearMonth` objects.
    .distinct ()                   // Eliminate duplicates.
    .toList () ;                   // Collect into an unmodifiable `List`. 

Apparently you want the end of each month. So ask each YearMonth object for a LocalDate representing its end-of-month date.

List < LocalDate > endOfMonths = yearMonths.stream ().map ( YearMonth :: atEndOfMonth ).toList () ;

Again, we could combine with operations above.

List < LocalDate > endOfMonths = 
    start
    .datesUntil( end )                  // Returns `Stream` of `LocalDate` objects.
    .map ( YearMonth :: from )          // For each `LocalDate`, produce a `YearMonth`. Returns a `Stream` of `YearMonth` objects.
    .distinct ()                        // Eliminate duplicates.
    .map ( YearMonth :: atEndOfMonth )  // For each `YearMonth`, produce a `LocalDate` that is the last date of that month. Returns a `Stream` of `LocalDate` objects.
    .toList () ;                        // Collect `LocalDate` objects into an unmodifiable `List`. 

Now you have the dates you need to do your database work.

for ( LocalDate endOfMonth : endOfMonths ) 
{
    … 
}

Upvotes: 1

Meno Hochschild
Meno Hochschild

Reputation: 44071

Assuming that you speak about class GregorianCalendar - Instead of calendar1.add(Calendar.MONTH, 1) try to also call following method as work-around:

static GregorianCalendar moveToEndOfMonth(GregorianCalendar gcal) {
  gcal.add(Calendar.MONTH, 1); // moving to some day of next month
  gcal.set(Calendar.DAY_OF_MONTH, 1); // moving to first day of current month
  gcal.add(Calendar.DATE, -1); // moving to last day of previous month
}

So your final code should look like:

calendar1.add(Calendar.MONTH, 1);
moveToEndOfMonth(calendar1);

Why? The analysis of @DavidCAdams is right, see his answer.

Upvotes: 1

David C Adams
David C Adams

Reputation: 1973

Where are you creating the calendar objects? Since you are incrementing the MONTH, and it is January 30, you get February 28 for the next month, since next month only has 28 days in it. There is no Feb 30, 2014. Thereafter, when you increment the month, you get March 28, April 28, etc. etc.

Upvotes: 1

Related Questions